Przeglądaj źródła

Re-Initialized Commit: v2.0.2

control 5 miesięcy temu
commit
087d90bdb3

+ 19 - 0
_ver_2.0.2.md

@@ -0,0 +1,19 @@
+# DOTS
+---
+
+# Changelog
+
+## 2025-08-18   v 2.0.2
+
+### Fixed:
+- Fixed bug not placing system aliases
+
+### New:
+- Added TMUX Plugin Manager manual install script
+    - Configuration setting is still manual
+
+
+## 2025-01-01    v 2.0.1
+
+### New:
+- Standalone, no longer coupled with QConfig

+ 102 - 0
aliases/default_aliases

@@ -0,0 +1,102 @@
+# Keep in dots/aliases & Source
+
+host=$(hostname)
+hostname="${host^^}"
+
+# Colored Prompts
+alias ls='ls --color=auto'
+alias dir='dir --color=auto'
+alias vdir='vdir --color=auto'
+alias grep='grep --color=auto'
+alias fgrep='fgrep --color=auto'
+alias egrep='egrep --color=auto'
+
+# colored GCC warnings and errors
+export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
+
+# Aliases
+
+if [ -e "/opt/qbins/eza" ]; then
+    alias ls="eza"
+fi
+
+alias cl="clear"
+alias cls="cl && pwd && ls"
+alias cdl="cd && cl"
+alias cdls="cdl && ls"
+alias l="ls"
+alias ll="ls -lh"
+alias la="ls -lah"
+alias lt="ls -lt"
+alias oo="open . || xdg-open ."
+alias ex="exit"
+alias qq="exit"
+alias mv="mv -iv"
+alias cp="cp -riv"
+alias mkdir="mkdir -vp"
+alias rm="rm -i"
+alias b="cd .."
+alias bls="cd .. && ls"
+alias bb="cd ../../"
+alias bbls="cd ../../ && ls"
+alias v="vim"
+alias vim="nvim -R"
+alias vime="nvim"
+alias py="python3"
+alias py2="python2"
+alias py3="python3"
+alias s="sudo -E"
+
+function check-env() {
+    if [ -n "$PIPENV_ACTIVE" ]; then
+        echo "Pipenv Environment Active"
+        echo "$VIRTUAL_ENV"
+    fi
+}
+alias ce="check-env"
+
+alias edit-alias="vim ~/.dots/user/aliases"
+alias edit-aliases="edit-alias"
+alias ea="edit-alias"
+
+alias edit-path="vim ~/.dots/user/paths"
+alias edit-paths="edit-path"
+alias ep="edit-paths"
+
+alias acknowledge-prompt="rm -rf /tmp/prompt_msg"
+alias ack="acknowledge-prompt"
+
+alias source-profile="source ~/.bashrc"
+alias source-pro="source-profile"
+alias sp="source-pro"
+
+alias internetSpeedTest="wget -O /dev/null http://speedtest.wdc01.softlayer.com/downloads/test10.zip"
+alias ufwcmd="echo 'ufw allow proto tcp from 0.0.0.0 port 00 to 0.0.0.0 port 00 comment'"
+alias weather="curl http://wttr.in/hk"
+alias publicip="curl ipinfo.io"
+
+alias git-graph="git log --all --decorate --oneline --graph"
+alias git-restore="git restore ."
+alias git-sreset="git reset --soft"
+alias git-hreset="git reset --hard"
+alias git-clean="git clean . -fd"
+alias git-check="git checkout"
+alias gs="git status"
+alias gl="git log"
+alias gd="git diff"
+alias gf="git fetch"
+alias ga="git add ."
+alias gb="git branch"
+alias gch="git checkout"
+alias gp="git push"
+alias gpl="git fetch && git pull"
+alias gc="git commit -am 'quick updates'"
+alias gcp="git commit -am 'quick updates' && git push"
+alias gcm="git commit -m"
+
+alias dlvid="yt-dlp"
+alias dlmp3="yt-dlp -x --audio-format mp3"
+alias dlflac="yt-dlp -x --audio-format flac"
+alias dlplaylist='yt-dlp --output "%(playlist_index)s.%(title)s.%(ext)s"'
+
+export EDITOR=/usr/bin/nvim

+ 56 - 0
aliases/system_aliases

@@ -0,0 +1,56 @@
+# Colored Prompts
+alias ls='ls --color=auto'
+alias dir='dir --color=auto'
+alias vdir='vdir --color=auto'
+alias grep='grep --color=auto'
+alias fgrep='fgrep --color=auto'
+alias egrep='egrep --color=auto'
+
+# colored GCC warnings and errors
+export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
+
+# System-Wide Aliases
+alias cl="clear"
+alias cls="cl && pwd && ls"
+alias cdl="cd && cl"
+alias cdls="cdl && ls"
+alias l="ls"
+alias ll="ls -lh"
+alias la="ls -lah"
+alias lt="ls -lt"
+alias oo="open . || xdg-open ."
+alias ex="exit"
+alias qq="exit"
+alias mv="mv -iv"
+alias cp="cp -riv"
+alias mkdir="mkdir -vp"
+alias rm="rm -i"
+alias b="cd .."
+alias bls="cd .. && ls"
+alias bb="cd ../../"
+alias bbls="cd ../../ && ls"
+alias v="vim"
+alias vim="nvim -R"
+alias vime="nvim"
+alias py="python3"
+alias py2="python2"
+alias py3="python3"
+alias s="sudo -E"
+
+alias internetSpeedTest="wget -O /dev/null http://speedtest.wdc01.softlayer.com/downloads/test10.zip"
+alias weather="curl http://wttr.in/hk"
+alias publicip="curl ipinfo.io"
+
+alias graph="git log --all --decorate --oneline --graph"
+alias gs="git status"
+alias gl="git log"
+alias gd="git diff"
+alias gf="git fetch"
+alias ga="git add ."
+alias gb="git branch"
+alias gch="git checkout"
+alias gp="git push"
+alias gpl="git fetch && git pull"
+alias gc="git commit -am 'quick updates'"
+alias gcp="git commit -am 'quick updates' && git push"
+alias gcm="git commit -m"

+ 2 - 0
app_config/inputrc

@@ -0,0 +1,2 @@
+set show-all-if-ambiguous on
+set completion-ignore-case on

+ 24 - 0
app_config/nvim

@@ -0,0 +1,24 @@
+" located in ~/.config/nvim/init.vim
+
+set nocompatible            " disable compatibility to old-time vi
+set showmatch               " show matching 
+set ignorecase              " case insensitive 
+set mouse=v                 " middle-click paste with 
+set hlsearch                " highlight search 
+set incsearch               " incremental search
+set tabstop=4               " number of columns occupied by a tab 
+set softtabstop=4           " see multiple spaces as tabstops so <BS> does the right thing
+set expandtab               " converts tabs to white space
+set shiftwidth=4            " width for autoindents
+set autoindent              " indent a new line the same amount as the line just typed
+set number                  " add line numbers
+set wildmode=longest,list   " get bash-like tab completions
+filetype plugin indent on   "allow auto-indenting depending on file type
+syntax on                   " syntax highlighting
+set mouse=a                 " enable mouse click
+set clipboard=unnamedplus   " using system clipboard
+filetype plugin on
+set cursorline              " highlight current cursorline
+set ttyfast                 " Speed up scrolling in Vim
+" set spell                 " enable spell check (may need to download language package)
+" set noswapfile            " disable creating swap file

+ 7 - 0
app_config/tmux.conf

@@ -0,0 +1,7 @@
+# put this in ~/.tmux.conf
+set -g default-command /bin/bash
+set -g default-shell /bin/bash
+set -g default-terminal "xterm-256color"
+set -ga terminal-overrides ',xterm-256color:Tc'
+set -g pane-border-status bottom
+unbind Space

+ 27 - 0
app_config/tmuxp.conf

@@ -0,0 +1,27 @@
+# put this in ~/.tmux.conf
+set -g default-command /bin/bash
+set -g default-shell /bin/bash
+set -g default-terminal "xterm-256color"
+set -ga terminal-overrides ',xterm-256color:Tc'
+set -g pane-border-status bottom
+# List of plugins
+set -g @plugin 'tmux-plugins/tpm'
+set -g @plugin 'tmux-plugins/tmux-sensible'
+
+# Other examples:
+# set -g @plugin 'github_username/plugin_name'
+# set -g @plugin 'github_username/plugin_name#branch'
+# set -g @plugin 'git@github.com:user/plugin'
+# set -g @plugin 'git@bitbucket.com:user/plugin'
+
+# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
+run '~/.tmux/plugins/tpm/tpm'
+
+# Tmux Resurrect
+set -g @plugin 'tmux-plugins/tmux-resurrect'
+
+# README
+# initialize with
+# tmux source ~/.tmux.conf while running a restart tmux env
+# then CTR-B + CTR-I to load plugins
+# CTR-B + CTR-S to save CTR-B + CTR-R to load

+ 43 - 0
app_config/vimrc

@@ -0,0 +1,43 @@
+" Turn on syntax highlighting
+syntax on
+
+" Automatically wrap text that extends beyond the screen length
+set wrap
+
+" Tabs 
+set tabstop=8 softtabstop=0 expandtab shiftwidth=4 smarttab
+
+" Show line numbers
+set number 
+
+" Display different types of white spaces 
+set list 
+set listchars=tab:›\ ,trail:•,extends:#,nbsp:.
+
+" Set status line display
+set statusline=%F%m%r%h%w\ [FORMAT=%{&ff}]\ [TYPE=%Y]\ [POS=%l,%v][%p%%]\ [BUFFER=%n]\ %{strftime('%c')}
+
+" Encoding 
+set encoding=utf-8
+
+"Highlight matching search patterns 
+set hlsearch
+
+" Enable incremental search 
+set incsearch
+
+" Include matching uppercase words with lowercase search terms 
+set ignorecase 
+
+" Include only uppercase words with uppercases search term 
+set smartcase 
+
+" Highlight matching pairs of brackets. Use the '%' character to jump between them.
+set matchpairs+=<:>
+
+" Speed up scrolling 
+set ttyfast
+
+" Fixes common backspace problems 
+set backspace=indent,eol,start
+

+ 132 - 0
install

@@ -0,0 +1,132 @@
+#!/usr/bin/python3
+# run as: root/user
+
+import os
+import sys
+import shutil
+
+SPATH = os.path.abspath(__file__)
+SDIR = os.path.dirname(SPATH)
+
+# Bash to loop through dir and source files
+BASHRC_STR = \
+""" # Dots Base Files
+for file in ~/.dots/base/*; do
+    if [ -r \"$file\" ]; then
+        source \"$file\"
+    fi
+done
+
+# Dots User Files
+for file in ~/.dots/user/*; do
+    if [ -r \"$file\" ]; then
+        source \"$file\"
+    fi
+done """
+
+def run(command: str):
+    os.system(command)
+
+def get_prompt() -> str:
+    # Check for argument input
+    if len(sys.argv) < 2:
+        print('::[Dots Installation Script]::')
+        print('Usage: install <prompt to use: (seafly|parrot|powerline)>')
+        sys.exit(1)
+
+    # Ensure user choice is valid
+    prompts = ['seafly', 'parrot', 'powerline']
+    uprompt = sys.argv[1]
+
+    if uprompt not in prompts:
+        print('Please choose a valid prompt file!')
+        print('seafly | parrot | powerline')
+        sys.exit(1)
+
+    return uprompt
+
+def string_in_file(path: str, string: str) -> bool:
+    try:
+        epath = os.path.expandvars(path) # expand Bash Environment Variables
+        with open(epath, 'r') as file:
+            file_contents = file.read()
+
+        if string in file_contents:
+            return True
+        else:
+            return False
+    except Exception as e:
+        print(f'General Exception (string_in_file): {e}')
+
+def add_string(path: str, string: str) -> bool:
+    try:
+        epath = os.path.expandvars(path) # expand Bash Environment Variables
+        with open(epath, 'a') as file:
+            file.write(string + '\n')
+        return True
+    except Exception as e:
+        print(f'General Exception (add_string): {e}')
+        return False
+
+# Create path and children if not exists
+def create_path(path) -> bool:
+    try:
+        epath = os.path.expandvars(path) # expand Bash Environment Variables
+        os.makedirs(epath, exist_ok = True)
+        return True
+    except Exception as e:
+        print(f'General Exception (create_path): {e}')
+        return False
+
+def copy_file(source: str, destination: str) -> bool:
+    try:
+        src = os.path.expandvars(source) # expand Bash Environment Variables
+        dst = os.path.expandvars(destination)
+        shutil.copy2(src, dst)
+        return True
+    except Exception as e:
+        print(f'General Exception (copy_file): {e}')
+        return False
+
+def is_sudo() -> bool:
+    try:
+        return os.geteuid() == 0
+    except Exception as e:
+        return False
+
+def main():
+    uprompt = get_prompt()
+
+    # NVIM
+    create_path('$HOME/.config/nvim/')
+    copy_file(f'{SDIR}/app_config/nvim', '$HOME/.config/nvim/init.vim')
+    print('Installed NVIM configs')
+
+    # TMUX
+    copy_file(f'{SDIR}/app_config/tmux.conf', '$HOME/.tmux.conf')
+    print('Installed TMUX configs')
+
+    # Create dots working dir
+    run(f'rm -rf $HOME/.dots/base/') # Remove old config
+    create_path('$HOME/.dots/base/')
+    create_path('$HOME/.dots/user/')
+    print('Initialized Dots dir')
+
+    # Set default aliases
+    copy_file(f'{SDIR}/aliases/default_aliases', f'$HOME/.dots/base')
+    copy_file(f'{SDIR}/prompts/{uprompt}-prompt', f'$HOME/.dots/base')
+    print('Set prompt')
+
+    # Add Bashrc Config
+    if not string_in_file('$HOME/.bashrc', BASHRC_STR):
+        add_string('$HOME/.bashrc', BASHRC_STR)
+
+    # Set System Aliases if sudo
+    if is_sudo():
+        copy_file(f'{SDIR}/aliases/system_aliases', '/etc/system_aliases')
+        run('chmod 644 /etc/system_aliases')
+        print('Set System Aliases')
+        
+
+if __name__ == '__main__':
+    main()

+ 4 - 0
install_tmux_plugins.sh

@@ -0,0 +1,4 @@
+#!/bin/bash
+
+git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
+echo "Remember to tmux source ~/.tmux.conf"

+ 144 - 0
prompts/parrot-prompt

@@ -0,0 +1,144 @@
+# ~/.bashrc: executed by bash(1) for non-login shells.
+# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
+# for examples
+
+# If not running interactively, don't do anything
+case $- in
+    *i*) ;;
+      *) return;;
+esac
+
+export PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/usr/share/games:/usr/local/sbin:/usr/sbin:/sbin:~/.local/bin:/snap/bin:$PATH
+
+# don't put duplicate lines or lines starting with space in the history.
+# See bash(1) for more options
+HISTCONTROL=ignoreboth
+
+# append to the history file, don't overwrite it
+shopt -s histappend
+
+# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
+HISTSIZE=1000
+HISTFILESIZE=2000
+
+# check the window size after each command and, if necessary,
+# update the values of LINES and COLUMNS.
+shopt -s checkwinsize
+
+# If set, the pattern "**" used in a pathname expansion context will
+# match all files and zero or more directories and subdirectories.
+#shopt -s globstar
+
+# make less more friendly for non-text input files, see lesspipe(1)
+#[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
+
+# set variable identifying the chroot you work in (used in the prompt below)
+if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
+    debian_chroot=$(cat /etc/debian_chroot)
+fi
+
+# set a fancy prompt (non-color, unless we know we "want" color)
+case "$TERM" in
+    xterm-color) color_prompt=yes;;
+esac
+
+# uncomment for a colored prompt, if the terminal has the capability; turned
+# off by default to not distract the user: the focus in a terminal window
+# should be on the output of commands, not on the prompt
+force_color_prompt=yes
+
+if [ -n "$force_color_prompt" ]; then
+    if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
+	# We have color support; assume it's compliant with Ecma-48
+	# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
+	# a case would tend to support setf rather than setaf.)
+	color_prompt=yes
+    else
+	color_prompt=
+    fi
+fi
+
+if [ "$color_prompt" = yes ]; then
+    PS1="\[\033[0;31m\]\342\224\214\342\224\200\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[01;31m\]root\[\033[01;33m\]@\[\033[01;96m\]\h'; else echo '\[\033[0;39m\]\u\[\033[01;33m\]@\[\033[01;96m\]\h'; fi)\[\033[0;31m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;31m\]]\n\[\033[0;31m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]\[\e[01;33m\]\\$\[\e[0m\]"
+else
+    PS1='┌──[\u@\h]─[\w]\n└──╼ \$ '
+fi
+
+# Set 'man' colors
+if [ "$color_prompt" = yes ]; then
+	man() {
+	env \
+	LESS_TERMCAP_mb=$'\e[01;31m' \
+	LESS_TERMCAP_md=$'\e[01;31m' \
+	LESS_TERMCAP_me=$'\e[0m' \
+	LESS_TERMCAP_se=$'\e[0m' \
+	LESS_TERMCAP_so=$'\e[01;44;33m' \
+	LESS_TERMCAP_ue=$'\e[0m' \
+	LESS_TERMCAP_us=$'\e[01;32m' \
+	man "$@"
+	}
+fi
+
+unset color_prompt force_color_prompt
+
+# If this is an xterm set the title to user@host:dir
+case "$TERM" in
+xterm*|rxvt*)
+    PS1="\[\033[0;31m\]\342\224\214\342\224\200\$([[ \$? != 0 ]] && echo \"[\[\033[0;31m\]\342\234\227\[\033[0;37m\]]\342\224\200\")[$(if [[ ${EUID} == 0 ]]; then echo '\[\033[01;31m\]root\[\033[01;33m\]@\[\033[01;96m\]\h'; else echo '\[\033[0;39m\]\u\[\033[01;33m\]@\[\033[01;96m\]\h'; fi)\[\033[0;31m\]]\342\224\200[\[\033[0;32m\]\w\[\033[0;31m\]]\n\[\033[0;31m\]\342\224\224\342\224\200\342\224\200\342\225\274 \[\033[0m\]\[\e[01;33m\]\\$\[\e[0m\]"
+    ;;
+*)
+    ;;
+esac
+
+# enable color support of ls and also add handy aliases
+if [ -x /usr/bin/dircolors ]; then
+    test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
+    alias ls='ls --color=auto'
+    alias dir='dir --color=auto'
+    alias vdir='vdir --color=auto'
+
+    alias grep='grep --color=auto'
+    alias fgrep='fgrep --color=auto'
+    alias egrep='egrep --color=auto'
+fi
+
+# some more ls aliases
+alias ll='ls -lh'
+alias la='ls -lha'
+alias l='ls -CF'
+alias em='emacs -nw'
+alias dd='dd status=progress'
+alias _='sudo'
+alias _i='sudo -i'
+
+# Alias definitions.
+# You may want to put all your additions into a separate file like
+# ~/.bash_aliases, instead of adding them here directly.
+# See /usr/share/doc/bash-doc/examples in the bash-doc package.
+
+if [ -f ~/.bash_aliases ]; then
+    . ~/.bash_aliases
+fi
+
+# enable programmable completion features (you don't need to enable
+# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
+# sources /etc/bash.bashrc).
+if ! shopt -oq posix; then
+  if [ -f /usr/share/bash-completion/bash_completion ]; then
+    . /usr/share/bash-completion/bash_completion
+  elif [ -f /etc/bash_completion ]; then
+    . /etc/bash_completion
+  fi
+fi
+
+# QNET: Custom Prompting
+MSG="/tmp/prompt_msg"
+prompt_func() {
+    if [[ -f "$MSG" ]]; then # exists
+        if [[ -n "$MSG" ]]; then # not empty
+            cat "$MSG"
+            echo ''
+        fi
+    fi
+}
+PROMPT_COMMAND='prompt_func'

+ 107 - 0
prompts/powerline-prompt

@@ -0,0 +1,107 @@
+#!/usr/bin/env bash
+
+## Uncomment to disable git info
+#POWERLINE_GIT=0
+
+HOSTNAME=$(hostname)
+
+__powerline() {
+    # Colors
+    COLOR_RESET='\[\033[m\]'
+    COLOR_CWD=${COLOR_CWD:-'\[\033[0;34m\]'} # blue
+    COLOR_GIT=${COLOR_GIT:-'\[\033[0;36m\]'} # cyan
+    COLOR_SUCCESS=${COLOR_SUCCESS:-'\[\033[0;32m\]'} # green
+    COLOR_FAILURE=${COLOR_FAILURE:-'\[\033[0;31m\]'} # red
+
+    # Symbols
+    SYMBOL_GIT_BRANCH=${SYMBOL_GIT_BRANCH:-⑂}
+    SYMBOL_GIT_MODIFIED=${SYMBOL_GIT_MODIFIED:-*}
+    SYMBOL_GIT_PUSH=${SYMBOL_GIT_PUSH:-↑}
+    SYMBOL_GIT_PULL=${SYMBOL_GIT_PULL:-↓}
+
+    if [[ -z "$PS_SYMBOL" ]]; then
+      case "$(uname)" in
+          Darwin)   PS_SYMBOL='';;
+          Linux)    PS_SYMBOL='$';;
+          *)        PS_SYMBOL='%';;
+      esac
+    fi
+
+    __git_info() { 
+        [[ $POWERLINE_GIT = 0 ]] && return # disabled
+        hash git 2>/dev/null || return # git not found
+        local git_eng="env LANG=C git"   # force git output in English to make our work easier
+
+        # get current branch name
+        local ref=$($git_eng symbolic-ref --short HEAD 2>/dev/null)
+
+        if [[ -n "$ref" ]]; then
+            # prepend branch symbol
+            ref=$SYMBOL_GIT_BRANCH$ref
+        else
+            # get tag name or short unique hash
+            ref=$($git_eng describe --tags --always 2>/dev/null)
+        fi
+
+        [[ -n "$ref" ]] || return  # not a git repo
+
+        local marks
+
+        # scan first two lines of output from `git status`
+        while IFS= read -r line; do
+            if [[ $line =~ ^## ]]; then # header line
+                [[ $line =~ ahead\ ([0-9]+) ]] && marks+=" $SYMBOL_GIT_PUSH${BASH_REMATCH[1]}"
+                [[ $line =~ behind\ ([0-9]+) ]] && marks+=" $SYMBOL_GIT_PULL${BASH_REMATCH[1]}"
+            else # branch is modified if output contains more lines after the header line
+                marks="$SYMBOL_GIT_MODIFIED$marks"
+                break
+            fi
+        done < <($git_eng status --porcelain --branch 2>/dev/null)  # note the space between the two <
+
+        # print the git branch segment without a trailing newline
+        printf " $ref$marks"
+    }
+
+    ps1() {
+        # Check the exit code of the previous command and display different
+        # colors in the prompt accordingly. 
+        if [ $? -eq 0 ]; then
+            local symbol="$COLOR_SUCCESS $PS_SYMBOL $COLOR_RESET"
+        else
+            local symbol="$COLOR_FAILURE $PS_SYMBOL $COLOR_RESET"
+        fi
+
+        local cwd="$COLOR_CWD\w$COLOR_RESET"
+        # Bash by default expands the content of PS1 unless promptvars is disabled.
+        # We must use another layer of reference to prevent expanding any user
+        # provided strings, which would cause security issues.
+        # POC: https://github.com/njhartwell/pw3nage
+        # Related fix in git-bash: https://github.com/git/git/blob/9d77b0405ce6b471cb5ce3a904368fc25e55643d/contrib/completion/git-prompt.sh#L324
+        if shopt -q promptvars; then
+            __powerline_git_info="$(__git_info)"
+            local git="$COLOR_GIT\${__powerline_git_info}$COLOR_RESET"
+        else
+            # promptvars is disabled. Avoid creating unnecessary env var.
+            local git="$COLOR_GIT$(__git_info)$COLOR_RESET"
+        fi
+
+        PS1="[$HOSTNAME]$cwd$git$symbol"
+    }
+
+    PROMPT_COMMAND="ps1${PROMPT_COMMAND:+; $PROMPT_COMMAND}"
+}
+
+# QNET: Custom Prompting
+MSG="/tmp/prompt_msg"
+prompt_func() {
+    if [[ -f "$MSG" ]]; then # exists
+        if [[ -n "$MSG" ]]; then # not empty
+            cat "$MSG"
+            echo ''
+        fi
+    fi
+}
+PROMPT_COMMAND='prompt_func'
+
+__powerline
+unset __powerline

+ 237 - 0
prompts/seafly-prompt

@@ -0,0 +1,237 @@
+#!/bin/bash
+# A modern, informative and configurable command prompt for the Bash shell.
+#
+# URL:     github.com/bluz71/bash-seafly-prompt
+# License: MIT (https://opensource.org/licenses/MIT)
+
+
+# Non-interactive shells don't have a prompt, exit early.
+[[ $- =~ i ]] || return 0
+
+# Set a simple prompt for non-256color, non-alacritty and non-kitty terminals.
+if [[ $TERM != *-256color ]] && [[ $TERM != alacritty* ]] && [[ $TERM != *-kitty ]]; then
+    PS1='\h \w > '
+    return 0
+fi
+
+# Default colors used in the prompt.
+: ${SEAFLY_PREFIX_COLOR:=$(tput setaf 153)}
+: ${SEAFLY_NORMAL_COLOR:=$(tput setaf 111)}
+: ${SEAFLY_ALERT_COLOR:=$(tput setaf 203)}
+: ${SEAFLY_HOST_COLOR:=$(tput setaf 255)}
+: ${SEAFLY_GIT_COLOR:=$(tput setaf 147)}
+: ${SEAFLY_PATH_COLOR:=$(tput setaf 150)}
+: ${NOCOLOR:=$(tput sgr0)}
+
+# Shorten directory paths to a maximum of four components unless PROMPT_DIRTRIM
+# has already been set.
+: ${PROMPT_DIRTRIM:=4}
+
+# Default Git indicator values.
+: ${GIT_PS1_SHOWDIRTYSTATE:=1}
+: ${GIT_PS1_SHOWSTASHSTATE:=1}
+: ${GIT_PS1_SHOWUPSTREAM:=1}
+
+# Default layout settings.
+: ${SEAFLY_LAYOUT:=1}
+: ${SEAFLY_MULTILINE:=0}
+: ${SEAFLY_SHOW_USER:=0}
+: ${SEAFLY_SHOW_HOST:=1}
+
+# Default symbols used in the prompt.
+: ${SEAFLY_PROMPT_SYMBOL:="❯"}
+: ${SEAFLY_PS2_PROMPT_SYMBOL:="❯"}
+: ${SEAFLY_GIT_PREFIX:=""}
+: ${SEAFLY_GIT_SUFFIX:=""}
+: ${SEAFLY_GIT_DIRTY:="✗"}
+: ${SEAFLY_GIT_STAGED:="✓"}
+: ${SEAFLY_GIT_STASH:="⚑"}
+: ${SEAFLY_GIT_AHEAD:="↑"}
+: ${SEAFLY_GIT_BEHIND:="↓"}
+: ${SEAFLY_GIT_DIVERGED:="↕"}
+
+# Location of [gitstatus](https://github.com/romkatv/gitstatus).
+: ${SEAFLY_GITSTATUS_DIR:="$HOME/.gitstatus"}
+
+# Optional command to run before every prompt; output is ignored.
+: ${SEAFLY_PRE_COMMAND:=""}
+# Optional command that outputs as the prompt prefix.
+: ${SEAFLY_PROMPT_PREFIX:=""}
+
+# Collate Git details using the optimized
+# [gitstatus](https://github.com/romkatv/gitstatus) command.
+#
+_seafly_git_optimized() {
+    local flags
+    # Note, gitstatus will automatically set '-p' if the local repository has
+    # set 'bash.showDirtyState' to false.
+    [[ $GIT_PS1_SHOWDIRTYSTATE == 0  ]] && flags=-p # Avoid unnecessary work
+    if ! hash gitstatus_query 2>/dev/null || ! gitstatus_query $flags; then
+        # Either gitstatus_query does not exist or it failed, use fallback
+        # instead.
+        _seafly_git_fallback
+        return
+    fi
+    [[ $VCS_STATUS_RESULT == ok-sync ]] || return
+
+    # We are in a Git repository and gitstatus_query succeeded.
+    local branch=$VCS_STATUS_LOCAL_BRANCH
+    if [[ -z $branch ]]; then
+        branch="detached*$(git rev-parse --short HEAD 2>/dev/null)"
+    fi
+    branch=${branch//\\/\\\\}  # Escape backslashes
+    branch=${branch//\$/\\\$}  # Escape dollars
+
+    local dirty
+    local staged
+    if [[ $GIT_PS1_SHOWDIRTYSTATE != 0 && $VCS_STATUS_HAS_UNSTAGED == 1 ]]; then
+        dirty=$SEAFLY_GIT_DIRTY
+    fi
+    if [[ $GIT_PS1_SHOWDIRTYSTATE != 0 && $VCS_STATUS_HAS_STAGED == 1 ]]; then
+        staged=$SEAFLY_GIT_STAGED
+    fi
+
+    local stash
+    if [[ $GIT_PS1_SHOWSTASHSTATE != 0 && $VCS_STATUS_STASHES -gt 0 ]]; then
+        stash=$SEAFLY_GIT_STASH
+    fi
+
+    local upstream
+    if [[ $GIT_PS1_SHOWUPSTREAM != 0 ]]; then
+        if [[ $VCS_STATUS_COMMITS_AHEAD -gt 0 &&
+              $VCS_STATUS_COMMITS_BEHIND -gt 0 ]]; then
+            upstream=$SEAFLY_GIT_DIVERGED
+        elif [[ $VCS_STATUS_COMMITS_AHEAD -gt 0 ]]; then
+            upstream=$SEAFLY_GIT_AHEAD
+        elif [[ $VCS_STATUS_COMMITS_BEHIND -gt 0 ]]; then
+            upstream=$SEAFLY_GIT_BEHIND
+        elif [[ -n $VCS_STATUS_REMOTE_NAME ]]; then
+            upstream="="
+        fi
+    fi
+
+    local spacer
+    if [[ -n $dirty || -n $staged || -n $stash || -n $upstream ]]; then
+        spacer=" "
+    fi
+    _seafly_git=" $SEAFLY_GIT_PREFIX$branch$spacer\[$SEAFLY_ALERT_COLOR\]$dirty\[$SEAFLY_NORMAL_COLOR\]$staged$upstream\[$SEAFLY_GIT_COLOR\]$stash$SEAFLY_GIT_SUFFIX"
+}
+
+# Collate Git details using just the 'git' command.
+#
+_seafly_git_fallback() {
+    local is_git_repo
+    if [[ $(git rev-parse --is-inside-work-tree --is-bare-repository 2>/dev/null) =~ true ]]; then
+        is_git_repo=1
+    fi
+    [[ $is_git_repo == 1 ]] || return
+
+    # We are in a Git repository.
+    local branch="$(git rev-parse --abbrev-ref HEAD 2>/dev/null)"
+    if [[ $branch == "HEAD" ]]; then
+        branch="detached*$(git rev-parse --short HEAD 2>/dev/null)"
+    fi
+    branch=${branch//\\/\\\\}  # Escape backslashes
+    branch=${branch//\$/\\\$}  # Escape dollars
+
+    local dirty
+    local staged
+    if [[ $branch != "detached*" &&
+          $GIT_PS1_SHOWDIRTYSTATE != 0 &&
+          $(git config --bool bash.showDirtyState) != "false" ]]; then
+        git diff --no-ext-diff --quiet --exit-code --ignore-submodules 2>/dev/null || dirty=$SEAFLY_GIT_DIRTY
+        git diff --no-ext-diff --quiet --cached --exit-code --ignore-submodules 2>/dev/null || staged=$SEAFLY_GIT_STAGED
+    fi
+
+    local stash
+    if [[ $GIT_PS1_SHOWSTASHSTATE != 0 ]]; then
+        git rev-parse --verify --quiet refs/stash >/dev/null && stash=$SEAFLY_GIT_STASH
+    fi
+
+    local upstream
+    if [[ $GIT_PS1_SHOWUPSTREAM != 0 ]]; then
+        case "$(git rev-list --left-right --count HEAD...@'{u}' 2>/dev/null)" in
+        "") # no upstream
+            upstream="" ;;
+        "0	0") # equal to upstream
+            upstream="=" ;;
+        "0	"*) # behind upstream
+            upstream=$SEAFLY_GIT_BEHIND ;;
+        *"	0") # ahead of upstream
+            upstream=$SEAFLY_GIT_AHEAD ;;
+        *)	    # diverged from upstream
+            upstream=$SEAFLY_GIT_DIVERGED ;;
+        esac
+    fi
+
+    local spacer
+    if [[ -n $dirty || -n $staged || -n $stash || -n $upstream ]]; then
+        spacer=" "
+    fi
+    _seafly_git=" $SEAFLY_GIT_PREFIX$branch$spacer\[$SEAFLY_ALERT_COLOR\]$dirty\[$SEAFLY_NORMAL_COLOR\]$staged$upstream\[$SEAFLY_GIT_COLOR\]$stash$SEAFLY_GIT_SUFFIX"
+}
+
+_seafly_command_prompt() {
+
+    # QNET: Custom Prompting
+    MSG="/tmp/prompt_msg"
+    if [[ -f "$MSG" ]]; then # var exists
+        if [[ -n "$MSG" ]]; then # not empty
+            cat "$MSG"
+            echo ''
+        fi
+    fi
+
+    # Run the pre-command if set.
+    eval $SEAFLY_PRE_COMMAND
+
+    local prompt_prefix
+    local prefix_value=$(eval $SEAFLY_PROMPT_PREFIX)
+    if [[ -n $prefix_value ]]; then
+        prompt_prefix="\[$SEAFLY_PREFIX_COLOR\]$prefix_value "
+    fi
+    if [[ $SEAFLY_MULTILINE = 1 ]]; then
+        prompt_prefix="\n$prompt_prefix"
+    fi
+
+    local prompt_start
+    if [[ $SEAFLY_SHOW_USER = 1 && $SEAFLY_SHOW_HOST = 1 ]]; then
+        prompt_start="\[$SEAFLY_HOST_COLOR\]\u@\h"
+    elif [[ $SEAFLY_SHOW_USER = 1 ]]; then
+        prompt_start="\[$SEAFLY_HOST_COLOR\]\u"
+    elif [[ $SEAFLY_SHOW_HOST = 1 ]]; then
+        prompt_start="\[$SEAFLY_HOST_COLOR\]\h"
+    fi
+
+    # Collate Git details, if applicable, for the current directory.
+    _seafly_git_optimized
+
+    local prompt_middle
+    if [[ $SEAFLY_LAYOUT = 1 ]]; then
+        prompt_middle="\[$SEAFLY_GIT_COLOR\]$_seafly_git\[$SEAFLY_PATH_COLOR\] \w"
+    else
+        prompt_middle="\[$SEAFLY_PATH_COLOR\] \w\[$SEAFLY_GIT_COLOR\]$_seafly_git"
+    fi
+    unset _seafly_git
+
+    # Normal prompt indicates that the last command ran successfully.
+    # Alert prompt indicates that the last command failed.
+    _seafly_colors=("$SEAFLY_ALERT_COLOR" "$SEAFLY_NORMAL_COLOR")
+
+    local prompt_end="\[\${_seafly_colors[\$((!\$?))]}\] $SEAFLY_PROMPT_SYMBOL\[\$NOCOLOR\] "
+    if [[ $SEAFLY_MULTILINE = 1 ]]; then
+        prompt_end="\n$prompt_end"
+    fi
+
+    PS1="$prompt_prefix$prompt_start$prompt_middle$prompt_end"
+    PS2="\[$SEAFLY_NORMAL_COLOR\]$SEAFLY_PS2_PROMPT_SYMBOL\[\$NOCOLOR\] "
+}
+
+# Use [gitstatus](https://github.com/romkatv/gitstatus) if it is available.
+if [[ -r $SEAFLY_GITSTATUS_DIR/gitstatus.plugin.sh ]]; then
+    source "$SEAFLY_GITSTATUS_DIR"/gitstatus.plugin.sh
+    gitstatus_stop && gitstatus_start -c 0 -d 0
+fi
+
+# Bind and call the '_seafly_command_prompt' function as the Bash prompt.
+PROMPT_COMMAND=_seafly_command_prompt

+ 17 - 0
scripts/chat

@@ -0,0 +1,17 @@
+#!/usr/bin/python3
+
+import os
+import sys
+
+URL = 'https://ch.at'
+
+# Usage & argument check
+if len(sys.argv) <= 1:
+    print(f'Usage: chat <query (STR): your question>')
+    sys.exit()
+
+user_input = sys.argv[1:]
+user_query = '+'.join(user_input)
+query_url = f'{URL}/?q={user_query}'
+
+os.system(f'curl "{query_url}"')

+ 35 - 0
scripts/convert-unixts

@@ -0,0 +1,35 @@
+#!/usr/bin/python3
+
+# Converts Unix Timestamp to HKT
+
+import sys
+import datetime
+
+def safe_cast(string):
+    try:
+        return int(string)
+    except ValueError:
+        print(f'Error: "{string}" is not a valid integer!')
+        sys.exit()
+
+# Check for user input
+if len(sys.argv) < 2:
+    print('Usage: convert-unixts <Timestamp: int>')
+    sys.exit()
+
+# Check for timestamp format 
+raw_input = sys.argv[1]
+if len(raw_input) < 10:
+    print('Invalid timestamp format! Less than 10 digits.')
+    sys.exit()
+else:
+    timestamp = safe_cast(raw_input)
+
+# Convert to UTC
+utc_time = datetime.datetime.utcfromtimestamp(timestamp)
+
+# Convert to HKT (UTC+8)
+hkt_time = utc_time + datetime.timedelta(hours=8)
+
+# Print the result
+print("HKT:", hkt_time.strftime('%Y-%m-%d %H:%M:%S'))

+ 73 - 0
scripts/life.sh

@@ -0,0 +1,73 @@
+#!/bin/bash
+
+RED="\033[41m  \033[0m"
+GREEN="\033[42m  \033[0m"
+GAP=" "
+
+if [ $# -lt 1 ]; then
+  echo "Usage: $0 birthdate [username]"
+  echo "Example: $0 1985-06-08 Joe"
+  exit 1
+fi
+
+birthdate=$1
+name=${2:-$USER}
+columns=${3:-20}
+
+life_expectancy=80
+last_year_index=$((life_expectancy - 1))
+
+case "$(uname)" in
+  "Linux")
+    birth_year=$(date -d "$birthdate" +"%Y")
+    birth_timestamp=$(date -d "$birthdate" +%s)
+    ;;
+  "Darwin")
+    birth_year=$(date -j -f "%Y-%m-%d" "$birthdate" +"%Y")
+    birth_timestamp=$(date -j -f "%Y-%m-%d" "$birthdate" +%s)
+    ;;
+  *) echo "Unsupported OS"; exit 1 ;;
+esac
+
+current_year=$(date +"%Y")
+current_timestamp=$(date +%s)
+years_passed=$((current_year - birth_year))
+weeks_passed=$(( (current_timestamp - birth_timestamp) / 604800 ))
+total_weeks=$((life_expectancy * 52))
+weeks_remaining=$((total_weeks - weeks_passed))
+
+echo -e "$name, only $weeks_remaining Sundays remain\n"
+
+rows=$((life_expectancy / columns))
+
+for (( row=0; row<rows; row++ )); do
+    for (( col=0; col<columns; col++ )); do
+        year_index=$((row * columns + col))
+          if (( year_index == 0 )); then
+            echo $birth_year
+          fi
+        if (( year_index < years_passed )); then
+            echo -ne "${RED}${GAP}"
+        else
+            echo -ne "${GREEN}${GAP}"
+        fi
+    done
+    echo
+    if (( year_index != $last_year_index )); then
+      echo
+    fi
+done
+
+# print spaces before last year
+gaps=$((columns - 1))
+squares=$((columns * 2))
+indent=$((gaps + squares - 4))
+for ((i=0; i<indent; i++)); do
+    echo -n ' '
+done
+
+last_year=$((birth_year + last_year_index))
+echo $last_year
+
+echo -e "\nHow are you going to spend these Sundays, $name?"
+