commit 4df49d16af0ee535a68ff85bf7182a0552a1c168
parent fffd5c7f5109234c4d0bf0c58dc648fc068dcd87
Author: Mahdi Mirzade <[email protected]>
Date: Sat, 8 Oct 2022 22:16:09 +0330
change builds to git submodules
Diffstat:
14 files changed, 678 insertions(+), 0 deletions(-)
diff --git a/.config/mutt/signature b/.config/mutt/signature
@@ -0,0 +1 @@
+Mahdi
diff --git a/.config/okshrc b/.config/okshrc
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+# Aliases
+for command in mount umount su vpn; do
+ alias $command="doas $command"
+done; unset command
+
+alias startx="startx \"$XINITRC\""
+
+alias \
+ ..='cd ..' \
+ ...='cd ../..' \
+ ....='cd ../../..'
+alias \
+ c="clear -x" \
+ d="doas" \
+ da="doas-askpass" \
+ e="$EDITOR" \
+ g="git" \
+ l="ls" \
+ la="ls -a" \
+ ll="ls -l" \
+ lla="ls -la" \
+ v="$EDITOR" \
+ x="exit"
+
+# Prompt
+RED=$(tput bold; tput setaf 1)
+GREEN=$(tput bold; tput setaf 2)
+YELLOW=$(tput bold; tput setaf 3)
+BLUE=$(tput bold; tput setaf 4)
+MAGENTA=$(tput bold; tput setaf 5)
+CYAN=$(tput bold; tput setaf 6)
+ERASE=$(tput sgr0)
+
+PROMPT_MINIMAL=0
+if [ "$(id -u)" -eq 0 ]; then
+ if [ "$PROMPT_MINIMAL" -eq 1 ]; then
+ PS1=' \[${YELLOW}\]\\w\[${ERASE}\] \[${RED}\]#\[${ERASE}\] '
+ else
+ PS1=' \[${RED}\]\\u\[${GREEN}\]@\[${RED}\]\\h\[${ERASE}\] \[${YELLOW}\]\\w\[${ERASE}\] \[${RED}\]#\[${ERASE}\] '
+ fi
+else
+ if [ "$PROMPT_MINIMAL" -eq 1 ]; then
+ PS1=' \[${YELLOW}\]\\w\[${ERASE}\] \[${BLUE}\]$\[${ERASE}\] '
+ else
+ PS1=' \[${BLUE}\]\\u\[${GREEN}\]@\[${BLUE}\]\\h\[${ERASE}\] \[${YELLOW}\]\\w\[${ERASE}\] \[${BLUE}\]$\[${ERASE}\] '
+ fi
+fi
+
+export PS1
diff --git a/.gitmodules b/.gitmodules
@@ -0,0 +1,18 @@
+[submodule ".local/src/dmenu"]
+ path = .local/src/dmenu
+ url = git://mahdi.pw/dmenu.git
+[submodule ".local/src/dwm"]
+ path = .local/src/dwm
+ url = git://mahdi.pw/dwm.git
+[submodule ".local/src/st"]
+ path = .local/src/st
+ url = git://mahdi.pw/st.git
+[submodule ".local/src/surf"]
+ path = .local/src/surf
+ url = git://mahdi.pw/surf.git
+[submodule ".local/src/slock"]
+ path = .local/src/slock
+ url = git://mahdi.pw/slock.git
+[submodule ".local/src/tabbed"]
+ path = .local/src/tabbed
+ url = git://mahdi.pw/tabbed.git
diff --git a/.local/bin/notify b/.local/bin/notify
@@ -0,0 +1,78 @@
+#!/bin/sh
+TEXT=$*
+[ "$TEXT" ] || TEXT=$(cat -u -)
+
+FONT="JetBrainsMono Nerd Font:pixelsize=12:antialias=true:autohint=true"
+WIDTH=$(($(printf '%s' "$TEXT" | \
+ awk 'length>max{max=length}END{print max}')*6+40))
+HEIGHT=40
+LINES=$(($(echo "$TEXT" | wc -l)-1))
+PADDING=40
+WAIT=5
+
+WIDTHxHEIGHT=$(xrandr | sed '/*/!d' |awk '{print $1;exit}')
+M_WIDTH=${WIDTHxHEIGHT%%x*}
+#M_HEIGHT=${WIDTHxHEIGHT##*x}
+
+N_WIDTH=$((M_WIDTH-WIDTH-PADDING))
+N_HEIGHT=$PADDING
+
+darken_hex(){
+ C=${1:-FFFFFF}
+ V=${2:-10}
+ if [ "$(printf '%s' "$C" | cut -c1-1)" = "#" ]; then
+ C=$(printf '%s' "$C" | cut -c2-8)
+ else
+ C=$1
+ fi
+ R=$(printf '%s' "$C" | awk '{print substr($0, 0, 2)}')
+ G=$(printf '%s' "$C" | awk '{print substr($0, 3, 2)}')
+ B=$(printf '%s' "$C" | awk '{print substr($0, 5, 2)}')
+ R=$(printf '%d' 0x"$R")
+ G=$(printf '%d' 0x"$G")
+ B=$(printf '%d' 0x"$B")
+ R=$((R+V))
+ G=$((G+V))
+ B=$((B+V))
+ if [ "$R" -lt 0 ]; then
+ R=0
+ elif [ "$R" -gt 255 ]; then
+ R=255
+ fi
+ if [ "$G" -lt 0 ]; then
+ G=0
+ elif [ "$G" -gt 255 ]; then
+ G=255
+ fi
+ if [ "$B" -lt 0 ]; then
+ B=0
+ elif [ "$B" -gt 255 ]; then
+ B=255
+ fi
+ printf "#%02X%02X%02X\n" "$R" "$G" "$B"
+}
+
+BG_COLOR=$(xrdb -query | awk '/background/{print $2;exit}')
+BG_COLOR=$(darken_hex "$BG_COLOR" "-5")
+
+FG_COLOR=$(xrdb -query | awk '/color12/{print $2;exit}')
+
+pkill dzen2
+(
+echo "^uncollapse()";
+printf '%s\n' "$TEXT" | while IFS= read -r NOTIF; do
+ echo "$NOTIF"
+done
+sleep $WAIT
+) | dzen2 \
+ -l $LINES \
+ -ta c \
+ -sa c \
+ -x $N_WIDTH \
+ -y $N_HEIGHT \
+ -w $WIDTH \
+ -h $HEIGHT \
+ -e 'button1=exit' \
+ -fn "$FONT" \
+ -bg "$BG_COLOR" \
+ -fg "$FG_COLOR" &
diff --git a/.local/bin/pash b/.local/bin/pash
@@ -0,0 +1,279 @@
+#!/bin/sh
+#
+# pash - simple password manager.
+# https://github.com/dylanaraps/pash
+
+pw_add() {
+ name=$1
+
+ if yn "Generate a password?"; then
+ # Generate a password by reading '/dev/urandom' with the
+ # 'tr' command to translate the random bytes into a
+ # configurable character set.
+ #
+ # The 'dd' command is then used to read only the desired
+ # password length.
+ #
+ # Regarding usage of '/dev/urandom' instead of '/dev/random'.
+ # See: https://www.2uo.de/myths-about-urandom
+ pass=$(LC_ALL=C tr -dc "${PASH_PATTERN:-_A-Z-a-z-0-9}" < /dev/urandom |
+ dd ibs=1 obs=1 count="${PASH_LENGTH:-50}" 2>/dev/null)
+
+ else
+ # 'sread()' is a simple wrapper function around 'read'
+ # to prevent user input from being printed to the terminal.
+ sread pass "Enter password"
+ sread pass2 "Enter password (again)"
+
+ # Disable this check as we dynamically populate the two
+ # passwords using the 'sread()' function.
+ # shellcheck disable=2154
+ [ "$pass" = "$pass2" ] || die "Passwords do not match"
+ fi
+
+ [ "$pass" ] || die "Failed to generate a password"
+
+ # Mimic the use of an array for storing arguments by... using
+ # the function's argument list. This is very apt isn't it?
+ if [ "$PASH_KEYID" ]; then
+ set -- --trust-model always -aer "$PASH_KEYID"
+ else
+ set -- -c
+ fi
+
+ # Use 'gpg' to store the password in an encrypted file.
+ # A heredoc is used here instead of a 'printf' to avoid
+ # leaking the password through the '/proc' filesystem.
+ #
+ # Heredocs are sometimes implemented via temporary files,
+ # however this is typically done using 'mkstemp()' which
+ # is more secure than a leak in '/proc'.
+ "$gpg" "$@" -o "$name.gpg" <<-EOF &&
+ $pass
+ EOF
+ printf '%s\n' "Saved '$name' to the store."
+}
+
+pw_del() {
+ yn "Delete pass file '$1'?" && {
+ rm -f "$1.gpg"
+
+ # Remove empty parent directories of a password
+ # entry. It's fine if this fails as it means that
+ # another entry also lives in the same directory.
+ rmdir -p "${1%/*}" 2>/dev/null || :
+ }
+}
+
+pw_show() {
+ "$gpg" -dq "$1.gpg"
+}
+
+pw_copy() {
+ # Disable warning against word-splitting as it is safe
+ # and intentional (globbing is disabled).
+ # shellcheck disable=2086
+ : "${PASH_CLIP:=xclip -sel c}"
+
+ # Wait in the background for the password timeout and
+ # clear the clipboard when the timer runs out.
+ #
+ # If the 'sleep' fails, kill the script. This is the
+ # simplest method of aborting from a subshell.
+ [ "$PASH_TIMEOUT" != off ] && {
+ printf 'Clearing clipboard in "%s" seconds.\n' "${PASH_TIMEOUT:=15}"
+
+ sleep "$PASH_TIMEOUT" || kill 0
+ $PASH_CLIP </dev/null
+ } &
+
+ pw_show "$1" | $PASH_CLIP
+}
+
+pw_list() {
+ find . -type f -name \*.gpg | sed 's/..//;s/\.gpg$//'
+}
+
+pw_tree() {
+ # This is a simple 'tree' implementation based around
+ # Minus the 'find' and 'sort' calls to grab the recursive
+ # file list, this is entirely shell!
+ items=$(find . -mindepth 1 | sort)
+ items_count=$(echo "$items" | wc -l)
+ count=1
+ echo "$items" | while read -r item; do
+ glob "$item" './.*' && continue
+
+ path=${item##./}
+ path=${path%%.gpg}
+
+
+ [ -d "$item" ] && suffix=/ || suffix=
+
+ # Split the string on each forward slash to count the
+ # "nest level" of each file and directory.
+ #
+ # The shift is added as the resulting count will always
+ # be one higher than intended.
+ #
+ # Disable warning about word splitting as it is
+ # intentional here and globbing is disabled.
+ # shellcheck disable=2086
+ {
+ IFS=/
+ set -- $path
+ shift
+ }
+
+ # Print the dividers from 1-nest_level. This is a simple
+ # iteration over the shifted argument list.
+ for _; do printf '│ '; done
+
+ [ "$count" -eq "$items_count" ] && {
+ printf '└── %s\n' "${path##*/}${suffix}"
+ break
+ }
+ printf '├── %s\n' "${path##*/}${suffix}"
+ count=$((count+1))
+ done
+}
+
+yn() {
+ printf '%s [y/n]: ' "$1"
+
+ # Enable raw input to allow for a single byte to be read from
+ # stdin without needing to wait for the user to press Return.
+ stty -icanon
+
+ # Read a single byte from stdin using 'dd'. POSIX 'read' has
+ # no support for single/'N' byte based input from the user.
+ answer=$(dd ibs=1 count=1 2>/dev/null)
+
+ # Disable raw input, leaving the terminal how we *should*
+ # have found it.
+ stty icanon
+
+ printf '\n'
+
+ # Handle the answer here directly, enabling this function's
+ # return status to be used in place of checking for '[yY]'
+ # throughout this program.
+ glob "$answer" '[yY]'
+}
+
+sread() {
+ printf '%s: ' "$2"
+
+ # Disable terminal printing while the user inputs their
+ # password. POSIX 'read' has no '-s' flag which would
+ # effectively do the same thing.
+ stty -echo
+ read -r "$1"
+ stty echo
+
+ printf '\n'
+}
+
+glob() {
+ # This is a simple wrapper around a case statement to allow
+ # for simple string comparisons against globs.
+ #
+ # Example: if glob "Hello World" '* World'; then
+ #
+ # Disable this warning as it is the intended behavior.
+ # shellcheck disable=2254
+ case $1 in $2) return 0; esac; return 1
+}
+
+die() {
+ printf 'error: %s.\n' "$1" >&2
+ exit 1
+}
+
+usage() { printf %s "\
+pash 2.3.0 - simple password manager.
+
+=> [a]dd [name] - Create a new password entry.
+=> [c]opy [name] - Copy entry to the clipboard.
+=> [d]el [name] - Delete a password entry.
+=> [l]ist - List all entries.
+=> [s]how [name] - Show password for an entry.
+=> [t]ree - List all entries in a tree.
+
+Using a key pair: export PASH_KEYID=XXXXXXXX
+Password length: export PASH_LENGTH=50
+Password pattern: export PASH_PATTERN=_A-Z-a-z-0-9
+Store location: export PASH_DIR=~/.local/share/pash
+Clipboard tool: export PASH_CLIP='xclip -sel c'
+Clipboard timeout: export PASH_TIMEOUT=15 ('off' to disable)
+"
+exit 0
+}
+
+main() {
+ : "${PASH_DIR:=${XDG_DATA_HOME:=$HOME/.local/share}/pash}"
+
+ # Look for both 'gpg' and 'gpg2',
+ # preferring 'gpg2' if it is available.
+ command -v gpg >/dev/null 2>&1 && gpg=gpg
+ command -v gpg2 >/dev/null 2>&1 && gpg=gpg2
+
+ [ "$gpg" ] ||
+ die "GPG not found"
+
+ mkdir -p "$PASH_DIR" ||
+ die "Couldn't create password directory"
+
+ cd "$PASH_DIR" ||
+ die "Can't access password directory"
+
+ glob "$1" '[acds]*' && [ -z "$2" ] &&
+ die "Missing [name] argument"
+
+ glob "$1" '[cds]*' && [ ! -f "$2.gpg" ] &&
+ die "Pass file '$2' doesn't exist"
+
+ glob "$1" 'a*' && [ -f "$2.gpg" ] &&
+ die "Pass file '$2' already exists"
+
+ glob "$2" '*/*' && glob "$2" '*../*' &&
+ die "Category went out of bounds"
+
+ glob "$2" '/*' &&
+ die "Category can't start with '/'"
+
+ glob "$2" '*/*' && { mkdir -p "${2%/*}" ||
+ die "Couldn't create category '${2%/*}'"; }
+
+ # Set 'GPG_TTY' to the current 'TTY' if it
+ # is unset. Fixes a somewhat rare `gpg` issue.
+ export GPG_TTY=${GPG_TTY:-$(tty)}
+
+ # Restrict permissions of any new files to
+ # only the current user.
+ umask 077
+
+ # Ensure that we leave the terminal in a usable
+ # state on exit or Ctrl+C.
+ [ -t 1 ] && trap 'stty echo icanon' INT EXIT
+
+ case $1 in
+ a*) pw_add "$2" ;;
+ c*) pw_copy "$2" ;;
+ d*) pw_del "$2" ;;
+ s*) pw_show "$2" ;;
+ l*) pw_list ;;
+ t*) pw_tree ;;
+ *) usage
+ esac
+}
+
+# Ensure that debug mode is never enabled to
+# prevent the password from leaking.
+set +x
+
+# Ensure that globbing is globally disabled
+# to avoid insecurities with word-splitting.
+set -f
+
+[ "$1" ] || usage && main "$@"
diff --git a/.local/bin/snd b/.local/bin/snd
@@ -0,0 +1,175 @@
+#!/bin/sh
+AUDIO_ACT="get"
+AUDIO_STEPS="5"
+AUDIO_NOTIF=0
+
+while getopts ':ngidmGIDMs:' flag; do
+ case "${flag}" in
+ n) AUDIO_NOTIF=1 ;;
+ g) AUDIO_ACT="get" ;;
+ i) AUDIO_ACT="inc" ;;
+ d) AUDIO_ACT="dec" ;;
+ m) AUDIO_ACT="mute" ;;
+ G) AUDIO_ACT="mic-get" ;;
+ I) AUDIO_ACT="mic-inc" ;;
+ D) AUDIO_ACT="mic-dec" ;;
+ M) AUDIO_ACT="mic-mute" ;;
+ s) AUDIO_STEPS="${OPTARG}" ;;
+ *)
+ printf 'Usage: %s [-g] [-d] [-i] [-m] [-G] [-D] [-I] [-M] [-s audio steps (in %%)]\n' "$0"
+ printf ' -g: get volume\n'
+ printf ' -i: increase volume\n'
+ printf ' -d: decrease volume\n'
+ printf ' -m: mute volume\n'
+ printf ' -G: get mic volume\n'
+ printf ' -I: increase mic volume\n'
+ printf ' -D: decrease mic volume\n'
+ printf ' -M: mute mic volume\n'
+ exit 2
+ ;;
+ esac
+done
+
+vol() {
+ case "$(uname)" in
+ "Linux"*)
+ if pactl stat >/dev/null 2>&1; then
+ case "$1" in
+ get) pactl get-sink-volume @DEFAULT_SOURCE@ | awk '/%/{sub(/%/, "", $5);print $5}' ;;
+ inc) pactl set-sink-volume @DEFAULT_SINK@ "+$2%" ;;
+ dec) pactl set-sink-volume @DEFAULT_SINK@ "-$2%" ;;
+ mute) pactl set-sink-mute @DEFAULT_SINK@ toggle ;;
+ ismuted) pactl get-sink-mute @DEFAULT_SOURCE@ | grep -o 'yes' ;;
+ mic-get) pactl get-source-volume @DEFAULT_SOURCE@ | awk '/%/{sub(/%/, "", $5);print $5}' ;;
+ mic-inc) pactl set-source-volume @DEFAULT_SINK@ "+$2%" ;;
+ mic-dec) pactl set-source-volume @DEFAULT_SINK@ "-$2%" ;;
+ mic-mute) pactl set-source-mute @DEFAULT_SINK@ toggle ;;
+ mic-ismuted) pactl get-source-mute @DEFAULT_SOURCE@ | grep -o 'yes' ;;
+ esac
+ else
+ case "$1" in
+ get) amixer get Master on | grep -o '[0-9]*%' | sed 's/%//' | sed -n '1p' ;;
+ inc) amixer set Master "$2%+" on -q ;;
+ dec) amixer set Master "$2%-" on -q ;;
+ mute) amixer set Master 1+ toggle -q ;;
+ ismuted) amixer get Master on | grep -o '\[off\]' ;;
+ mic-get) amixer get Capture on | grep -o '[0-9]*%' | sed 's/%//' | sed -n '1p' ;;
+ mic-inc) amixer set Capture "$2%+" on -q ;;
+ mic-dec) amixer set Capture "$2%-" on -q ;;
+ mic-mute) amixer set Capture 1+ toggle -q ;;
+ mic-ismuted) amixer get Capture on | grep -o '\[off\]' ;;
+ esac
+ fi
+ ;;
+ "FreeBSD"*)
+ case "$1" in
+ get) mixer -s vol | cut -d ':' -f 2 ;;
+ inc) mixer -s vol "+$2%" ;;
+ dec) mixer -s vol "-$2%" ;;
+ mute)
+ if [ "$(vol get)" -eq 0 ]; then
+ mixer -s vol 75
+ else
+ mixer -s vol 0
+ fi
+ ;;
+ ismuted) [ "$(vol get)" -eq 0 ] && echo yes ;;
+ mic-get) mixer -s mic | cut -d ':' -f 2 ;;
+ mic-inc) mixer -s mic "+$2%" ;;
+ mic-dec) mixer -s mic "-$2%" ;;
+ mic-mute)
+ if [ "$(vol mic-get)" -eq 0 ]; then
+ mixer -s mic 35
+ else
+ mixer -s mic 0
+ fi
+ ;;
+ mic-ismuted) [ "$(vol mic-get)" -eq 0 ] && echo yes ;;
+ esac
+ ;;
+ esac
+}
+
+notif() {
+ case "$AUDIO_ACT" in
+ mic)
+ VOLUME=$(vol mic-get)
+ IS_MUTED=$(vol mic-ismuted)
+ VOLUME_ICON_0=""
+ VOLUME_ICON_1=""
+ VOLUME_ICON_2=""
+ VOLUME_ICON_3=""
+ ;;
+ *)
+ VOLUME=$(vol get)
+ IS_MUTED=$(vol ismuted)
+ VOLUME_ICON_0="ﱝ"
+ VOLUME_ICON_1=""
+ VOLUME_ICON_2=""
+ VOLUME_ICON_3=""
+ ;;
+ esac
+ if [ "$IS_MUTED" ] || [ "$VOLUME" -eq 0 ]; then
+ VOLUME="Muted"
+ VOLUME_ICON=$VOLUME_ICON_0
+ elif [ "$VOLUME" -lt 30 ]; then
+ VOLUME_ICON=$VOLUME_ICON_1
+ elif [ "$VOLUME" -lt 70 ]; then
+ VOLUME_ICON=$VOLUME_ICON_2
+ else
+ VOLUME_ICON=$VOLUME_ICON_3
+ fi
+ notify "$VOLUME_ICON $VOLUME"
+}
+
+case "$AUDIO_ACT" in
+ inc)
+ CURRENT_VOLUME=$(vol get)
+ REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS))
+ AUDIO_STEPS=$((AUDIO_STEPS-REMAINDER))
+ ;;
+ dec)
+ CURRENT_VOLUME=$(vol get)
+ REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS))
+ AUDIO_STEPS=$((AUDIO_STEPS+REMAINDER))
+ ;;
+ mic-inc)
+ CURRENT_VOLUME=$(vol mic-get)
+ REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS))
+ AUDIO_STEPS=$((AUDIO_STEPS-REMAINDER))
+ ;;
+ mic-dec)
+ CURRENT_VOLUME=$(vol mic-get)
+ REMAINDER=$((CURRENT_VOLUME%AUDIO_STEPS))
+ AUDIO_STEPS=$((AUDIO_STEPS+REMAINDER))
+ ;;
+esac
+
+case "$AUDIO_ACT" in
+ get)
+ vol get
+ ;;
+ inc)
+ vol inc "$AUDIO_STEPS"
+ ;;
+ dec)
+ vol dec "$AUDIO_STEPS"
+ ;;
+ mute)
+ vol mute
+ ;;
+ mic-get)
+ vol mic-get
+ ;;
+ mic-inc)
+ vol mic-inc "$AUDIO_STEPS"
+ ;;
+ mic-dec)
+ vol mic-dec "$AUDIO_STEPS"
+ ;;
+ mic-mute)
+ vol mic-mute
+ ;;
+esac
+
+[ "$AUDIO_NOTIF" -eq 1 ] && notif
diff --git a/.local/bin/torrent-from-clip b/.local/bin/torrent-from-clip
@@ -0,0 +1,15 @@
+#!/bin/sh
+while :; do
+ clip=$(xclip -selection c -o)
+ case "$clip" in
+ magnet:*)
+ url=$(cat ~/.cache/url.txt || echo 0)
+ if [ "$url" != "$clip" ]; then
+ qbittorrent-nox "$clip"
+ echo "$clip" > ~/.cache/url.txt
+ notify "Added Torrent
+$clip"
+ fi
+ ;;
+ esac
+done
diff --git a/.local/src/dmenu b/.local/src/dmenu
@@ -0,0 +1 @@
+Subproject commit c61036548411483a6284f095a028930f76bbd834
diff --git a/.local/src/dwm b/.local/src/dwm
@@ -0,0 +1 @@
+Subproject commit a2f05d7af4cb17f58d1e3b6b0c8980d410752b9d
diff --git a/.local/src/slock b/.local/src/slock
@@ -0,0 +1 @@
+Subproject commit 072324b905878281552e0b5fb34f60f8dfe5c2bd
diff --git a/.local/src/st b/.local/src/st
@@ -0,0 +1 @@
+Subproject commit 4687ea1b0505dacb908060b42d901e8b7bd05fb4
diff --git a/.local/src/surf b/.local/src/surf
@@ -0,0 +1 @@
+Subproject commit 107fe086707b94e94990f2b83d83d13c47c3e32c
diff --git a/.local/src/tabbed b/.local/src/tabbed
@@ -0,0 +1 @@
+Subproject commit 1fea079791467a8168303a99f247ea0f8cbaf972
diff --git a/.profile b/.profile
@@ -0,0 +1,55 @@
+#!/bin/sh
+# Environmental variables are set here. (Runs on login)
+
+# Add `~/.local/bin/*` to $PATH
+[ -d "$HOME/.local/bin" ] && \
+ export PATH=$PATH:$(find "$HOME/.local/bin" -type d | \
+ sed ':a;N;$!ba;s/\n/:/g')
+
+# Default Programs
+export BROWSER="surf-open"
+export EDITOR="vis"
+export TERMINAL="st"
+
+# XDG_BASE_DIRS
+export XDG_CACHE_HOME=$HOME/.cache
+export XDG_CONFIG_HOME=$HOME/.config
+export XDG_DATA_HOME=$HOME/.local/share
+export XDG_STATE_HOME=$HOME/.local/state
+export XDG_RUNTIME_DIR=$HOME/.local/run
+
+# Create XDG_BASE_DIRS, if not exists
+[ -d "$XDG_DATA_HOME" ] || mkdir -p "$XDG_DATA_HOME"
+[ -d "$XDG_STATE_HOME" ] || mkdir -p "$XDG_STATE_HOME"
+[ -d "$XDG_CACHE_HOME" ] || mkdir -p "$XDG_CACHE_HOME"
+[ -d "$XDG_RUNTIME_DIR" ] || mkdir -p "$XDG_RUNTIME_DIR"
+[ -d "$XDG_CONFIG_HOME" ] || mkdir -p "$XDG_CONFIG_HOME"
+
+# Store shell's name to $SH
+SH=${0:-$SHELL}
+SH=${SH##*/}
+SH=${SH#-}
+
+# Use $XDG_CONFIG_HOME for disrespectful programs
+export GNUPGHOME=${XDG_DATA_HOME:-$HOME/.local/share}/gnupg
+export GTK2_RC_FILES=${XDG_CONFIG_HOME:-$HOME/.config}/gtk-2.0/gtkrc-2.0
+export HISTFILE=${XDG_DATA_HOME:-$HOME/.local/share}/history.$SH
+export INPUTRC=${XDG_CONFIG_HOME:-$HOME/.config}/shell/inputrc
+export MBSYNCRC=${XDG_CONFIG_HOME:-$HOME/.config}/mbsync/mbsyncrc
+export PASSWORD_STORE_DIR=${XDG_DATA_HOME:-$HOME/.local/share}/password-store
+export PYTHONSTARTUP=${XDG_CONFIG_HOME:-$HOME/.config}/pythonrc
+export WGETRC=${XDG_CONFIG_HOME:-$HOME/.config}/wget/wgetrc
+export LESSHISTFILE=${XDG_DATA_HOME:-$HOME/.local/share}/lesshst
+export XAUTHORITY=${XDG_RUNTIME_DIR:-$HOME/.local/run}/Xauthority
+export XINITRC=${XDG_CONFIG_HOME:-$HOME/.config}/x11/xinitrc
+
+# Misc
+# : Source $HOME/.config/okshrc (or your own shell)
+export ENV=${XDG_CONFIG_HOME:-$HOME/.config}/${SH}rc
+# : Use Unix's password-store's files for pash
+export PASH_DIR=${PASSWORD_STORE_DIR:-$HOME/.password-store}
+
+# Start X
+if [ "$(tty)" = "/dev/tty1" ] || [ "$(tty)" = "/dev/ttyv0" ]; then
+ startx "$XINITRC"
+fi