from app import app
if __name__ == "__main__":
app.run()
#!/bin/python
# APP.PY: Flask server to serve html or plain text depending on client's useragent string
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 21/01/2021
# License: MIT License
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "flask",
# "pygments",
# "markdown",
# ]
# ///
#
# Quickrun with uv run app.py
import os
import markdown
import markdown.extensions.fenced_code
import markdown.extensions.codehilite
from flask import Flask, request, make_response, abort
from pygments.formatters import HtmlFormatter
PLAIN_TEXT_AGENTS = [ "curl", "httpie", "lwp-request", "wget", "python-requests", "openbsd ftp", "powershell", "fetch" ]
INDEX_PATH = "./README.md"
app = Flask(__name__)
def to_html(lines):
md = markdown.markdown(lines, extensions=["fenced_code", "codehilite"])
formatter = HtmlFormatter(style="monokai",full=True,cssclass="codehilite")
css = "\nbody { background-color: #33363B; color: #CCCCCC;}\ntd.linenos pre { background-color: #AAAAAA; }"
return "<style>" + formatter.get_style_defs() + css + "</style>" + md
def get_file_path(path, is_man):
if is_man:
if path is None:
return "./man/README.md"
elif os.path.isfile("./man/" + path):
return "./man/" + path
elif os.path.isfile("./man/" + path + ".md"):
return "./man/" + path + ".md"
else:
if path is None:
return INDEX_PATH
elif os.path.isfile("./" + path):
return "./" + path
elif os.path.isfile("./" + path + ".sh"):
return "./" + path + ".sh"
return None
def try_get_lines(file_path):
if file_path is None:
return ""
with open(file_path) as f:
lines = f.read()
return lines
def get_content(path, request, is_man, is_raw):
file_path = get_file_path(path, is_man)
lines = try_get_lines(file_path)
user_agent = request.headers.get('User-Agent', '').lower()
if any([x in user_agent for x in PLAIN_TEXT_AGENTS]):
return "Error: file not found" if file_path is None else lines
if file_path is None:
abort(404)
if is_raw:
resp = make_response(lines)
resp.mimetype = 'text/plain'
return resp
if file_path == INDEX_PATH or is_man:
return to_html(lines)
#This must be the base url so display the man above the file
man_path = get_file_path(path, True)
man_lines = try_get_lines(man_path)
return to_html(man_lines + "\n##CODE:\n```\n" + lines + "\n```")
@app.route("/")
@app.route("/<path>")
def get_file(path=None):
return get_content(path, request, False, False)
@app.route("/man/<path>")
def get_man(path=None):
return get_content(path, request, True, False)
@app.route("/raw/<path>")
def get_raw(path=None):
return get_content(path, request, False, True)
@app.route("/raw/man/<path>")
def get_raw_man(path=None):
return get_content(path, request, True, True)
if __name__ == '__main__':
app.run(host='0.0.0.0')
# Try to append domain name to an ip in the hosts file.
# Does not append if it's already bound.
hosts_append_missing() {
IP="$1"
HOSTNAMES="$2"
HOSTS_FILE="/etc/hosts"
echo -e "Trying to bind the following domains to $IP\n\n$HOSTNAMES\n"
# Print nice output
for HNAME in $LOCAL_HOSTNAMES; do
if grep -q "^$IP.*$HNAME" $HOSTS_FILE; then
echo -e "$HNAME,is already bound to $IP"
else
echo -e "$HNAME,is not bound to $IP"
fi
done | column -t -s,
APPEND_LIST=$(
for HNAME in $LOCAL_HOSTNAMES; do
grep -q "^$IP.*$HNAME" $HOSTS_FILE || printf " %s" "$HNAME"
done
)
if [ -z "$APPEND_LIST" ]; then
echo -e "\nAll domains already bound."
else
echo -e "\nBinding the following hostnames to $IP\n$APPEND_LIST\n"
sudo sed -i "s/^\($IP.*\)/\1$APPEND_LIST/" $HOSTS_FILE
fi
}
#!/bin/sh
# BM: Bookmarks
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 17/10/2020
# License: GPL v3
add() { read -p "Enter key: " key; read -p "Enter value: " val; echo "$key~|~$val" >> $1; }
delete() {
if [ -z $2 ]; then
sed -i $(cat -n $1 | fzy | sed "s/\(\s*[0-9]*\).*/\1dq/") $1
else
idx=$(grep -n "$1~|~.*" $2 | head -n1 | sed "s/^\([0-9]*\):.*/\1/")
sed -i "${idx}d" $2
fi
}
get() { sed -n "s/^$1~|~\(.*\)/\1/p" $2 | head -n1; }
readval() { cat "$1" | fzy | sed "s/.*~|~//"; }
if [ ! -f "$HOME/.config/bookmarks/" ]; then
mkdir -p "$HOME/.config";
mkdir -p "$HOME/.config/bookmarks/";
fi
if [ -z $1 ]; then readval $(ls $HOME/.config/bookmarks/*.bm | fzy);
elif [ "$1" = "add" ]; then add "$HOME/.config/bookmarks/$2.bm";
elif [ "$1" = "rm" ]; then delete "$2" "$HOME/.config/bookmarks/$3.bm";
elif [ "$1" = "get" ]; then get "$2" "$HOME/.config/bookmarks/$3.bm";
elif [ "$1" = "list" ]; then cat "$HOME/.config/bookmarks/$2.bm" | sed "s/~|~/\t/" | column -ts $'\t';
else readval "$HOME/.config/bookmarks/$1.bm";
fi
#!/bin/sh
# CB: cd bookmarks
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 31/08/2021
# License: GPL v3
cb() {
#TODO Prompt for missing args
if [ ! -f "$HOME/.config/bookmarks/dirs.bm" ]; then
mkdir -p "$HOME/.config";
mkdir -p "$HOME/.config/bookmarks/";
touch "$HOME/.config/bookmarks/dirs.bm";
fi
[ -z $1 ] && bm list dirs
case "$1" in
add) echo -e "$2\n$(pwd)" | bm add dirs;;
rm) bm rm "$2" dirs;;
ls) bm list dirs;;
reload) source "$NREPOS/n0s1.core/cb";;
*) cd $(bm get "$1" dirs);;
esac
}
#!/bin/sh
# EF: Edit bookmarked files
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 31/08/2021
# License: GPL v3
ef() {
#TODO Prompt for missing args
case "$1" in
add) echo -e "$2\n$(pwd)/$3" | bm add editfiles;;
rm) bm rm "$2" editfiles;;
list) bm list editfiles;;
reload) source "$NREPOS/n0s1.core/ef" && echo "Reloaded ef";;
*) vim $(bm get "$1" editfiles);;
esac
}
#!/usr/bin/env bash
set -eEuCo pipefail
declare -r file=$1
declare -i -r line=$2
declare -i -r lines=$LINES
# subtract 3 for the header
declare -i center=$(( (lines - 3) / 2 ))
if [ $line -lt $center ]; then
center=$line
fi
declare -i -r start=$(( line - center ))
declare -i -r end=$(( lines + start ))
exec bat --color always --highlight-line $line --line-range $start:$end --paging never "$file"
#!/bin/bash
# ask: Promts the user to answer a yes/no question.
# Returns after a single char is entered without hitting return.
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:29:17 AEST
# License: GPL v3
ask() {
while true; do
read -p "${1} ${yellow}y/n${reset} " -sn1
echo
[[ $REPLY =~ ^[Yy]$ ]] && return 0
[[ $REPLY =~ ^[Nn]$ ]] && return 1
done
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || ask $@
#!/bin/sh
#AWKP: awk print colums
#Author: Nan0Scho1ar (Christopher Mackinga)
#License: GPLv3
#Description: simplify printing specifig colums using awk
if [[ $# -eq 0 ]]; then
column -t
else
awk "{print $(echo "\$$@" | sed 's/ /"\t"$/g')}" | column -t
fi
#!/bin/sh
# CHECK_ROOT: Throws an error if the current user is not root
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 07/11/2020
# License: GPL v3
check_root () { [[ $EUID - 0 ]] && echo "Error this must be run as root" && return 1; }
green=`tput setaf 2`
red=`tput setaf 1`
yellow=`tput setaf 3`
blue=`tput setaf 4`
magenta=`tput setaf 5`
cyan=`tput setaf 6`
white=`tput setaf 7`
blink=`tput blink`
reset=`tput sgr0`
#!/bin/sh
md_to_confluence() {
FILE="$1"
# Delete anchors
sed -i '/<a id="org.*">/d' "$FILE"
# Fix links
sed -i 's/\(.*\)\[\(.*\)\](#org.*)/\1[\2](#\2)/' "$FILE"
for i in $(seq 100); do
sed -i 's/\(.*\[.*](.*\) \(.*\)/\1-\2/g' "$FILE"
done
# Fix underscores
sed -i 's/<sub>/_/g;s/<\/sub>//g' "$FILE"
}
#!/bin/sh
# DISCORD_WEBHOOKS: Tool for managing and messaging using discord webhooks
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 17/10/2020
# License: GPL v3
save() { read -p "Enter $1: " r1; read -p "Enter $2: " r2; echo "$r1|$r2" >> $3; }
delete() { sed -i $(cat -n $1 | fzf --with-nth 2.. | awk '{print $1"d"}') $1; }
mkdir -p ~/.config/discordwebhooks/;
if [ -z $1 ]; then
IFS='|' read -r username avatar_url <<< $(cat $HOME/.config/discordwebhooks/users.bm | fzf)
IFS='|' read -r channel_name webhook_url <<< $(cat $HOME/.config/discordwebhooks/channels.bm | fzf)
echo "Enter message to post in $channel_name:"
while true; do
read -p "> " msg || exit 1
data="{\"username\": \"$username\", \"avatar_url\": \"$avatar_url\", \"content\": \"$msg\" }"
curl -X POST -H "Content-Type: application/json" -d "$data" $webhook_url
done
elif [ "$1" = "adduser" ]; then save "username" "avatar url" "$HOME/.config/discordwebhooks/users.bm";
elif [ "$1" = "addchannel" ]; then save "channel name" "webhook url" "$HOME/.config/discordwebhooks/channels.bm";
elif [ "$1" = "deleteuser" ]; then delete "$HOME/.config/discordwebhooks/users.bm";
elif [ "$1" = "deletechannel" ]; then delete "$HOME/.config/discordwebhooks/channels.bm";
fi
#!/bin/bash
# Extract an archive
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xjf $1 ;;
*.tar.gz) tar xzf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xf $1 ;;
*.tbz2) tar xjf $1 ;;
*.tgz) tar xzf $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1;;
*.7z) 7z x $1 ;;
*) echo "'$1' cannot be extracted via extract" ;;
esac
else
echo "'$1' is not a valid file"
fi
#!/bin/bash
# create a header or an oeg file to be exported to html
title="$1"
export_fname="$2"
git_url="$3"
if echo "$git_url" | grep -q "github\.com"; then
commit="commit"
viewlink="#+begin_export html
<a href=\"${git_url}\"
style=\"font-family: 'Open Sans'; background-image: none; color: inherit;
text-decoration: none; position: relative; top: clamp(-26px, calc(1280px - 100vw), 0px); opacity: 0.7;\">
<img src=\"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIxMDI0IiB2aWV3Qm94PSIwIDAgMTAyNCAxMDI0IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTggMEMzLjU4IDAgMCAzLjU4IDAgOEMwIDExLjU0IDIuMjkgMTQuNTMgNS40NyAxNS41OUM1Ljg3IDE1LjY2IDYuMDIgMTUuNDIgNi4wMiAxNS4yMUM2LjAyIDE1LjAyIDYuMDEgMTQuMzkgNi4wMSAxMy43MkM0IDE0LjA5IDMuNDggMTMuMjMgMy4zMiAxMi43OEMzLjIzIDEyLjU1IDIuODQgMTEuODQgMi41IDExLjY1QzIuMjIgMTEuNSAxLjgyIDExLjEzIDIuNDkgMTEuMTJDMy4xMiAxMS4xMSAzLjU3IDExLjcgMy43MiAxMS45NEM0LjQ0IDEzLjE1IDUuNTkgMTIuODEgNi4wNSAxMi42QzYuMTIgMTIuMDggNi4zMyAxMS43MyA2LjU2IDExLjUzQzQuNzggMTEuMzMgMi45MiAxMC42NCAyLjkyIDcuNThDMi45MiA2LjcxIDMuMjMgNS45OSAzLjc0IDUuNDNDMy42NiA1LjIzIDMuMzggNC40MSAzLjgyIDMuMzFDMy44MiAzLjMxIDQuNDkgMy4xIDYuMDIgNC4xM0M2LjY2IDMuOTUgNy4zNCAzLjg2IDguMDIgMy44NkM4LjcgMy44NiA5LjM4IDMuOTUgMTAuMDIgNC4xM0MxMS41NSAzLjA5IDEyLjIyIDMuMzEgMTIuMjIgMy4zMUMxMi42NiA0LjQxIDEyLjM4IDUuMjMgMTIuMyA1LjQzQzEyLjgxIDUuOTkgMTMuMTIgNi43IDEzLjEyIDcuNThDMTMuMTIgMTAuNjUgMTEuMjUgMTEuMzMgOS40NyAxMS41M0M5Ljc2IDExLjc4IDEwLjAxIDEyLjI2IDEwLjAxIDEzLjAxQzEwLjAxIDE0LjA4IDEwIDE0Ljk0IDEwIDE1LjIxQzEwIDE1LjQyIDEwLjE1IDE1LjY3IDEwLjU1IDE1LjU5QzEzLjcxIDE0LjUzIDE2IDExLjUzIDE2IDhDMTYgMy41OCAxMi40MiAwIDggMFoiIHRyYW5zZm9ybT0ic2NhbGUoNjQpIiBmaWxsPSIjMUIxRjIzIi8+Cjwvc3ZnPgo=\"
class=\"invertible\" alt=\"GitHub Octicon\"
style=\"height: 1em; position: relative; top: 0.1em;\">
View on GitHub</a> 
#+end_export"
else
commit="commits"
viewlink="#+begin_export html
<a href=\"${git_url}\"
style=\"font-family: 'Open Sans'; background-image: none; color: inherit;
text-decoration: none; position: relative; top: clamp(-26px, calc(1280px - 100vw), 0px); opacity: 0.7;\">
<img src=\"data:image/vnd.microsoft.icon;base64,AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAAAABgAAAAAQAgAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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Jv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4QmmwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmBP+EJq7/hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qmvf+EJgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmEf+EJs3/hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm2f+EJhkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmJv+EJuX/hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm7f+EJjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmQv+EJvb/hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm+v+EJk8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmY/+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJnMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmiP+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJpcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/hCYB/4Qmo/+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJv//hCb//4Qm//+EJrH/hCYFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmVv+EJsb/hCbN/4Qmzf+EJs3/hCbN/4Qmzf+EJs3/hCbN/4Qmzf+EJs3/hCbN/4Qmzf+EJs3/hCbM/4Qmx/+EJsb/hCbG/4Qmxv+EJsb/hCbG/4Qmxv+EJsb/hCbG/4Qmxv+EJsb/hCbG/4Qmxv+EJsb/hCbG/4Qmxv+EJsb/hCbG/4Qmxv+EJsb/hCbG/4QmxP+EJmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4QmAf+EJg3/hCYR/4QmEf+EJhH/hCYR/4QmEf+EJhH/hCYR/4QmEf+EJhH/hCYR/4QmEf+EJhH/hCYQ/4QmDf+EJg3/hCYN/4QmDf+EJg3/hCYN/4QmDf+EJg3/hCYN/4QmDf+EJg3/hCYN/4QmDf+EJg3/hCYN/4QmDf+EJg3/hCYN/4QmDf+EJg3/hCYN/4QmC/+EJgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////wAA////////AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA/+AAAAf/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAP/AAD/wAAAA/8AAP/AAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+AAAAB/wAA/4AAAAH/AAD/gAAAAf8AAP+AAAAB/wAA/4AP8AD/AAD/AA/wAP8AAP8AD/AA/wAA/wAf+AD/AAD/AB/4AP8AAP8AH/gA/wAA/wAf+AB/AAD+AB/4AH8AAP4AP/gAfwAA/gA//AB/AAD+AB/4AH8AAP4AAAAAfwAA/gAAAAB/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/AAD8AAAAAD8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAB8AAPgAAAAAHwAA/AAAAAA/AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////AAD///////8AACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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\"
class=\"invertible\" alt=\"Bitbucket icon\"
style=\"height: 1em; position: relative; top: 0.1em;\">
View on Bitbucket</a> 
#+end_export"
fi
echo "#+TITLE: ${title}
#+STARTUP: inlineimages
#+LANGUAGE: en
#+EXPORT_FILE_NAME: ${export_fname}
#+date: @@html:<!--@@{{{git-rev}}}@@html:-->@@@@latex:\\\\\\Large\bfseries@@ {{{modification-time(%Y-%m-%d, t)}}} @@latex:\\\\\\normalsize\mdseries@@{{{modification-time(%H:%M, t)}}} @@latex:\acr{\lowercase{@@{{{timezone}}}@@latex:}}\iffalse@@, {{{git-rev}}}@@latex:\fi@@
#+macro: timezone (eval (substring (shell-command-to-string \"date +%Z\") 0 -1))
#+macro: git-rev (eval (format \"@@html:<a href=\\\"${git_url}/${commit}/%1\$s\\\" style=\\\"text-decoration: none\\\"><code style=\\\"padding: 0; color: var(--text-light); font-size: inherit; opacity: 0.7\\\">%1\$s</code></a>@@@@latex:\\\\href{${git_url}/${commit}/%1\$s}{\\\\normalsize\\\\texttt{%1\$s}}@@\" (substring (shell-command-to-string \"git rev-parse --short HEAD\") 0 -1)))
#+HTML_HEAD:
${viewlink}"
#!/bin/bash
# mkpath: build a path variable using a dir and all sub dirs
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Wed 17 Nov 2021 16:32:14 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
find "$1" -type d | grep -v "\.git" | tr '\n' ':' | sed "s/:$//"
#!/bin/bash
# exprx: syntactic sugar for expr to test if regex matches
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Fri 17 Sep 2021 14:48:03 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
exprq() { expr "$1" : "$2" 1>/dev/null; }
#!/bin/bash
# FZY: Command Line Fuzzy Finder
# Created: 29/10/2020
# Author: Nan0Scho1ar (Christopher Mackinga)
# License: GPL v3
hideinput() { [ -t 0 ] && save_state=$(stty -g) && stty -echo -icanon time 0 min 0 && echo -ne "\e[?1049h\r" 1>&2; }
cleanup() { [ -t 0 ] && stty "$save_state" < /dev/tty && echo -ne "\e[?1049l" 1>&2 && echo "$result"; }
trap 'cleanup < /dev/tty' < /dev/tty EXIT
trap 'hideinput < /dev/tty' CONT
hideinput < /dev/tty
input="$(< /dev/stdin)";
height="$(tput lines)";
inum=$(echo "$input" | wc -l);
fnum=$inum;
clearline=$(echo -e "\033[2K")
valid='0-9a-zA-Z '
str=""; regex=""; regex2=""; result="";
row=1; col=1; cur=1; scrolling=1;
while true;
do
range="$row,$((row+height-3))p;$((row+height-3))q";
filtered=$(echo "$input" | grep ".*$regex" | sed -n $range 2>/dev/null | sed -e "s/^.*/ &/");
frange="$(echo "$filtered" | wc -l)";
curpos=$((frange-cur+1));
echo "$filtered" | cut -c$col- | grep -E --color=always "$regex2" | tac | sed -e $curpos"s/^ \(.*\)/> \1/;s/^.*/$clearline&/" 1>&2;
echo "$clearline $fnum/$inum" 1>&2;
tput cnorm
[ $scrolling = 1 ] && read -r -sn200 -t 0.0001 junk < /dev/tty;
read -r -p "$clearline> $str" -sn1 < /dev/tty;
read -r -sn3 -t 0.001 k1 < /dev/tty;
REPLY+=$k1;
case "$REPLY" in
'')
result=$(echo "$filtered" | sed -n "${cur}s/ //p;${cur}q");
exit;
;;
$'\e[C'|$'\e0C') col=$((col+1)) && scrolling=1 ;;
$'\e[D'|$'\e0D') [[ $col -gt 1 ]] && col=$((col-1)) && scrolling=1 ;;
$'\e[B'|$'\e0B') [[ $cur -ge 1 ]] && cur=$((cur-1)) && scrolling=1 ;;
$'\e[A'|$'\e0A') [[ $cur -le $fnum ]] && cur=$((cur+1)) && scrolling=1 ;;
$'\e[1~'|$'\e0H'|$'\e[H') row=1 ;;
$'\e[4~'|$'\e0F'|$'\e[F') row=$fnum ;;
*)
char=$(echo "$REPLY" | hexdump -c | tr -d '[:space:]');
if [[ $char = "0000000033\n0000002" ]]; then
exit 1;
elif [[ $char = "0000000177\n0000002" ]] && [[ ${#str} -gt 0 ]]; then
str="${str::-1}";
scrolling=1;
else
filtchar=$(echo "$REPLY" | hexdump -c | awk '{ print $2 }')
result="$filtchar"
if [[ "$filtchar" != "033" ]] && [[ "$filtchar" != "177" ]] && [[ ! "$REPLY" =~ [^$valid] ]]; then
str="$str$REPLY" && row=1;
scrolling=0;
fi
fi
regex=$(echo "$str" | sed "s/\(.\)/\1.*/g");
regex2=$(echo "$str" | sed "s/\(.\)/\1|/g");
fnum=$(echo "$input" | grep -c ".*$regex");
;;
esac
[[ $((frange-cur+1)) -lt 1 ]] && row=$((row+1)) && cur=$((cur-1));
[[ $cur -lt 1 ]] && row=$((row-1)) && cur=$((cur+1));
[[ $cur -gt $fnum ]] && cur=$fnum;
[[ $((row-fnum+frange)) -gt 1 ]] && row=$((row-1));
[[ $row -lt 1 ]] && row=1;
tput civis
tput cup 0 0
[[ $fnum -lt $height ]] && yes "$clearline" | sed "$((height-fnum-2))q" 1>&2;
done
#!/bin/sh
# FZY_Lite: 10 SLOC Command Line Fuzzy Finder
# Copyright: Nan0Scho1ar (Christopher Mackinga) MIT License (29/10/2020)
fzy_lite() {
str=""; input="$(< /dev/stdin)"; echo -e "\e[?1049h"; while true; do
filtered=$(echo "$input" | grep ".*$(echo "$str" | sed "s/\(.\)/\1.*/g")");
echo "$filtered"; read -p "> $str" -n 1 -s < /dev/tty;
char=$(echo $REPLY | hexdump -c | awk '{ print $2 }');
[[ $char = "\n" ]] && echo -e "\e[?1049l$filtered" && return 0
[[ $char = "177" ]] && [[ $str = "" ]] && echo -e "\e[?1049l" && return 1
[[ $char = "177" ]] && str="${str::-1}" || str="$str$REPLY";
yes '' | sed "$(tput lines)q"; done
}
#!/bin/sh
# LESS: The hackable less
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 30/10/2020
# License: MIT License
hackless() {
lines="$(cat "$1" || cat /dev/stdin)"
row=1 && col=1 && regex="" &&
height="$(tput lines)" && cols=$(tput cols) &&
numln="$(echo "$lines" | wc -l)" &&
maxlen=$(echo "$lines" | awk '{ print length }' | sort -n | tail -1) &&
lastln="$([[ $numln -ge $height ]] && echo $((numln-height+2)) || echo 1)" &&
lastcol="$([[ $maxlen -ge $cols ]] && echo $((maxlen-cols+4)) || echo 1)" &&
lines="$lines$(echo; yes '~' | sed -n "1,${cols}p;${cols}q")" &&
echo -e "\e[?1049h" || return 1
while true; do
echo "$lines" | sed -n "$row,$((row+height-2))p;$((row+height-2))q" \
| cut -c $col-$((col+cols-1)) | grep --colour=always "^\|$regex";
[[ $row -eq $lastln ]] && cur="$(tput rev)END$(tput sgr0)" || cur=":"
read -rsn1 -p "$cur" < /dev/tty char && echo -e "$(tput el1)\r"
case $char in
'q') echo -e "\e[?1049l" && return;;
'k') [[ $row -gt 1 ]] && row=$((row-1));;
'j') [[ $row -lt $lastln ]] && row=$((row+1));;
'h') [[ $col -gt 1 ]] && col=$((col-1));;
'l') col=$((col+1));;
'g') row=1;;
'G') row=$lastln;;
'0') col=1;;
'$') col=$lastcol;;
'/') read -p "/" < /dev/tty regex;;
esac
done
}
#!/bin/sh
# USELESS: less but less code. Seriously, just use less.
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 30/10/2020
# License: MIT License
# 20 line pager. Not very useful in its current form but easily extended
useless() {
lines="$(cat "$1" || cat /dev/stdin)"
numlines="$(echo "$lines" | wc -l)" && height="$(tput lines)" && \
echo -e "\e[?1049h" && row=1 && col=1 && regex="" || return 1
while true; do
echo "$lines" | sed -n "$row,$((row+height-2))p;$((row+height-2))q"\
| cut -c $col- | grep --colour=always "^\|$regex";
read -rsn1 -p ":" < /dev/tty char && echo -e "$(tput el1)\r"
case $char in
'q') echo -e "\e[?1049l" && return;;
'k') [[ $row -gt 1 ]] && row=$((row-1));;
'j') [[ $row -lt $numlines ]] && row=$((row+1));;
'h') [[ $col -gt 1 ]] && col=$((col-1));;
'l') col=$((col+1));;
'g') row=1;;
'G') row=$numlines;;
'/') read -p "/" < /dev/tty regex;;
esac
done
}
permanent history using bm
#!/bin/sh
# HIST: Shell history made easy
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 06/11/2020
# License: GPL v3
[ $SHELL = "/bin/zsh" ] &&
histfile="$XDG_CONFIG_HOME/zsh/.zhistory" ||
histfile="$HOME/.history"
sep="; "
cmdlist="$1"
if [ -z "$1" ]; then
cat --number "$histfile" | less
exit
elif [ "$1" = '-a' ]; then
sep=" && "
cmdlist="$2"
elif [[ "$1" =~ "-h|--help" ]]; then
echo "hist list history"
echo "hist 50..55 run cmd list ; seperated"
echo "hist -a 50..55 run cmd list && seperated"
exit
fi
# 50..55
if [[ $cmdlist =~ ^[0-9]+\.\.[0-9]+$ ]]; then
START="$(echo $cmdlist | sed 's/^\([0-9]*\)\.\.\([0-9]*\)$/\1/')"
END="$(echo $cmdlist | sed 's/^\([0-9]*\)\.\.\([0-9]*\)$/\2/')"
final=""
for i in $(eval echo "{$START..$END}"); do
cmd=$(cat --number $histfile | sed -n "s/^\s*${i}\t\(.*\)/\1/p")
[ -z "$final" ] && final="$cmd" || final="$final$sep$cmd"
done
echo "$final"
eval "$final"
fi
#!/bin/bash
hideinput()
{
if [ -t 0 ]; then
save_state=$(stty -g)
stty -echo -icanon time 0 min 0
echo -ne "\e[?1049h\r" 1>&2;
fi
}
cleanup()
{
if [ -t 0 ]; then
stty "$save_state" < /dev/tty
echo -ne "\e[?1049l" 1>&2;
echo "$result"
fi
}
trap 'cleanup < /dev/tty' < /dev/tty EXIT
trap 'hideinput < /dev/tty' CONT
hideinput < /dev/tty
while true
do
read -r -sn1000 -t 0.001 junk < /dev/tty;
read -r -sn1 < /dev/tty;
read -r -sn3 -t 0.001 k1 < /dev/tty;
REPLY+=$k1;
case "$REPLY" in
'')
echo "Enter pressed"
;;
$'\e[C'|$'\e0C') echo "Right arrow pressed";;
$'\e[D'|$'\e0D') echo "Left arrow pressed";;
$'\e[B'|$'\e0B') echo "Down arrow pressed";;
$'\e[A'|$'\e0A') echo "Up arrow pressed";;
$'\e[1~'|$'\e0H'|$'\e[H') echo "Home pressed";;
$'\e[4~'|$'\e0F'|$'\e[F') echo "End pressed";;
*)
char=$(echo "$REPLY" | hexdump -c | tr -d '[:space:]');
if [[ $char = "0000000033\n0000002" ]]; then
echo "Escape pressed"
exit;
elif [[ $char = "0000000177\n0000002" ]] && [[ ${#str} -gt 0 ]]; then
echo "Backspace pressed"
else
filtchar=$(echo "$REPLY" | hexdump -c | awk '{ print $2 }')
result="$filtchar"
if [[ "$filtchar" != "033" ]] && [[ "$filtchar" != "177" ]] && [[ ! "$REPLY" =~ [^$valid] ]]; then
echo "$REPLY pressed"
fi
fi
;;
esac
sleep 0.1
done
#!/bin/bash
# mkexecdir: Make all files in current directory which begin with a shebang executable
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Wed 17 Nov 2021 15:06:27 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
green=`tput setaf 2`
reset=`tput sgr0`
while IFS= read -r fname; do
head="$(head -n1 "$fname")"
if [[ $head =~ ^#! ]]; then
echo -e "$green$fname$reset:\t$head"
chmod +x "$fname"
fi
done < <(ls -F | grep -v "/$") | column -ts $'\t'
use fd if available find -maxdepth 1 -type f fd -d1 -tf
#!/bin/bash
# mkpath: build a path variable using a dir and all sub dirs
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Wed 17 Nov 2021 16:32:14 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
find "$1" -type d | grep -v "\.git" | tr '\n' ':' | sed "s/:$//"
#!/bin/bash
green=`tput setaf 2`
red=`tput setaf 1`
yellow=`tput setaf 3`
blue=`tput setaf 4`
magenta=`tput setaf 5`
cyan=`tput setaf 6`
white=`tput setaf 7`
blink=`tput blink`
reset=`tput sgr0`
nan0S() {
echo ' ___ ____ '
echo ' _ __ __ _ _ __ / _ \/ ___| '
echo '| `_ \ / _` | `_ \| | | \___ \ '
echo '| | | | (_| | | | | |_| |___) |'
echo '|_| |_|\__,_|_| |_|\___/|____/ '
}
n0s1_tiny() {
echo ' /\ /\ '
echo ' //\\ //\\ '
echo ' // \V/ \\ '
echo ' // /A\ \\ '
echo '//----/_\____\\'
echo '/-------------\'
}
n0s1() {
echo ' /\ /\ '
echo ' / \ / \ '
echo ' / /\ \ / /\ \ '
echo ' / / \ X / \ \ '
echo ' / / X X \ \ '
echo ' / / / X \ \ \ '
echo ' / / /_/_\_\ \ \ '
echo '/_/______/___\ \ \ '
echo ' / /____________\_\'
echo '/_____________________\ '
}
n0s1_large() {
echo ' /\ /\ '
echo ' / \ / \ '
echo ' / \ / \ '
echo ' / \ / \ '
echo ' / /\ \ / /\ \ '
echo ' / / \ \ / / \ \ '
echo ' / / \ X / \ \ '
echo ' / / \ / \ / \ \ '
echo ' / / X X \ \ '
echo ' / / / \ / \ \ \ '
echo ' / / / X \ \ \ '
echo ' / / / / \ \ \ \ '
echo ' / / /___/___\___\ \ \ '
echo ' / / / \ \ \ '
echo '/___/____________/_______\ \ \ '
echo ' / / \ \ '
echo ' / /________________________\___\'
echo ' / \ '
echo '/_________________________________________\ '
}
usegreen=0
centered=0
large=0
banner=0
while getopts "gclb" OPT; do
if [ "$OPT" = "-" ]; then # long option: reformulate OPT and OPTARG
OPT="${OPTARG%%=*}" # extract long option name
OPTARG="${OPTARG#$OPT}" # extract long option argument (may be empty)
OPTARG="${OPTARG#=}" # if long option argument, remove assigning `=`
fi
case "$OPT" in
g) usegreen=1 ;;
c) centered=1 ;;
l) large=1 ;;
b) banner=1 ;;
??*) die "Illegal option --$OPT" ;; # bad long option
?) exit 2 ;; # bad short option (error reported via getopts)
esac
done
shift $((OPTIND-1)) # remove parsed options and args from $@ list
if [ $large = 1 ]; then
text="$(n0s1_large)"
else
text="$(n0s1)"
fi
if [ $usegreen = 1 ]; then
text="${green}
${text}
${reset}"
fi
if [ $banner = 1 ]; then
text="${text}
$(nan0S)"
fi
if [ $centered = 1 ]; then
echo "${text}" | center
else
echo "${text}"
fi
#!/bin/bash
#n0s1m: n0s1 menu
# Bish
#!/bin/bash
# Ingest a directory full of files to tangled script blocks in a org file.
dir="$([ -z $1 ] && pwd || echo $1)"
while IFS= read -r fname; do
echo "* $fname"
head="$(head -n1 "$fname")"
if [[ $head =~ ^#! ]]; then
echo "#+begin_src sh :tangle out/$fname :tangle-mode (identity #o755)"
else
echo "#+begin_src sh :tangle out/$fname"
fi
cat "$fname"
echo "#+end_src"
echo
done < <(ls -p "$dir" | grep -v /)
#!/bin/bash
#AUTHOR: Nan0Scho1ar
#License: GPL v3
#Script for running nested tmux sessions
#Calls recursively to add additional information
case $1 in
sys)
toomuxh system $HOME/repos/me/dotfiles/tmux/sys.sh $2
;;
local)
TMUX= ;
toomuxh $HOSTNAME $HOME/repos/me/dotfiles/tmux/local.sh $2
;;
cluster)
TMUX= ;
toomuxh ${HOSTNAME}_C $HOME/repos/me/dotfiles/tmux/cluster.sh $2
;;
*)
SESSION="$1"
CONFIG="$2"
case $3 in
q|quit|Q|QUIT|Quit|exit|Exit)
if tmux has-session -t $SESSION 2>/dev/null; then
tmux kill-session -t $SESSION 2>/dev/null &&
echo "Killed tmux session '$SESSION'" ||
echo "Failed to kill tmux session '$SESSION'"
else
echo "Tmux session '$SESSION' does not exist"
fi
exit
;;
*)
echo "SESSION=$SESSION"
echo "CONFIG=$CONFIG"
if tmux has-session -t $SESSION 2>/dev/null; then
tmux -2 attach-session -t $SESSION 2>/dev/null ||
echo "Failed to attach tmux session '$SESSION'"
else
tmux -2 new-session -d -s $SESSION $CONFIG
tmux -2 attach-session -t $SESSION
fi
;;
esac
;;
esac
#!/bin/bash
# READ_TOML: One line script to read from a toml file
# Author: Nan0Scho1ar
# Created: 11/1/2021
# License: MIT License
# TODO support multiline values
# TODO support dotted notation (dotted headers/parent already work)
# TODO apologize to my future self or anyone who has to maintin this
sed -n "s/#.*//g;$([[ $1 =~ \. ]] && echo "/^\s*\[`sed 's/\..*//' <<< $1`\]/" || echo 0),/\^\s*[.*\]/!d;s/^\s*\"*`sed 's/.*\.//' <<< $1`\"*\s*=\s*//p" <<< $(cat $2 || cat /dev/stdin)
#Super Minimal version which doesn't strip comments before processing and can't handle malformed whitespace
#cat $2 | sed -n "$([[ $1 =~ \. ]] && echo "/^\[`sed 's/\..*//' <<< $1`\]/" || echo 0),/\^[.*\]/!d;s/^\s*\"*`sed 's/.*\.//' <<< $1`\"*\s=\s//p"
#Explainer
#parent="$(sed 's/\..*//' <<< "$1")"
#key="$(sed 's/.*\.\//' <<< "$1")"
#begin="$([[ $1 =~ \. ]] && echo "/^\s*\[$parent\]/" || echo 0)"
##Remove comments from file; Filter to section; Return value
#sed -n "s/#.*//g;$begin,/^\s*\[.*\]/!d;s/^\s*\"*$key\"*\s*=\s*//p" <<< $(cat $2 || cat /dev/stdin)
# This is a TOML document
title = "TOML Example"
"quoted" = "Quoted Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00
[database]
enabled = true
ports = [ 8001, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }
[servers]
[servers.alpha]
ip = "10.0.0.1"
role = "frontend"
[servers.beta]
ip = "10.0.0.2"
role = "backend"
#!/bin/bash
# TOML: Simple get commands to read toml files
# (Not all featues supported)
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 27/10/2020
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
toml() {
flatten() {
comment_regex="^\s*#"
header_regex="\s*\[.*\]"
value_regex="\s*.*=.*"
extract_header="s/\[//g; s/\]//g; s/ //g; s/\t//g; s/\n//g"
extract_value="s/^\s*//; s/\t//g; s/\n//; s/ =/=/; s/= /=/"
parent=""
while IFS= read -r line; do
if [[ $line =~ $comment_regex ]]; then
continue
elif [[ $line =~ $header_regex ]]; then
parent=$(sed "$extract_header" <<< "$line")
elif [[ $line =~ $value_regex ]]; then
if [ -z $parent ]; then
sed "$extract_value" <<< "$line"
else
echo "$parent.$(sed "$extract_value" <<< "$line")"
fi
fi
done < /dev/stdin
}
#Returns the first value which matches the header
get_value() {
match="$1=.*"
while IFS= read -r line; do
if [[ $line =~ $match ]]; then
sed "s/^.*=//" <<< "$line" | tr -d '"'
break
fi
done < <(cat /dev/stdin | flatten)
}
# Returns all headers and values matching the input
get() {
match="^$1.*"
while IFS= read -r line; do
if [[ $line =~ $match ]]; then
echo "$line"
fi
done < <(cat /dev/stdin | flatten)
}
case "$1" in
"get") cat /dev/stdin | get "$2" ;;
"get_value") cat /dev/stdin | get_value "$2" ;;
"-V") echo "toml: version 0.7.1" ;;
*) echo "Error: Unknown option";;
esac
}
#!/usr/bin/env python3
# toml.py: Read values from a toml file
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Fri 17 Sep 2021 14:48:03 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import re
def flatten(lines):
flat = []
for line in lines:
if re.match("^\s*#", line):
continue
elif re.match("\s*\[.*\]", line):
parent = line.replace("[", "").replace("]", "").replace(" ", "").replace("\t", "").replace("\n", "")
elif re.match("\s*.*=.*", line):
flat.append(parent + "." + re.sub("^\s*", "", line).replace("\t", "").replace("\n", "").replace(" =", "=").replace("= ", "="))
return flat
# TODO support multiline arrays
# Returns first match
def get(key):
flat = flatten(sys.stdin)
for line in flat:
if key + "=" in line:
result = re.sub(".*=", "", line)
return result[1:-1] if re.match("^\".*\"$", result) else result
def get_headers(key):
flat = flatten(sys.stdin)
matches = []
for line in flat:
if key == line[:len(key)]:
matches.append(line)
return matches
if sys.argv[1] == "get":
print(get(sys.argv[2]))
elif sys.argv[1] == "get_headers":
for match in get_headers(sys.argv[2]):
print(match)
#!/bin/bash
# sexec: Source and execute a shell function from a file
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Wed 17 Nov 2021 18:24:40 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
source "$1"
cmd="$1"
shift
$cmd $@
#!/bin/sh
# CATENATE: Prepend/Append data to stdin
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 17/10/2020
# License: MIT License
catenate() { cat <(echo -n "$1") - <(echo -n "$2"); }
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || catenate $@
#!/bin/sh
# RD: Read a character from the tty
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 9/12/2020
# License: MIT License
rd() {
IFS=
read -rsn1 mode # get 1 character
[[ $mode == $(printf "\u1b") ]] && read -rsn4 -t 0.001 mode2
char=$(echo -n "$mode$mode2" | sed 's/\[A//;s/\[B//;s/\[C//;s/\[D//;')
if [[ "$(echo -n $char | hexdump -c | tr -d '\n' | tr -d ' ')" == '00000000000001' ]]; then
str='space'
else
case "$char" in
[a-zA-Z0-9,._+:@%/-\#\$\^\&\*\(\)\=\{\}\|\\\;\'\"\<\>\~\`\[\]]) str=$char;;
'!') str='!';;
'?') str='?';;
*)
seq=$(echo -n "$mode$mode2" | hexdump -c | sed 's/^0+ \(.*\) \\n/\1/;s/ //g;s/^0*//;1q')
case $seq in
'33') str='esc' ;;
'33[A') str='up' ;;
'33[B') str='down' ;;
'33[C') str='right' ;;
'33[D') str='left' ;;
*)
s=$(echo $seq | sed 's/\[A//;s/\[B//;s/\[C//;s/\[D//;')
case $s in
'') str='enter' ;;
'1') str='^A' ;;
'177') str='backspace' ;;
*) str=$seq ;;
esac
;;
esac
;;
esac
fi
[[ -z $1 ]] && echo "$str" || eval "$1=\"$str\""
}
#!/bin/sh
# RDLN: Read a line from the tty
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 9/12/2020
# License: MIT License
rdln() {
str="";
while true; do
echo -n "> $str"
char=`rd`
echo -en "$(tput el1)\r"
case $char in
"enter") [[ -z $1 ]] && echo "$str" || eval "$1=\"$str\""; return;;
"backspace") [[ $(echo $str | wc -m) -gt 1 ]] && str="${str::-1}";;
*) str+=$char;;
esac
done
}
#!/bin/bash
# TOLOWER: Converts all chars in stdin to lowercase
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 8/12/2020
# License: MIT License
tolower() { sed 's/./\L&/g' /dev/stdin; }
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || tolower $@
#!/bin/bash
# TOUPPER: Converts all chars in stdin to uppercase
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 8/12/2020
# License: MIT License
toupper() { sed 's/./\U&/g' /dev/stdin; }
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || toupper $@
#!/bin/bash
hideinput()
{
if [ -t 0 ]; then
echo "Is tty"
save_state=$(stty -g)
stty -echo -icanon time 0 min 0
echo -ne "\e[?1049h\r" 1>&2;
else
echo "is not tty"
fi
}
cleanup()
{
if [ -t 0 ]; then
stty "$save_state"
echo -ne "\e[?1049l" 1>&2;
echo "exit tty"
else
echo "is not tty"
fi
}
trap 'cleanup < /dev/tty' EXIT
trap 'hideinput < /dev/tty' CONT
hideinput
input="$(< /dev/stdin)";
echo "$input"
while true;
do
read -r -sn1 < /dev/tty;
read -r -sn3 -t 0.001 k1 < /dev/tty;
REPLY+=$k1;
echo $REPLY
done
#!/bin/bash
# wait_any_key: Waits for the user to press any key
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:28:22 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
wait_any_key() { read -n 1 -s -r -p "Press any key to continue"; }
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || wait_any_key $@
#!/bin/sh
# TRANSPOSE: Swap columns and rows separated by spaces
# Author: https://stackoverflow.com/users/459745/hai-vu
# Question: https://stackoverflow.com/questions/9534744/how-to-transfer-the-data-of-columns-to-rows-with-awk
# Created: 9/12/2020
# License: MIT License
awk '{ for (i=1; i<=NF; i++) col[i] = col[i] " " $i }
END {
for (i=1; i<=NF; i++) {
sub(/^ /, "", col[i]);
print col[i]
}
}' $1
#!/bin/bash
# Script to init arch/ubuntu/windows_10 systems to nanOS
#{{{ Colours
# Add colour vars
if [ -t 1 ] && command -v tput > /dev/null; then
# see if it supports colors
ncolors=$(tput colors)
if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
bold="$(tput bold || echo)"
blink="$(tput blink || echo)"
reset="$(tput sgr0 || echo)"
black="$(tput setaf 0 || echo)"
red="$(tput setaf 1 || echo)"
green="$(tput setaf 2 || echo)"
yellow="$(tput setaf 3 || echo)"
blue="$(tput setaf 4 || echo)"
magenta="$(tput setaf 5 || echo)"
cyan="$(tput setaf 6 || echo)"
white="$(tput setaf 7 || echo)"
fi
fi
#}}}
#{{{ trypacmaninstall()
#}}}
#{{{ tryaurinstall()
#}}}
#{{{ tryaptinstall()
#}}}
#{{{ wait_any_key()
#}}}
#{{{ ask()
#}}}
#{{{ asklink()
#}}}
#{{{ askrecursivelinkdir()
#}}}
#{{{ asklinksudo()
#}}}
#{{{ askclone()
#}}}
#{{{ setup_ssh()
#}}}
#{{{ detect_os()
#Detect OS
#}}}
#{{{ arch_pkg_setup()
#}}}
#{{{ ubuntu_pkg_setup()
#}}}
#{{{ vim_setup()
#}}}
#{{{ tmux_setup()
#}}}
#{{{ setup_symlinks()
#}}}
#{{{ setup_repos()
#}}}
#{{{ setup_git()
#}}}
# BEGIN
detect_os
cd $HOME
if [ "$1" = "--configure" ]; then
setup_symlinks
exit
elif [ "$1" = "--repos" ]; then
clone_repos
exit
fi
# Setup ssh
echo ${blue}SSH Keys${reset}
ask "Setup ssh" && setup_ssh
echo ${blue}Git repos${reset}
ask "Clone repos" && setup_repos
echo ${blue}System Packages${reset}
# Update system
if ask "Upgrade packages"; then
case $NANOS_DISTRO in
Arch) sudo pacman -Syu && yay -Syu ;;
Ubuntu) sudo apt update && sudo apt upgrade ;;
Windows) echo "TODO Windows" ;;
esac
fi
# Install packages
if ask "Install packages"; then
case $NANOS_DISTRO in
Arch) arch_pkg_setup ;;
Ubuntu) ubuntu_pkg_setup ;;
Windows) echo "TODO Windows" ;;
esac
fi
echo ${blue}Link files${reset}
setup_symlinks
echo ${blue}Vim plugins${reset}
vim_setup
echo ${blue}Tmux plugins${reset}
tmux_setup
#echo ${blue}Git settings${reset}
#setup_git
#doom emacs
#!/bin/bash
# vim_setup: Install vimplug and plugins
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:40:42 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
vim_setup() {
#Setup vim/nvim
if [ -f "$XDG_DATA_HOME/vim/autoload/plug.vim" ] && [ -f "$XDG_DATA_HOME/nvim/site/autoload/plug.vim" ]; then
echo "${green}vimplug already installed${reset}"
elif ask "Install vim/nvim plugins"; then
if [ $NANOS_NAME = "linux" ]; then
if [ ! -f "$XDG_DATA_HOME/vim/autoload/plug.vim" ]; then
echo "$XDG_DATA_HOME/vim/autoload/plug.vim not found. Downloading..."
curl -fLo $HOME/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
vim -E -s +PlugInstall +visual +qall
fi
if [ ! -f "$XDG_DATA_HOME/nvim/site/autoload/plug.vim" ]; then
echo "$HOME/.config/nvim/site/autoload/plug.vim not found. Copying from $HOME/.vim/autoload/plug.vim"
curl -fLo "$XDG_DATA_HOME/nvim/site/autoload/plug.vim" --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
fi
if [ ! -f "$XDG_DATA_HOME/n0s1vim/site/autoload/plug.vim" ]; then
echo "$HOME/.config/n0s1vim/site/autoload/plug.vim not found. Copying from $HOME/.vim/autoload/plug.vim"
curl -fLo "$XDG_DATA_HOME/n0s1vim/site/autoload/plug.vim" --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
fi
fi
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || vim_setup $@
#!/bin/bash
# tryaptinstall: Prompt the user to install packages using apt
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:27:28 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
tryaptinstall() {
dpkg-query -W -f='${Status}' $1 2>/dev/null | grep -q "install ok installed" && echo "${green}$1${reset} is already installed" && return
ask "${magenta}$1${reset} is not installed, would you like to install it" && sudo apt-get --yes install $1
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || tryaptinstall $@
#!/bin/bash
# tryaurinstall: Prompt the user to install list of packages using AUR helper
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:25:57 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
tryaurinstall() {
pkgs=`echo $@ | sed "s/--prompt //"`
for pkg in $pkgs; do
pacman -Qi $pkg 1>/dev/null 2>/dev/null && echo "${green}$pkg${reset} is already installed" && continue
#Idk if this check works properly
pacman -Qg "$pkg@" 1>/dev/null 2>/dev/null && echo "${gree}$pkg${reset} is already installed" && continue
if [[ $1 == "--prompt" ]]; then
ask "install $pkg" || continue
fi
echo "${red}Installing $pkg${reset}" && yay -S $pkg;
done
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || tryaurinstall $@
#!/bin/bash
# trylink: Tries to create a symlink
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:32:19 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
trylink() {
if [ "$(diff -q "$1" "$2")" != "" ]; then
ask "${magenta}$2${reset} already exists and is not identical. Show diff" &&
diff "$1" "$2"
ask "Remove ${red}$2${reset}" && rm "$2"
else
rm "$2"
fi
echo "Linking ${magenta}$2${reset}"
ln -sf "$1" "$2"
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || trylink $@
#!/bin/bash
# trypacmaninstall: Prompts the user to install packages in the list
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 18:36:30 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
trypacmaninstall() {
pkgs=`echo $@ | sed "s/--prompt //"`
for pkg in $pkgs; do
pacman -Qi $pkg 1>/dev/null 2>/dev/null && echo "${green}$pkg${reset} is already installed" && continue
#Idk if this check works properly
pacman -Qg "$pkg@" 1>/dev/null 2>/dev/null && echo "${green}$pkg${reset} is already installed" && continue
if [[ $1 == "--prompt" ]]; then
ask "install $pkg" || continue
fi
echo "${red}Installing $pkg${reset}" && sudo pacman -S --noconfirm $pkg;
done
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || trypacmaninstall $@
#!/bin/bash
# ubuntu_pkg_setup: Script to install ubuntu packages
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:39:47 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
ubuntu_pkg_setup() {
tryaptinstall ripgrep
tryaptinstall fzf
tryaptinstall keychain
tryaptinstall tmux
tryaptinstall curl
tryaptinstall youtube-dl
tryaptinstall vim
tryaptinstall neovim
tryaptinstall nodejs
tryaptinstall zsh
tryaptinstall fd-find
#fd is already used on Ubuntu
if dpkg-query -W -f='${Status}' fd-find 2> /dev/null | grep -q "install ok installed"; then
asklink "fdfind (ubuntu fix)" "$(which fdfind)" "$HOME/.local/bin/fd"
fi
#Bat is not in standard repos because reasons
if dpkg-query -W -f='${Status}' bat 2> /dev/null | grep -q "install ok installed"; then
echo "${green}bat${reset} is already installed"
elif ask "'${magenta}bat${reset}' is not installed, would you like to install it"; then
cur_dir=$(pwd)
cd /tmp
wget https://github.com/sharkdp/bat/releases/download/v0.17.1/bat_0.17.1_amd64.deb
sudo dpkg -i bat_0.17.1_amd64.deb
cd $cur_dir
fi
###TODO Install Rider
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || ubuntu_pkg_setup $@
#!/bin/bash
# setup_git: setup git settings
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 20:28:25 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
setup_git() {
##Git settings
if [ "$(git config --get pull.rebase)" = false ] &&
[ "$(git config --get user.email)" = "[email protected]" ] &&
[ "$(git config --get user.name)" = "nan0scho1ar" ] &&
[ "$(git config --get core.editor)" = "vim" ]; then
echo "${green}Git${reset} configured correctly"
elif ask "Update git settings"; then
git config --global pull.rebase false
git config --global user.email "[email protected]"
git config --global user.name "nan0scho1ar"
git config --global core.editor "vim"
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || setup_git $@
#!/bin/bash
# setup_repos: sets up repos for a system
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 20:23:47 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
setup_repos() {
mkdir -p "$NANOS_REPOS_DIR"
cd $NANOS_REPOS_DIR
askclone "dotfiles" "[email protected]:Nan0Scho1ar/dotfiles.git"
askclone "scripts" "[email protected]:Nan0Scho1ar/scripts.git"
askclone "vimwiki" "[email protected]:Nan0Scho1ar/vimwiki.git"
askclone "n0s1.core" "[email protected]:Nan0Scho1ar/n0s1.core.git"
askclone "bish" "[email protected]:Nan0Scho1ar/bish"
askclone "gitmanager" "[email protected]:Nan0Scho1ar/gitmanager"
askclone "n0s1.core" "[email protected]:Nan0Scho1ar/n0s1.core.git"
cd $HOME
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || setup_repos $@
#!/bin/bash
# setup_ssh: Propmts user to create new ssh keys if none exist
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:36:17 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
setup_ssh() {
if [ -d .ssh ]; then
echo ".ssh directory already exits, continuing...";
else
echo "Creating .ssh directory";
mkdir .ssh
fi
if [ -f .ssh/id_rsa.pub ]; then
echo "ssh key already exists";
echo "Using existing key";
else
echo "Generating ssh key..."
ssh-keygen
fi
ask "add public key to remotes" && cat .ssh/id_rsa.pub && echo "Add ssh key to bitbucket and github before continuing." \
&& sh brave "https://bitbucket.org/account/settings/ssh-keys/" "https://github.com/settings/keys"
wait_any_key
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || setup_ssh $@
#!/bin/bash
# setup_symlinks: Sets up symlinks for a system
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 20:21:31 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
setup_symlinks() {
#asklinksudo "/etc/update-motd.d/10-help-text" "/home/nan0scho1ar/dotfiles/linux/99-banner" "/etc/update-motd.d/99-banner"
asklink ".bashrc" "$NANOS_REPOS_DIR/dotfiles/.bashrc" "$HOME/.bashrc"
asklink ".xinitrc" "$NANOS_REPOS_DIR/dotfiles/.xinitrc" "$HOME/.xinitrc"
asklink ".profile" "$NANOS_REPOS_DIR/dotfiles/.profile" "$HOME/.profile"
asklink ".vimrc" "$NANOS_REPOS_DIR/dotfiles/.vimrc" "$HOME/.vimrc"
asklink ".xprofile" "$NANOS_REPOS_DIR/dotfiles/.xprofile" "$HOME/.xprofile"
asklink ".zshenv" "$NANOS_REPOS_DIR/dotfiles/.zshenv" "$HOME/.zshenv"
asklink ".tmux.conf" "$NANOS_REPOS_DIR/dotfiles/.tmux.conf" "$HOME/.tmux.conf"
asklinkrecursive ".config" "$NANOS_REPOS_DIR/dotfiles/.config" "$HOME/.config"
asklinkrecursive ".doom.d" "$NANOS_REPOS_DIR/dotfiles/.doom.d" "$HOME/.doom.d"
asklinksudo "/etc/hosts" "$NANOS_REPOS_DIR/dotfiles/linux/hosts" "/etc/hosts"
asklinksudo "/etc/thinkfan.conf" "$NANOS_REPOS_DIR/dotfiles/etc/thinkfan.conf" "/etc/thinkfan.conf"
asklinksudo "awesome/rc.lua" "$NANOS_REPOS_DIR/dotfiles/etc/xdg/awesome/rc.lua" "/etc/xdg/awesome/rc.lua"
mkdir -p $HOME/.config/z/
source $HOME/.profile
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || setup_symlinks $@
#!/bin/bash
# tmux_setup: Installs tmux plugin manager
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:41:50 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
tmux_setup() {
if [ -d "$HOME/.tmux/plugins" ];then
echo "tmux plugin manager (tpm) already installed"
elif ask "Install tmux plugin manager"; then
mkdir -p $HOME/.tmux/plugins/
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || tmux_setup $@
#!/bin/sh
# FINDPKG: Attempts to find a package using available package managers
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: 17/10/2020
# License: MIT License
findpkg() {
local found_pkg_mgr=false
if command -v pacman >/dev/null 2>&1; then
found_pkg_mgr=true
echo -e "`tput setaf 2`Searching using pacman ($(command -v pacman))`tput sgr0`"
sudo pacman -Sy && pacman -Ss $@ && return
echo "`tput setaf 3`Could not find package using pacman`tput sgr0`"
else
echo "`tput setaf 3`Could not find pacman`tput sgr0`"
fi
if command -v yay >/dev/null 2>&1; then
found_pkg_mgr=true
echo -e "`tput setaf 2`Searching using yay ($(command -v yay))`tput sgr0`"
yay -Sy && local list=$(yay -Ss $@)
[[ $list != '' ]] && echo "$list" && return
echo `tput setaf 3`"Could not find package using yay`tput sgr0`"
else
echo `tput setaf 3`"Could not find yay`tput sgr0`"
fi
if $found_pkg_mgr; then
echo "`tput setaf 1`Could not find package using available package managers`tput sgr0`"
else
echo "`tput setaf 1`Could not find any valid package managers`tput sgr0`"
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || findpkg $@
#!/bin/bash
# detect_os: Attempts to detect the current operating system
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:37:08 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
detect_os() {
os=$(uname | tr '[:upper:]' '[:lower:]')
case $os in
linux|linux*)
export NANOS_NAME=linux
distros=$(cat /etc/*-release | sed -n "s/DISTRIB_ID=\(.*\)/\1/p")
case $distros in
ManjaroLinux) NANOS_DISTRO="Arch" ;;
Ubuntu) NANOS_DISTRO="Ubuntu" ;;
*)
if pacman --help >/dev/null 2>&1; then
NANOS_DISTRO="Arch"
elif command -v termux-setup-storage > /dev/null 2>&1; then
NAN0S_DISTRO="Termux"
else
echo "Unrecognized linux distro, please update startup script"
exit
fi
;;
esac
NANOS_REPOS_DIR="$HOME/repos/me"
;;
darwin*)
export NANOS_NAME=osx
;;
msys*|MINGW64_NT-10.0*)
export NANOS_NAME=windows
NANOS_DISTRO="Windows"
NANOS_REPOS_DIR="$HOME/repos/me"
;;
*)
echo "Unrecognized OS {$os}, please update startup script"
exit
;;
esac
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || detect_os $@
#!/bin/bash
# askclone: promts the user to clone a git repository
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:35:26 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
askclone() {
if [ -d $1 ]; then
echo "Directory $1 already exists, skipping..."
elif ask "Clone ${1}"; then
echo "Cloning $1"
git clone --recurse-submodules $2
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || askclone $@
#!/bin/bash
# asklink: prompts the user to create symlink if not already created
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:30:32 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
asklink() {
echo "$1"
echo "$2"
echo "$3"
if [ "$(readlink -- $3)" = "$2" ]; then
echo "${green}$1${reset} already linked correctly"
elif ask "Link ${magenta}${1}${reset}"; then
#Create dir if not exist
mkdir -p "$(dirname "${3}")"
trylink "$2" "$3"
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || asklink $@
#!/bin/bash
# asklinkrecursive: Creates symlinks for all nested dirs
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:33:23 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
#This is not actually recursive lol
asklinkrecursive() {
for f in $(find "$2" -type f | sed "s|$2/*||"); do
if [ "$(readlink -- $3/$f)" != "$2/$f" ]; then
if ask "Recursively Link $1"; then
#Create dir if not exist
mkdir -p "$3"
for dir in $(find "$2" -type d | sed "s|$2||"); do
if [ ! -d "$3/$dir" ]; then
echo "Creating directory $3/$dir"
#Create child dirs if not exist
mkdir -p "$3/$dir"
fi
done
for file in $(find "$2" -type f | sed "s|$2/*||"); do
if [ "$(readlink -- $3/$file)" = "$2/$file" ]; then
echo "${green}$1${reset} already linked correctly"
continue
elif [ ! -z "$3/$file" ]; then
trylink "$2/$file" "$3/$file"
else
echo "File does not exist"
fi
done
fi
return
fi
done
echo "${green}$1${reset} already linked correctly"
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || asklinkrecursive $@
#!/bin/bash
# asklinksudo: prompts user to create a symlink which requires sudo
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:34:34 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
asklinksudo() {
if [ "$(readlink -- $3)" = $2 ]; then
echo "${green}$1${reset} already linked correctly"
elif ask "Link ${magenta}$1${reset}"; then
#Create dir if not exist
mkdir -p "$(dirname "${3}")"
if [ -f "$3" ]; then
ask "${red}$1${reset} already exists. Remove it?" && sudo rm "$3"
fi
sudo ln -sf "$2" "$3"
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || asklinksudo $@
#!/bin/bash
# arch_pkg_setup: Sets up packages on an arch system
# Author: Nan0Scho1ar (Christopher Mackinga)
# Created: Tue 26 Oct 2021 19:38:38 AEST
# License: GPL v3
# Copyright (C) 2021 Christopher Mackinga <[email protected]>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
arch_pkg_setup() {
sudo pacman -Sy
### Pacman
#trypacmaninstall --prompt
trypacmaninstall \
alacritty aspell aspell-en base-devel bat bluez bluez-utils \
brave-browser bspwm cmake dmenu elixir emacs entr fd flameshot fzf gimp \
github-cli inkscape julia keychain languagetool mpv neovim net-tools \
nextcloud-client nitrogen nodejs peek polybar python-black python-isort \
python-neovim python-pipenv python-pyflakes python-pytest python-rednose \
racket ripgrep sbcl screenkey shellcheck stylelint sxhkd synergy tidy \
tmux ttf-jetbrains-mono unzip vim xclip xdotool xorg-xprop xorg-xwininfo \
xournalpp xsel yarn yay youtube-dl youtube-viewer zathura zathura-pdf-poppler \
if ask "Install doom emacs"; then
git clone --depth 1 https://github.com/hlissner/doom-emacs ~/.emacs.d
~/.emacs.d/bin/doom install
fi
### AUR
if ask "Askinstall extra"; then
yay -Sy
tryaurinstall --prompt minecraft-launcher
tryaurinstall --prompt pandoc
tryaurinstall --prompt texlive-most
tryaurinstall --prompt postman
tryaurinstall --prompt rider
tryaurinstall --prompt js-beautify
tryaurinstall --prompt clj-kondo-bin
fi
if ask "Install rust toolchain"; then
trypacmaninstall rustup rust-racer
sudo rustup install stable
sudo rustup default stable
sudo rustup component add rls rust-analysis rust-src
fi
if [ -d $NANOS_REPOS_DIR/neovim ] && ask "Install nvim from source"; then
cd $NANOS_REPOS_DIR &&
sudo rm -r neovim &&
git clone https://github.com/neovim/neovim &&
cd neovim &&
sudo make CMAKE_BUILD_TYPE=Release install &&
cd $NANOS_REPOS_DIR
fi
}
[[ "${BASH_SOURCE[0]}" != "${0}" ]] || arch_pkg_setup $@
#!/bin/sh
### Basic Arch VM install script
read -p "Enter the hostname: " MYHOSTNAME
timedatectl set-ntp true
echo -e "g\nn\n\n\n+1M\nt\n4\nn\n\n\n+4G\nt\n2\n19\nn\n\n\n\np\nw\n" | fdisk /dev/sda
mkfs.ext4 /dev/sda3
mkswap /dev/sda2
mount /dev/sda3 /mnt
swapon /dev/sda2
pacstrap /mnt base linux linux-firmware vi
genfstab -U /mnt >> /mnt/etc/fstab
cat << EOF | arch-chroot /mnt
ln -sf /usr/share/zoneinfo/Australia/Brisbane /etc/localtime
hwclock --systohc
sed -i "s/#\(en_US.UTF-8 UTF-8\)/\1/;s/#\(en_AU.UTF-8 UTF-8\)/\1/" /etc/locale.gen
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
echo "$MYHOSTNAME" > /etc/hostname
echo -e "127.0.0.1 localhost\n::1 localhost\n127.0.1.1 $MYHOSTNAME.localdomain $MYHOSTNAME" >> /etc/hosts
pacman -Sy --noconfirm grub
grub-install --target=i386-pc /dev/sda
grub-mkconfig -o /boot/grub/grub.cfg
EOF
echo "Run passwd to set root password then exit and reboot"
arch-chroot /mnt
#!/bin/bash
### Reverse a bash array
reverse_array() {
# first argument is the array to reverse
# second is the output array
declare -n arr="$1" rev="$2"
for i in "${arr[@]}"
do
rev=("$i" "${rev[@]}")
done
}
### Several suckless shell scripts and other core features.
## Shell
### FZY: Command Line Fuzzy Finder ([link](fzy))
I found myself using fzf a lot and building it into my scripts. But on a number of occasions I was working on machines which didn’t have it installed. This covers many of my use cases (Like fuzzy menus) in < 20 lines of shell script.
#### FZY_Lite: 10 SLOC Command Line Fuzzy Finder ([link](fzy_lite)) I have also included FZY_Lite which is basically the same logic but squished into 10 SLOC (And smaller comment) for embedding inside scripts.
### TOML: Simple get/set commands to read and write toml files ([link](toml)) POSIX Compliant shell script for reading from + writing to TOML files.
### BISH ([link](bish)) Floating shell used for loading scripts and managing the system configuration. Built to allow easy customization supporting bioinformatics workloads, but generally just a good tool for extending your shell.
### BM: Bookmarks ([link](bm)) Bookmarks for everything.
### CHECK_ROOT: Throws an error if the current user is not root ([link](check_root)) Checks if the current user is root.
### DISCORD_WEBHOOKS: Tool for managing and messaging using discord webhooks ([link](discordwebhooks)) Manage webhooks to post as multiple users, for multiple channels in your servers.
### HIST: Shell history made easy ([link](hist)) Tool for working with shell history.
### USELESS: less but less code. Seriously, just use less. ([link](useless)) Less but written in 20 lines of shell script. Not designed to be used as is, more a foundation for other CLI tools
### HACKLESS: The hackable less ([link](hackless)) More extensible version of useless.
### SETUP ([link](setup)) Script to set up parts of NanOS