From 19120d4f9761c67d99ed1ce3da6084b83f5a49c9 Mon Sep 17 00:00:00 2001 From: srdusr Date: Sat, 30 Aug 2025 19:22:59 +0200 Subject: Linux-specific dotfiles --- linux/home/.config/zsh/.zshenv | 348 ++++++++++++ linux/home/.config/zsh/.zshrc | 63 +++ linux/home/.config/zsh/user/aliases.zsh | 129 +++++ linux/home/.config/zsh/user/bindings.zsh | 39 ++ linux/home/.config/zsh/user/completion.zsh | 156 ++++++ linux/home/.config/zsh/user/functions.zsh | 813 +++++++++++++++++++++++++++++ linux/home/.config/zsh/user/options.zsh | 50 ++ linux/home/.config/zsh/user/prompt.zsh | 202 +++++++ 8 files changed, 1800 insertions(+) create mode 100644 linux/home/.config/zsh/.zshenv create mode 100644 linux/home/.config/zsh/.zshrc create mode 100644 linux/home/.config/zsh/user/aliases.zsh create mode 100644 linux/home/.config/zsh/user/bindings.zsh create mode 100644 linux/home/.config/zsh/user/completion.zsh create mode 100644 linux/home/.config/zsh/user/functions.zsh create mode 100644 linux/home/.config/zsh/user/options.zsh create mode 100644 linux/home/.config/zsh/user/prompt.zsh (limited to 'linux/home/.config/zsh') diff --git a/linux/home/.config/zsh/.zshenv b/linux/home/.config/zsh/.zshenv new file mode 100644 index 0000000..1d6eee9 --- /dev/null +++ b/linux/home/.config/zsh/.zshenv @@ -0,0 +1,348 @@ +# Load local/system wide binaries and scripts +export PATH=$HOME/.bin:$HOME/.local/bin:$HOME/.scripts:$HOME/.scripts/test:/usr/local/bin:/sbin:/usr/sbin:$PATH +export PATH="/data/data/com.termux/files/usr/local/bin:$PATH" + +if [ -d "$HOME/.scripts" ]; then + for d in "$HOME/.scripts"/*; do + [ -d "$d" ] && PATH="$PATH:$d" + done +fi + +#export PATH + +export TERM=xterm-256color +# Skip the not really helpful global compinit +skip_global_compinit=1 + +#export WINEARCH=win64 # +#export WINEPREFIX=~/.wine +#export PATH=$PATH:/usr/bin/wine +#winetricks vcrun2019 +### Conditionally set WM(window manager) +#available_wms=("bspwm" "mutter" "i3") +#for wm in "${available_wms[@]}"; do +# if command -v "$wm" &> /dev/null; then +# export WM="$wm" +# break +# fi +#done + +## Set a flag to indicate if the display server type is found +#display_server_found=0 +# +## Conditionally set Display server +#available_displays=("wayland" "x11") +#for display in "${available_displays[@]}"; do +# if [ "$WAYLAND_DISPLAY" = "$display" ]; then +# export XDG_SESSION_TYPE="$display" +# display_server_found=1 +# break +# fi +#done +# +## Check if XDG_SESSION_TYPE is "x11" and set X11-specific variables +#if [ "$display_server_found" -eq 1 ] && [ "$XDG_SESSION_TYPE" == "x11" ]; then +# # X11-specific variables +# export XINITRC="$HOME/.config/X11/.xinitrc" +# export XSERVERRC="$XDG_CONFIG_HOME/X11/xserverrc" +# export USERXSESSION="$XDG_CONFIG_HOME/X11/xsession" +# export USERXSESSIONRC="$XDG_CONFIG_HOME/X11/xsessionrc" +# export ALTUSERXSESSION="$XDG_CONFIG_HOME/X11/Xsession" +# export ERRFILE="$XDG_CONFIG_HOME/X11/xsession-errors" +# export ICEAUTHORITY="$XDG_CACHE_HOME/.ICEauthority" +#fi + +# Conditionally set default term +available_terms=("wezterm" "alacritty" "xterm") +for term in "${available_terms[@]}"; do + if command -v "$term" &> /dev/null; then + export TERMINAL="$term" + break + fi +done + +# Default Programs: +export EDITOR=$(command -v nvim || echo "vim") +#if command -v nvim &> /dev/null; then +# export EDITOR=nvim +#else +# export EDITOR=vim +#fi +export VISUAL=$EDITOR +export GIT_EDITOR="$EDITOR" +export COLORTERM="truecolor" +export TERM="xterm-256color" +export READER="zathura" +export BROWSER="firefox" +export OPENER="xdg-open" +#export MANPAGER="$EDITOR +Man!" +#if [ "$EDITOR" = "nvim" ]; then +if command -v nvim &> /dev/null; then + #export MANPAGER="sh -c 'col -b | nvim -c \"set ft=man ts=8 nomod nolist nonu noma\" -c \"autocmd VimEnter * call feedkeys(\\\"q\\\")\" -'" + export MANPAGER="sh -c 'col -b | nvim -c \"set ft=man ts=8 nomod nolist nonu noma\" -c \"autocmd VimEnter * call feedkeys(\\\"\\q\\\")\" -'" + #export MANPAGER="$nvim --clean -n -i NONE -u NORC -c 'colorscheme desert' -c 'highlight Normal ctermbg=NONE guibg=NONE' +Man\!" +else + export MANPAGER="bat" + #export MANPAGER="less -R --use-color -Dd+r -Du+b" + #export MANPAGER="sh -c 'col -bx | bat -l man -p --pager \"less -R\"'" +fi +export MANROFFOPT="-c" +export PAGER="less" +export SUDO_ASKPASS=/usr/lib/ssh/x11-ssh-askpass +export FAQ_STYLE='github' +export VIDEO="mpv" +export IMAGE="phototonic" + +# XDG Paths: +export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:-$HOME/.config} +export XDG_DATA_HOME=${XDG_DATA_HOME:-$HOME/.local/share} +export XDG_CACHE_HOME=${XDG_CACHE_HOME:-$HOME/.cache} +export INPUTRC="${XDG_CONFIG_HOME:-$HOME/.config}/inputrc" +export ZDOTDIR="$XDG_CONFIG_HOME/zsh" +export HISTFILE="$ZDOTDIR/.zhistory" # History filepath +export HISTSIZE=1000000 # Maximum events for internal history +export SAVEHIST=1000000 # Maximum events in history file +export BANG_HIST # Treat the '!' character specially during expansion. +export EXTENDED_HISTORY # Write the history file in the ":start:elapsed;command" format. +export INC_APPEND_HISTORY # Write to the history file immediately, not when the shell exits. +export SHARE_HISTORY # Share history between all sessions. +export HIST_EXPIRE_DUPS_FIRST # Expire duplicate entries first when trimming history. +export HIST_IGNORE_DUPS # Don't record an entry that was just recorded again. +export HIST_IGNORE_ALL_DUPS # Delete old recorded entry if new entry is a duplicate. +export HIST_FIND_NO_DUPS # Do not display a line previously found. +export HIST_IGNORE_SPACE # Don't record an entry starting with a space. +export HIST_SAVE_NO_DUPS # Don't write duplicate entries in the history file. +export HIST_REDUCE_BLANKS # Remove superfluous blanks before recording entry. +export HIST_VERIFY # Don't execute immediately upon history expansion. +export HIST_BEEP # Beep when accessing nonexistent history. +export INC_APPEND_HISTORY + +# Customize `ls` colours +export LSCOLORS=ExGxBxDxCxEgEdxbxgxcxd + +# Other XDG paths: +export RIPGREP_CONFIG_PATH="$XDG_CONFIG_HOME/ripgrep/ripgreprc" +export DOCKER_CONFIG="$XDG_CONFIG_HOME/docker" +export VSCODE_PORTABLE="$XDG_DATA_HOME/vscode" +export GTK2_RC_FILES="$XDG_CONFIG_HOME/gtk-2.0/gtkrc" +export PATH="/usr/bin/cmake:$PATH" +export PATH=$PATH:/opt/google/chrome +export DISCORD_USER_DATA_DIR="$XDG_DATA_HOME" +export LYNX_CFG="$XDG_CONFIG_HOME/.lynxrc" + +# Manage Arch linux build sources +export ASPROOT="${XDG_CACHE_HOME:-$HOME/.cache}/asp" + +# Homebrew +#export PATH=/opt/homebrew/bin:$PATH +export PATH="/opt/homebrew/sbin:$PATH" + +# Nix-profile +export PATH=$HOME/.nix-profile/bin:$PATH + +# GnuPG +export GPG_TTY=$(tty) +#export GNUPGHOME="$XDG_CONFIG_HOME/gnupg" + +# Nvim +export NVIM_TUI_ENABLE_TRUE_COLOR=1 + +# Fzf +export FZF_DEFAULT_COMMAND="rg --files --hidden --glob '!{node_modules/*,.git/*}'" +export FZF_CTRL_T_COMMAND="$FZF_DEFAULT_COMMAND" +export FZF_DEFAULT_OPTS='-m --height 50% --border' + + +# enable git scripts +export DEVELOPMENT_DIRECTORY="$HOME/code" + +# Android Home +export ANDROID_HOME=/opt/android-sdk +export PATH=$ANDROID_HOME/cmdline-tools/latest/bin:$PATH +#export PATH=$ANDROID_HOME/cmdline-tools/bin:$PATH +export PATH=$ANDROID_HOME/tools:$PATH +export PATH=$ANDROID_HOME/tools/bin:$PATH +export PATH=$ANDROID_HOME/platform-tools:$PATH +# Android emulator PATH +export PATH=$ANDROID_HOME/emulator:$PATH +# Android SDK ROOT PATH +export ANDROID_SDK_ROOT=/opt/android-sdk +export PATH=$ANDROID_SDK_ROOT:$PATH +#export ANDROID_SDK_HOME="${XDG_CONFIG_HOME:-$HOME/.config}/android" + +# Programming Environment Variables: + +# Rust +export RUSTUP_HOME=${XDG_DATA_HOME:-$HOME/.local/share}/rustup +export CARGO_HOME=${XDG_DATA_HOME:-$HOME/.local/share}/cargo +export PATH="${CARGO_HOME}/bin:${RUSTUP_HOME}/bin:$PATH" +#export PATH="$PATH:$CARGO_HOME/bin" +#[[ -d $CARGO_HOME/bin ]] && path=($CARGO_HOME/bin $path) +if which rustc > /dev/null; then export RUST_BACKTRACE=1; fi +#export PATH="$HOME/.cargo/bin:$PATH" +#export CARGO_HOME=${XDG_DATA_HOME}/cargo +#export RUSTUP_HOME=${XDG_DATA_HOME}/rustup + + +# Dotnet +# # Currently dotnet does not support XDG ( https://github.com/dotnet/sdk/issues/10390 ) +#export DOTNET_TOOLS_DIR="$HOME/.dotnet/tools" +export DOTNET_HOME=${XDG_DATA_HOME:-$HOME/.local/share}/dotnet +export DOTNET_CLI_HOME="$XDG_CONFIG_HOME/dotnet" +#mkdir -p "$DOTNET_CLI_HOME"; +export PATH="$PATH":"$DOTNET_HOME"/tools +export DOTNET_ROOT=/opt/dotnet +# Disable telemetry for dotnet apps +export DOTNET_CLI_TELEMETRY_OPTOUT=1 + + +# Java +#export JAVA_HOME=/usr/lib/jvm/default-java +#export JAVA_HOME='/usr/lib/jvm/java-8-openjdk' +#export JAVA_HOME='/usr/lib/jvm/java-10-openjdk' +#export JAVA_HOME='/usr/lib/jvm/java-11-openjdk' +#export JAVA_HOME='/usr/lib/jvm/java-17-openjdk' +export JAVA_HOME='/usr/lib/jvm/java-20-openjdk' +#export PATH=$JAVA_HOME/bin:$PATH +export _JAVA_OPTIONS=-Djava.util.prefs.userRoot="$XDG_CONFIG_HOME"/java +#export DEFAULT_JVM_OPTS='"-Dcom.android.sdklib.toolsdir=$APP_HOME" -XX:+IgnoreUnrecognizedVMOptions' +#export _JAVA_AWT_WM_NONREPARENTING=1 +#export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee' +#export JAVA_OPTS='-XX:+IgnoreUnrecognizedVMOptions --add-modules java.xml.bind' +#Windows: +#set JAVA_OPTS=-XX:+IgnoreUnrecognizedVMOptions --add-modules java.se.ee + + +# Dart/Flutter +export PATH="/opt/flutter/bin:/usr/lib/dart/bin:$PATH" + + +# Go +export GO_PATH=${XDG_DATA_HOME}/go +export GOPATH="${XDG_DATA_HOME:-$HOME/.local/share}/go" + + +# Javascript +# NVM +export NVM_DIR="$HOME/.config/nvm" +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" +#[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm + +# global node installs (gross) +[[ -d "$XDG_DATA_HOME/node/bin" ]] && path=($XDG_DATA_HOME/node/bin $path) +export NODE_REPL_HISTORY="$XDG_DATA_HOME"/node_repl_history +export NPM_CONFIG_USERCONFIG=$XDG_CONFIG_HOME/npm/npmrc +#export NPM_CONFIG_INIT_AUTHOR_NAME='srdusr' +#export NPM_CONFIG_INIT_AUTHOR_EMAIL='trevorgray@srdusr.com' +#export NPM_CONFIG_INIT_AUTHOR_URL='https://srdusr.com' +#export NPM_CONFIG_INIT_LICENSE='GPL-3.0' +#export NPM_CONFIG_INIT_VERSION='0.0.0' +#export NPM_CONFIG_SIGN_GIT_TAG='true' + +# Yarn +#if command -v yarn >/dev/null 2>&1; then +# export PATH="$PATH:`yarn global bin`" +#fi +#export PATH="$(yarn global bin):$PATH" +#YARN_PATH="$HOME/.yarn/bin" +#YARN_BIN_EXPORT="$HOME/.config/yarn/global/node_modules/.bin" + +# Ruby +export GEM_PATH="$XDG_DATA_HOME/ruby/gems" +export GEM_SPEC_CACHE="$XDG_DATA_HOME/ruby/specs" +export GEM_HOME="$XDG_DATA_HOME/ruby/gems" +#if [[ -d ~/.gem/ruby ]]; then +# ver=$(find ~/.gem/ruby/* -maxdepth 0 | sort -rV | head -n 1) +# export PATH="$PATH:${ver}/bin" +#fi + + +# Python +# lazy load pyenv +#export PYENV_ROOT=${PYENV_ROOT:-$HOME/.pyenv} +#[[ -a $PYENV_ROOT/bin/pyenv ]] && path=($PYENV_ROOT/bin $path) +#if type pyenv &> /dev/null || [[ -a $PYENV_ROOT/bin/pyenv ]]; then +# function pyenv() { +# unset pyenv +# path=($PYENV_ROOT/shims $path) +# eval "$(command pyenv init -)" +# if which pyenv-virtualenv-init > /dev/null; then +# eval "$(pyenv virtualenv-init -)" +# export PYENV_VIRTUALENV_DISABLE_PROMPT=1 +# fi +# pyenv $@ +# } +#fi +#export WORKON_HOME="$XDG_DATA_HOME/virtualenvs" +export WORKON_HOME=$HOME/.virtualenvs +export VIRTUALENVWRAPPER_PYTHON=`which python3` +export VIRTUALENVWRAPPER_VIRTUALENV=`which virtualenv` +#source /usr/local/bin/virtualenvwrapper.sh +source $(which virtualenvwrapper.sh) +export VIRTUAL_ENV_DISABLE_PROMPT=false +export JUPYTER_CONFIG_DIR="$XDG_CONFIG_HOME/jupyter" +export IPYTHONDIR="$XDG_CONFIG_HOME/jupyter" + +# Python +[[ "$(uname)" == "Darwin" ]] && export PYTHON_CONFIGURE_OPTS="--enable-framework" +[[ "$(uname)" == "Linux" ]] && export PYTHON_CONFIGURE_OPTS="--enable-shared" + +export PYENV_ROOT="$HOME/.pyenv" +export PATH="$PYENV_ROOT/bin:$PATH" + +# PHP +PATH="$HOME/.config/composer/vendor/bin:$PATH" + + +# Lua +export PATH=$PATH:/usr/local/luarocks/bin +#export PATH="$XDG_DATA_HOME/luarocks/bin:$PATH" + +#ver=$(find lua* -maxdepth 0 | sort -rV | head -n 1) +#export LUA_PATH="$LUA_PATH:${ver}/share/lua/5.1/?.lua;${ver}/share/lua/5.1/?/init.lua;;" +#export LUA_CPATH="$LUA_CPATH:${ver}/lib/lua/5.1/?.so;;" + +#LUAROCKS_PREFIX=/usr/local +#export LUA_PATH="$LUAROCKS_PREFIX/share/lua/5.1/?.lua;$LUAROCKS_PREFIX/share/lua/5.1/?/init.lua;;" +#export LUA_CPATH="$LUAROCKS_PREFIX/lib/lua/5.1/?.so;;" + +#export LUA_PATH=";;" +#export LUA_CPATH="./?.so;/usr/local/lib/lua/5.3/?.so; +# /usr/local/share/lua/5.3/?.so;" + + +# Program settings +#export MOZ_USE_XINPUT2="1" # Mozilla smooth scrolling/touchpads. +# Pixel-perfect Firefox touchpad scrolling +export MOZ_USE_XINPUT2=1 + + +# Scaling +#export QT_AUTO_SCREEN_SCALE_FACTOR=0 +#export QT_SCALE_FACTOR=1 +#export QT_SCREEN_SCALE_FACTORS="1;1;1" +#export GDK_SCALE=1 +#export GDK_DPI_SCALE=1 + + +#typeset -U PATH path +export GTK_IM_MODULE='fcitx' +export QT_IM_MODULE='fcitx' +export SDL_IM_MODULE='fcitx' +export XMODIFIERS='@im=fcitx' + + +# Start blinking +export LESS_TERMCAP_mb=$(tput bold; tput setaf 2) # green +# Start bold +export LESS_TERMCAP_md=$(tput bold; tput setaf 2) # green +# Start stand out +export LESS_TERMCAP_so=$(tput bold; tput setaf 3) # yellow +# End standout +export LESS_TERMCAP_se=$(tput rmso; tput sgr0) +# Start underline +export LESS_TERMCAP_us=$(tput smul; tput bold; tput setaf 1) # red +# End Underline +export LESS_TERMCAP_ue=$(tput sgr0) +# End bold, blinking, standout, underline +export LESS_TERMCAP_me=$(tput sgr0). diff --git a/linux/home/.config/zsh/.zshrc b/linux/home/.config/zsh/.zshrc new file mode 100644 index 0000000..ececf24 --- /dev/null +++ b/linux/home/.config/zsh/.zshrc @@ -0,0 +1,63 @@ + +# ███████╗███████╗██╗ ██╗██████╗ ██████╗ +# ╚══███╔╝██╔════╝██║ ██║██╔══██╗██╔════╝ +# ███╔╝ ███████╗███████║██████╔╝██║ +# ███╔╝ ╚════██║██╔══██║██╔══██╗██║ +# ███████╗███████║██║ ██║██║ ██║╚██████╗ +# ╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ + +for zsh_source in "$HOME"/.config/zsh/user/*.zsh; do + source $zsh_source +done + +# If not running interactively, don't do anything +[[ $- != *i* ]] && return + +if [[ -n "$SSH_CLIENT" ]]; then + export KEYTIMEOUT=10 +else + export KEYTIMEOUT=15 +fi + +# Tmux default session +if command -v tmux &> /dev/null && [ -n "$PS1" ] && [ -z "$DISPLAY" ] && [ -z "$TMUX" ]; then + if ! tmux list-sessions | grep -q '^tmux:'; then + tmux new -s tmux + fi +fi + +# Enable various options +setopt interactive_comments beep extendedglob nomatch notify completeinword prompt_subst + +# Some other useful functionalities +setopt autocd # Automatically cd into typed directory. +setopt AUTO_PUSHD # More history for cd and use "cd -TAB" +stty intr '^q' # free Ctrl+C for copy use Ctrl+q instead +stty lnext '^-' # free Ctrl+V for paste use ^- instead +stty stop undef # Disable ctrl-s to freeze terminal. +stty start undef +#COMPLETION_WAITING_DOTS="false" +#unsetopt BEEP + +########## Source Plugins, should be last ########## +#source /usr/share/nvm/init-nvm.sh + +# Load fzf keybindings and completion if fzf is installed +if command -v fzf > /dev/null 2>&1; then + #FZF_BASE="/usr/share/fzf" + FZF_BASE="/usr/local/bin/fzf/shell" + source "${FZF_BASE}/key-bindings.zsh" + source "${FZF_BASE}/completion.zsh" +else + echo "fzf not found, please install it to use fzf keybindings and completion." +fi + +# Suggest aliases for commands +source ~/.config/zsh/plugins/zsh-you-should-use/you-should-use.plugin.zsh + +# Load zsh-syntax-highlighting +source ~/.config/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh + +# Load fish like auto suggestions +source ~/.config/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.plugin.zsh +source ~/.config/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh diff --git a/linux/home/.config/zsh/user/aliases.zsh b/linux/home/.config/zsh/user/aliases.zsh new file mode 100644 index 0000000..df0c4af --- /dev/null +++ b/linux/home/.config/zsh/user/aliases.zsh @@ -0,0 +1,129 @@ +########## Aliases ########## + +### Dotfiles +alias config='git --git-dir=$HOME/.cfg --work-tree=$HOME' +cfg_files=$(config ls-tree --name-only -r HEAD) + +export CFG_FILES="$cfg_files" + +# Define alias for nvim/vim (fallback to vim) +if command -v nvim > /dev/null; then + alias vi='nvim' +else + alias vi='vim' +fi + +# Confirmation # +alias mv='mv -i' +alias cp='cp -i' +alias ln='ln -i' + +# Disable 'rm' +alias rm='function _rm() { echo -e "\033[0;31mrm\033[0m is disabled, use \033[0;32mtrash\033[0m or \033[0;32mdel \033[0m\033[0;33m$1\033[0m"; }; _rm' +alias del='/bin/rm' + +alias ls='lsd --color=auto --group-directories-first' +#alias ls="ls --color=auto --group-directories-first" + +# ls variants +alias l='ls -FAh --group-directories-first' +alias la='ls -lAFh --group-directories-first' +alias lt='ls -lFAht --group-directories-first' +alias lr='ls -RFAh --group-directories-first' + +# more ls variants +alias ldot='ls -ld .* --group-directories-first' +alias lS='ls -1FASsh --group-directories-first' +alias lart='ls -1Fcart --group-directories-first' +alias lrt='ls -1Fcrt --group-directories-first' + +# ls with different alphabethical sorting +#unalias ll +#ll() { LC_COLLATE=C ls "$@" } + +# suffix aliases +alias -g CP='| xclip -selection clipboard -rmlastnl' +alias -g LL="| less" +alias -g CA="| cat -A" +alias -g KE="2>&1" +alias -g NE="2>/dev/null" +alias -g NUL=">/dev/null 2>&1" + +alias grep='grep --color=auto --exclude-dir={.git,.svn,.hg}' +alias egrep='egrep --color=auto --exclude-dir={.git,.svn,.hg}' +alias egrep='fgrep --color=auto --exclude-dir={.git,.svn,.hg}' + +alias gdb='gdb -q' +alias rust-gdb='rust-gdb -q' + +# List upto last 10 visited directories using "d" and quickly cd into any specific one +alias d="dirs -v | head -10" + +# Using just a number from "0" to "9" +alias 0="cd +0" +alias 1="cd +1" +alias 2="cd +2" +alias 3="cd +3" +alias 4="cd +4" +alias 5="cd +5" +alias 6="cd +6" +alias 7="cd +7" +alias 8="cd +8" +alias 9="cd +9" + +alias sudo='sudo ' # zsh: elligible for alias expansion/fix syntax highlight +alias sedit='sudoedit' +#alias se='sudoedit' +alias se='sudo -e' +alias :q='exit' +alias sc="systemctl" +alias jc="journalctl" +alias jck="journalctl -k" # Kernel +alias jce='sudo journalctl -b --priority 0..3' # error +alias journalctl-error='sudo journalctl -b --priority 0..3' +alias jcssh="sudo journalctl -u sshd" +alias tunnel='ssh -fNTL' +# tty aliases +if [[ "$TERM" == 'linux' ]]; then + alias tmux='/usr/bin/tmux -L linux' +fi +alias logout="loginctl kill-user $(whoami)" + +#alias suspend='systemctl suspend && betterlockscreen -l' # Suspend(sleep) and lock screen if using systemctl +alias suspend='systemctl suspend' # Suspend(sleep) and lock screen if using systemctl +alias hibernate='systemctl hibernate' # Hibernate +alias lock='DISPLAY=:0 xautolock -locknow' # Lock my workstation screen from my phone +alias oports="sudo lsof -i -P -n | grep -i 'listen'" # List open ports +alias keyname="xev | sed -n 's/[ ]*state.* \([^ ]*\)).*/\1/p'" +alias wget=wget --hsts-file="$XDG_CACHE_HOME/wget-hsts" # wget does not support environment variables +alias pp='getlast 2>&1 |&tee -a output.txt' +alias lg='la | grep' +alias pg='ps aux | grep' +alias py='python' +alias py3='python3' +alias sha256='shasum -a 256' +alias rgf='rg -F' +alias weather='curl wttr.in/durban' +alias wifi='nmcli dev wifi show-password' +alias ddg='w3m lite.duckduckgo.com' +alias rss='newsboat' +alias vpn='protonvpn' +alias yt-dl="yt-dlp -f 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4' --restrict-filename" + +# Time aliases +alias utc='TZ=Africa/Johannesburg date' +alias ber='TZ=Europe/Berlin date' +alias nyc='TZ=America/New_York date' +alias sfo='TZ=America/Los_Angeles date' +alias utc='TZ=Etc/UTC date' + +alias src='source ~/.zshrc' +alias p=proxy + +alias cheat='~/.scripts/cheat.sh ~/documents/notes/cheatsheets' +alias crypto='curl -s rate.sx | head -n -2 | tail -n +10' +alias todo='glow "$HOME"/media/notes/_TODO.md' + +alias android-studio='/opt/android-studio/bin/studio.sh' # android-studio +alias nomachine='/usr/NX/bin/nxplayer' # nomachine +alias spotify='LD_PRELOAD=/usr/lib/spotify-adblock.so /bin/spotify %U' diff --git a/linux/home/.config/zsh/user/bindings.zsh b/linux/home/.config/zsh/user/bindings.zsh new file mode 100644 index 0000000..ce8451b --- /dev/null +++ b/linux/home/.config/zsh/user/bindings.zsh @@ -0,0 +1,39 @@ +########## Vi mode ########## +bindkey -v +#bindkey -M viins '^?' backward-delete-char +#local WORDCHARS='*?_-.[]~=&;!#$%^(){}<>' +backward-kill-dir () { + local WORDCHARS=${WORDCHARS/\/} + zle backward-kill-word + zle -f kill +} +zle -N backward-kill-dir +bindkey '^[^?' backward-kill-dir +bindkey "^W" backward-kill-dir +bindkey -M viins '^[[3~' delete-char +bindkey -M vicmd '^[[3~' delete-char +bindkey -v '^?' backward-delete-char +bindkey -r '\e/' +bindkey -s jk '\e' +#bindkey "^W" backward-kill-word +bindkey "^H" backward-delete-char # Control-h also deletes the previous char +bindkey "^U" backward-kill-line +bindkey "^[j" history-search-forward # or you can bind it to the down key "^[[B" +bindkey "^[k" history-search-backward # or you can bind it to Up key "^[[A" + +# Define the 'autosuggest-execute' and 'autosuggest-accept' ZLE widgets +autoload -Uz autosuggest-execute autosuggest-accept +zle -N autosuggest-execute +zle -N autosuggest-accept +bindkey '^X' autosuggest-execute +bindkey '^Y' autosuggest-accept + +# Edit line in vim with alt-e +autoload edit-command-line; zle -N edit-command-line +bindkey '^e' edit-command-line +bindkey '^[e' edit-command-line # alt + e + +# Allow CTRL+D to exit zsh with partial command line (non empty line) +exit_zsh() { exit } +zle -N exit_zsh +bindkey '^D' exit_zsh diff --git a/linux/home/.config/zsh/user/completion.zsh b/linux/home/.config/zsh/user/completion.zsh new file mode 100644 index 0000000..7d9198a --- /dev/null +++ b/linux/home/.config/zsh/user/completion.zsh @@ -0,0 +1,156 @@ +#!/bin/zsh + +########## Completion(s) ########## + +autoload -Uz compinit +_comp_path="${XDG_CACHE_HOME:-$HOME/.cache}/zcompdump" + +# Expands globs in conditional expressions +if [[ $_comp_path(#qNmh-20) ]]; then + # -C (skip function check) implies -i (skip security check). + compinit -C -d "$_comp_path" +else + mkdir -p "$_comp_path:h" + compinit -i -d "$_comp_path" + # Keep $_comp_path younger than cache time even if it isn't regenerated. + touch "$_comp_path" +fi +unset _comp_path + +# Accept completion with or Ctrl+i and go to next/previous suggestions with Vi like keys: Ctrl+n/p +zmodload -i zsh/complist +accept-and-complete-next-history() { + zle expand-or-complete-prefix +} +zle -N accept-and-complete-next-history +bindkey -M menuselect '^i' accept-and-complete-next-history +bindkey '^n' expand-or-complete +bindkey '^p' reverse-menu-complete +bindkey -M menuselect '^[' undo + +#zstyle ':completion:*' menu select=1 +#zstyle ':completion:*:directory-stack' list-colors '=(#b) #([0-9]#)*( *)==95=38;5;12' + +# Options +setopt COMPLETE_IN_WORD # Complete from both ends of a word. +setopt ALWAYS_TO_END # Move cursor to the end of a completed word. +setopt PATH_DIRS # Perform path search even on command names with slashes. +setopt AUTO_MENU # Show completion menu on a successive tab press. +setopt AUTO_LIST # Automatically list choices on ambiguous completion. +setopt AUTO_PARAM_SLASH # If completed parameter is a directory, add a trailing slash. +setopt EXTENDED_GLOB # Needed for file modification glob modifiers with compinit. +unsetopt MENU_COMPLETE # Do not autoselect the first completion entry. + +# Variables +LS_COLORS=${LS_COLORS:-'di=34:ln=35:so=32:pi=33:ex=31:bd=36;01:cd=33;01:su=31;40;07:sg=36;40;07:tw=32;40;07:ow=33;40;07:'} + +# Styles +# Defaults. +zstyle ':completion:*:default' list-colors ${(s.:.)LS_COLORS} +zstyle ':completion:*:default' list-prompt '%S%M matches%s' + +# Use caching to make completion for commands such as dpkg and apt usable. +zstyle ':completion::complete:*' use-cache on +zstyle ':completion::complete:*' cache-path "${XDG_CACHE_HOME:-$HOME/.cache}/zcompcache" + + +# Group matches and describe. +zstyle ':completion:*:*:*:*:*' menu select +zstyle ':completion:*:matches' group 'yes' +zstyle ':completion:*:options' description 'yes' +zstyle ':completion:*:options' auto-description '%d' +zstyle ':completion:*:corrections' format ' %F{green}-- %d (errors: %e) --%f' +zstyle ':completion:*:descriptions' format ' %F{yellow}-- %d --%f' +zstyle ':completion:*:messages' format ' %F{purple} -- %d --%f' +zstyle ':completion:*:warnings' format ' %F{red}-- no matches found --%f' +zstyle ':completion:*' format ' %F{yellow}-- %d --%f' +zstyle ':completion:*' group-name '' +zstyle ':completion:*' verbose yes + +# Fuzzy match mistyped completions. +zstyle ':completion:*' completer _complete _match _approximate +zstyle ':completion:*:match:*' original only +zstyle ':completion:*:approximate:*' max-errors 1 numeric + +# Increase the number of errors based on the length of the typed word. But make +# sure to cap (at 7) the max-errors to avoid hanging. +zstyle -e ':completion:*:approximate:*' max-errors 'reply=($((($#PREFIX+$#SUFFIX)/3>7?7:($#PREFIX+$#SUFFIX)/3))numeric)' + +# Don't complete unavailable commands. +zstyle ':completion:*:functions' ignored-patterns '(_*|pre(cmd|exec))' + +# Array completion element sorting. +zstyle ':completion:*:*:-subscript-:*' tag-order indexes parameters + +# Directories +zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories +zstyle ':completion:*:*:cd:*:directory-stack' menu yes select +zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand' +zstyle ':completion:*' squeeze-slashes true + +# History +zstyle ':completion:*:history-words' stop yes +zstyle ':completion:*:history-words' remove-all-dups yes +zstyle ':completion:*:history-words' list false +zstyle ':completion:*:history-words' menu yes + +# Environment Variables +zstyle ':completion::*:(-command-|export):*' fake-parameters ${${${_comps[(I)-value-*]#*,}%%,*}:#-*-} + +# Populate hostname completion. But allow ignoring custom entries from static +# */etc/hosts* which might be uninteresting. +zstyle -a ':completion:*:hosts' etc-host-ignores '_etc_host_ignores' + +zstyle -e ':completion:*:hosts' hosts 'reply=( + ${=${=${=${${(f)"$(cat {/etc/ssh/ssh_,~/.ssh/}known_hosts(|2)(N) 2> /dev/null)"}%%[#| ]*}//\]:[0-9]*/ }//,/ }//\[/ } + ${=${(f)"$(cat /etc/hosts(|)(N) <<(ypcat hosts 2> /dev/null))"}%%(\#${_etc_host_ignores:+|${(j:|:)~_etc_host_ignores}})*} + ${=${${${${(@M)${(f)"$(cat ~/.ssh/config 2> /dev/null)"}:#Host *}#Host }:#*\**}:#*\?*}} +)' + +# Don't complete uninteresting users... +zstyle ':completion:*:*:*:users' ignored-patterns \ + adm amanda apache avahi beaglidx bin cacti canna clamav daemon \ + dbus distcache dovecot fax ftp games gdm gkrellmd gopher \ + hacluster haldaemon halt hsqldb ident junkbust ldap lp mail \ + mailman mailnull mldonkey mysql nagios \ + named netdump news nfsnobody nobody nscd ntp nut nx openvpn \ + operator pcap postfix postgres privoxy pulse pvm quagga radvd \ + rpc rpcuser rpm shutdown squid sshd sync uucp vcsa xfs '_*' + +# ... unless we really want to. +zstyle '*' single-ignored show + +# Ignore multiple entries. +zstyle ':completion:*:(rm|kill|diff):*' ignore-line other +zstyle ':completion:*:rm:*' file-patterns '*:all-files' + +# Kill +zstyle ':completion:*:*:*:*:processes' command 'ps -u $LOGNAME -o pid,user,command -w' +zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#) ([0-9a-z-]#)*=01;36=0=01' +zstyle ':completion:*:*:kill:*' menu yes select +zstyle ':completion:*:*:kill:*' force-list always +zstyle ':completion:*:*:kill:*' insert-ids single + +# Man +zstyle ':completion:*:manuals' separate-sections true +zstyle ':completion:*:manuals.(^1*)' insert-sections true + +# Media Players +zstyle ':completion:*:*:mpg123:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories' +zstyle ':completion:*:*:mpg321:*' file-patterns '*.(mp3|MP3):mp3\ files *(-/):directories' +zstyle ':completion:*:*:ogg123:*' file-patterns '*.(ogg|OGG|flac):ogg\ files *(-/):directories' +zstyle ':completion:*:*:mocp:*' file-patterns '*.(wav|WAV|mp3|MP3|ogg|OGG|flac):ogg\ files *(-/):directories' + +# Mutt +if [[ -s "$HOME/.mutt/aliases" ]]; then + zstyle ':completion:*:*:mutt:*' menu yes select + zstyle ':completion:*:mutt:*' users ${${${(f)"$(<"$HOME/.mutt/aliases")"}#alias[[:space:]]}%%[[:space:]]*} +fi + +# SSH/SCP/RSYNC +zstyle ':completion:*:(ssh|scp|rsync):*' tag-order 'hosts:-host:host hosts:-domain:domain hosts:-ipaddr:ip\ address *' +zstyle ':completion:*:(scp|rsync):*' group-order users files all-files hosts-domain hosts-host hosts-ipaddr +zstyle ':completion:*:ssh:*' group-order users hosts-domain hosts-host users hosts-ipaddr +zstyle ':completion:*:(ssh|scp|rsync):*:hosts-host' ignored-patterns '*(.|:)*' loopback ip6-loopback localhost ip6-localhost broadcasthost +zstyle ':completion:*:(ssh|scp|rsync):*:hosts-domain' ignored-patterns '<->.<->.<->.<->' '^[-[:alnum:]]##(.[-[:alnum:]]##)##' '*@*' +zstyle ':completion:*:(ssh|scp|rsync):*:hosts-ipaddr' ignored-patterns '^(<->.<->.<->.<->|(|::)([[:xdigit:].]##:(#c,2))##(|%*))' '127.0.0.<->' '255.255.255.255' '::1' 'fe80::*' diff --git a/linux/home/.config/zsh/user/functions.zsh b/linux/home/.config/zsh/user/functions.zsh new file mode 100644 index 0000000..75032ba --- /dev/null +++ b/linux/home/.config/zsh/user/functions.zsh @@ -0,0 +1,813 @@ +## Function to temporarily unset GIT_WORK_TREE +function git_without_work_tree() { + # Only proceed if a git command is being run + if [ "$1" = "git" ]; then + shift + # Check if the current directory is inside a Git work tree + if git rev-parse --is-inside-work-tree &>/dev/null; then + # If inside a work tree, temporarily unset GIT_WORK_TREE + GIT_WORK_TREE_OLD="$GIT_WORK_TREE" + unset GIT_WORK_TREE + git "$@" + export GIT_WORK_TREE="$GIT_WORK_TREE_OLD" + else + # If not inside a work tree, call git command directly + git "$@" + fi + else + # If it's not a git command, just execute it normally + command "$@" + fi +} + +# Set alias conditionally +alias git='git_without_work_tree git' + +# Set bare dotfiles repository git environment variables dynamically +function set_git_env_vars() { + # Check if the current command is a package manager command + if [[ "${(%)${(z)history[1]}}" =~ ^(pacman|yay|apt|dnf|brew|npm|pip|gem|go|cargo) ]]; then + return + fi + local git_dir="$(git rev-parse --git-dir -C . 2>/dev/null)" + if [[ -n "$git_dir" ]]; then + local is_bare="$(git -C "$git_dir" rev-parse --is-bare-repository 2>/dev/null)" + if [[ "$is_bare" == "true" ]]; then + export GIT_DIR="$HOME/.cfg" + export GIT_WORK_TREE=$(realpath $(eval echo ~)) + else + unset GIT_DIR + unset GIT_WORK_TREE + fi + else + local root_dir="$(git rev-parse --show-toplevel 2>/dev/null)" + if [[ -n "$root_dir" ]]; then + unset GIT_DIR + export GIT_WORK_TREE="$root_dir" + else + export GIT_DIR="$HOME/.cfg" + export GIT_WORK_TREE=$(realpath $(eval echo ~)) + fi + fi +} + +# Define an auto_cd hook to automatically update Git environment variables +#function chpwd() { +# set_git_env_vars +#} +# Call the function to set Git environment variables when the shell starts up +set_git_env_vars + + +function gsp() { + # Config file for subtrees + # + # Format: + # ;; + # # Lines starting with '#' will be ignored + GIT_SUBTREE_FILE="$PWD/.gitsubtrees" + + if [ ! -f "$GIT_SUBTREE_FILE" ]; then + echo "Nothing to do - file <$GIT_SUBTREE_FILE> does not exist." + return + fi + + if ! command -v config &> /dev/null; then + echo "Error: 'config' command not found. Make sure it's available in your PATH." + return + fi + + OLD_IFS=$IFS + IFS=$'\n' + for LINE in $(cat "$GIT_SUBTREE_FILE"); do + + # Skip lines starting with '#'. + if [[ $LINE = \#* ]]; then + continue + fi + + # Parse the current line. + PREFIX=$(echo "$LINE" | cut -d';' -f 1) + REMOTE=$(echo "$LINE" | cut -d';' -f 2) + BRANCH=$(echo "$LINE" | cut -d';' -f 3) + + # Pull from the remote. + echo "Executing: git subtree pull --prefix=$PREFIX $REMOTE $BRANCH" + if git subtree pull --prefix="$PREFIX" "$REMOTE" "$BRANCH"; then + echo "Subtree pull successful for $PREFIX." + else + echo "Error: Subtree pull failed for $PREFIX." + fi + done + + IFS=$OLD_IFS +} + +# Print previous command into a file +getlast () { + fc -nl $((HISTCMD - 1)) +} + +# Enter directory and list contents +#cd() { builtin cd $@ && lsd } +cd() { + if [ -n "$1" ]; then + builtin cd "$@" && ls + else + builtin cd ~ && ls + fi +} + +# cd using "up n" as a command up as many directories, example "up 3" +up() { + # default parameter to 1 if non provided + declare -i d=${@:-1} + # ensure given parameter is non-negative. Print error and return if it is + (( $d < 0 )) && (>&2 echo "up: Error: negative value provided") && return 1; + # remove last d directories from pwd, append "/" in case result is empty + cd "$(pwd | sed -E 's;(/[^/]*){0,'$d'}$;;')/"; +} + +# cd into $XDG_CONFIG_HOME/$1 directory +c() { + local root=${XDG_CONFIG_HOME:-~/.config} + local dname="$root/$1" + if [[ ! -d "$dname" ]]; then + return + fi + cd "$dname" +} + +# Make and cd into directory and any parent directories +mkcd () { + if [[ -z "$1" ]]; then + echo "Usage: mkcd " 1>&2 + return 1 + fi + mkdir -p "$1" + cd "$1" +} + +bak() { + if [[ -e "$1" ]]; then + echo "Found: $1" + mv "${1%.*}"{,.bak} + elif [[ -e "$1.bak" ]]; then + echo "Found: $1.bak" + mv "$1"{.bak,} + fi +} + +back() { + for file in "$@"; do + cp -r "$file" "$file".bak + done +} + +# tre is a shorthand for tree +tre() { + tree -aC -I \ + '.git|.hg|.svn|.tmux|.backup|.vim-backup|.swap|.vim-swap|.undo|.vim-undo|*.bak|tags' \ + --dirsfirst "$@" \ + | less +} + +# switch from/to project/package dir +pkg() { + if [ "$#" -eq 2 ]; then + ln -s "$(readlink -f $1)" "$(readlink -f $2)"/._pkg + ln -s "$(readlink -f $2)" "$(readlink -f $1)"/._pkg + else + cd "$(readlink -f ./._pkg)" + fi +} + +# Prepare C/C++ project for Language Server Protoco +lsp-prep() { + (cd build && cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON) \ + && ln -sf build/compile_commands.json +} + +reposize() { + url=`echo $1 \ + | perl -pe 's#(?:https?://github.com/)([\w\d.-]+\/[\w\d.-]+).*#\1#g' \ + | perl -pe 's#git\@github.com:([\w\d.-]+\/[\w\d.-]+)\.git#\1#g' + ` + printf "https://github.com/$url => " + curl -s https://api.github.com/repos/$url \ + | jq '.size' \ + | numfmt --to=iec --from-unit=1024 +} + +# Launch a program in a terminal without getting any output, +# and detache the process from terminal +# (can then close the terminal without terminating process) +-echo() { + "$@" &> /dev/null & disown +} + +# Reload shell +function reload() { + local compdump_files="$ZDOTDIR/.zcompdump*" + + if ls $compdump_files &> /dev/null; then + rm -f $compdump_files + fi + + exec $SHELL -l +} + +#pom() { +# local -r HOURS=${1:?} +# local -r MINUTES=${2:-0} +# local -r POMODORO_DURATION=${3:-25} +# +# bc <<< "(($HOURS * 60) + $MINUTES) / $POMODORO_DURATION" +#} + +#mnt() { +# local FILE="/mnt/external" +# if [ ! -z $2 ]; then +# FILE=$2 +# fi +# +# if [ ! -z $1 ]; then +# sudo mount "$1" "$FILE" -o rw +# echo "Device in read/write mounted in $FILE" +# fi +# +# if [ $# = 0 ]; then +# echo "You need to provide the device (/dev/sd*) - use lsblk" +# fi +#} +# +#umnt() { +# local DIRECTORY="/mnt" +# if [ ! -z $1 ]; then +# DIRECTORY=$1 +# fi +# MOUNTED=$(grep $DIRECTORY /proc/mounts | cut -f2 -d" " | sort -r) +# cd "/mnt" +# sudo umount $MOUNTED +# echo "$MOUNTED unmounted" +#} + +mntmtp() { + local DIRECTORY="$HOME/mnt" + if [ ! -z $2 ]; then + local DIRECTORY=$2 + fi + if [ ! -d $DIRECTORY ]; then + mkdir $DIRECTORY + fi + + if [ ! -z $1 ]; then + simple-mtpfs --device "$1" "$DIRECTORY" + echo "MTPFS device in read/write mounted in $DIRECTORY" + fi + + if [ $# = 0 ]; then + echo "You need to provide the device number - use simple-mtpfs -l" + fi +} + +umntmtp() { + local DIRECTORY="$HOME/mnt" + if ; then + DIRECTORY=$1 + fi + cd $HOME + umount $DIRECTORY + echo "$DIRECTORY with mtp filesystem unmounted" +} +duckduckgo() { + lynx -vikeys -accept_all_cookies "https://lite.duckduckgo.com/lite/?q=$@" +} + +wikipedia() { + lynx -vikeys -accept_all_cookies "https://en.wikipedia.org/wiki?search=$@" +} +#function filesize() { +# # Check if 'du' supports the -b option, which provides sizes in bytes. +# if du -b /dev/null > /dev/null 2>&1; then +# local arg=-sbh; # If supported, use -sbh options for 'du'. +# else +# local arg=-sh; # If not supported, use -sh options for 'du'. +# fi +# +# # Check if no arguments are provided. +# if [ "$#" -eq 0 ]; then +# # Calculate and display sizes for all files and directories in cwd. +# du $arg ./* +# else +# # Calculate and display sizes for the specified files and directories. +# du $arg -- "$@" +# fi +#} +# + +fgl() { + git log --graph --color=always \ + --format="%C(auto)%h%d %s %C(black)%C(bold)%cr" "$@" | + fzf --ansi --no-sort --reverse --tiebreak=index --bind=ctrl-s:toggle-sort \ + --bind "ctrl-m:execute: + (grep -o '[a-f0-9]\{7\}' | head -1 | + xargs -I % sh -c 'git show --color=always % | less -R') << 'FZF-EOF' + {} +FZF-EOF" +} + +fgb() { + local branches branch + branches=$(git --no-pager branch -vv) && + branch=$(echo "$branches" | fzf +m) && + git checkout $(echo "$branch" | awk '{print $1}' | sed "s/.* //") +} + +# +--------+ +# | Pacman | +# +--------+ + +# TODO can improve that with a bind to switch to what was installed +fpac() { + pacman -Slq | fzf --multi --reverse --preview 'pacman -Si {1}' | xargs -ro sudo pacman -S +} + +fyay() { + yay -Slq | fzf --multi --reverse --preview 'yay -Si {1}' | xargs -ro yay -S +} + +# +------+ +# | tmux | +# +------+ + +fmux() { + prj=$(find $XDG_CONFIG_HOME/tmuxp/ -execdir bash -c 'basename "${0%.*}"' {} ';' | sort | uniq | nl | fzf | cut -f 2) + echo $prj + [ -n "$prj" ] && tmuxp load $prj +} + +# ftmuxp - propose every possible tmuxp session +ftmuxp() { + if [[ -n $TMUX ]]; then + return + fi + + # get the IDs + ID="$(ls $XDG_CONFIG_HOME/tmuxp | sed -e 's/\.yml$//')" + if [[ -z "$ID" ]]; then + tmux new-session + fi + + create_new_session="Create New Session" + + ID="${create_new_session}\n$ID" + ID="$(echo $ID | fzf | cut -d: -f1)" + + if [[ "$ID" = "${create_new_session}" ]]; then + tmux new-session + elif [[ -n "$ID" ]]; then + # Change name of urxvt tab to session name + printf '\033]777;tabbedx;set_tab_name;%s\007' "$ID" + tmuxp load "$ID" + fi +} + +# ftmux - help you choose tmux sessions +ftmux() { + if [[ ! -n $TMUX ]]; then + # get the IDs + ID="`tmux list-sessions`" + if [[ -z "$ID" ]]; then + tmux new-session + fi + create_new_session="Create New Session" + ID="$ID\n${create_new_session}:" + ID="`echo $ID | fzf | cut -d: -f1`" + if [[ "$ID" = "${create_new_session}" ]]; then + tmux new-session + elif [[ -n "$ID" ]]; then + printf '\033]777;tabbedx;set_tab_name;%s\007' "$ID" + tmux attach-session -t "$ID" + else + : # Start terminal normally + fi + fi +} + +# +-------+ +# | Other | +# +-------+ + +# List install files for dotfiles +fdot() { + file=$(find "$DOTFILES/install" -exec basename {} ';' | sort | uniq | nl | fzf | cut -f 2) + [ -n "$file" ] && "$EDITOR" "$DOTFILES/install/$file" +} + +# List projects +fwork() { + result=$(find ~/workspace/* -type d -prune -exec basename {} ';' | sort | uniq | nl | fzf | cut -f 2) + [ -n "$result" ] && cd ~/workspace/$result +} + +# Open pdf with Zathura +fpdf() { + result=$(find -type f -name '*.pdf' | fzf --bind "ctrl-r:reload(find -type f -name '*.pdf')" --preview "pdftotext {} - | less") + [ -n "$result" ] && nohup zathura "$result" &> /dev/null & disown +} + +# Open epubs with Zathura +fepub() { + result=$(find -type f -name '*.epub' | fzf --bind "ctrl-r:reload(find -type f -name '*.epub')") + [ -n "$result" ] && nohup zathura "$result" &> /dev/null & disown +} + +# Search and find directories in the dir stack +fpop() { + # Only work with alias d defined as: + + # alias d='dirs -v' + # for index ({1..9}) alias "$index"="cd +${index}"; unset index + + d | fzf --height="20%" | cut -f 1 | source /dev/stdin +} + +#ip() { +# emulate -LR zsh +# +# if [[ $1 == 'get' ]]; then +# res=$(curl -s ipinfo.io/ip) +# echo -n $res | xsel --clipboard +# echo "copied $res to clipboard" +# # only run ip if it exists +# elif (( $+commands[ip] )); then +# command ip $* +# fi +#} + +ssh-create() { + if [ ! -z "$1" ]; then + ssh-keygen -f $HOME/.ssh/$1 -t rsa -N '' -C "$1" + chmod 700 $HOME/.ssh/$1* + fi +} + +historystat() { + history 0 | awk '{print $2}' | sort | uniq -c | sort -n -r | head +} + +promptspeed() { + for i in $(seq 1 10); do /usr/bin/time zsh -i -c exit; done +} + +#matrix () { +# local lines=$(tput lines) +# cols=$(tput cols) +# +# awkscript=' +# { +# letters="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()" +# lines=$1 +# random_col=$3 +# c=$4 +# letter=substr(letters,c,1) +# cols[random_col]=0; +# for (col in cols) { +# line=cols[col]; +# cols[col]=cols[col]+1; +# printf "\033[%s;%sH\033[2;32m%s", line, col, letter; +# printf "\033[%s;%sH\033[1;37m%s\033[0;0H", cols[col], col, letter; +# if (cols[col] >= lines) { +# cols[col]=0; +# } +# } +# } +# ' +# +# echo -e "\e[1;40m" +# clear +# +# while :; do +# echo $lines $cols $(( $RANDOM % $cols)) $(( $RANDOM % 72 )) +# sleep 0.05 +# done | awk "$awkscript" +#} + +matrix() { + local lines=$(tput lines) + cols=$(tput cols) + + # Check if tmux is available + if command -v tmux > /dev/null; then + # Save the current status setting + local status_setting=$(tmux show -g -w -v status) + + # Turn off tmux status + tmux set -g status off + else + echo "tmux is not available. Exiting." + return 1 + fi + + # Function to restore terminal state + restore_terminal() { + # Clear the screen + clear + + # Bring back tmux status to its original setting + if command -v tmux > /dev/null; then + tmux set -g status "$status_setting" + fi + } + + trap 'restore_terminal' INT + + awkscript=' + { + letters="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%^&*()" + lines=$1 + random_col=$3 + c=$4 + letter=substr(letters,c,1) + cols[random_col]=0; + for (col in cols) { + line=cols[col]; + cols[col]=cols[col]+1; + printf "\033[%s;%sH\033[2;32m%s", line, col, letter; + printf "\033[%s;%sH\033[1;37m%s\033[0;0H", cols[col], col, letter; + if (cols[col] >= lines) { + cols[col]=0; + } + } + } + ' + + echo -e "\e[1;40m" + clear + + while :; do + echo $lines $cols $(( $RANDOM % $cols)) $(( $RANDOM % 72 )) + sleep 0.05 + done | awk "$awkscript" + + # Restore terminal state + restore_terminal +} + +## Reload shell +function reload() { + local compdump_files="$ZDOTDIR/.zcompdump*" + + if ls $compdump_files &> /dev/null; then + rm -f $compdump_files + fi + + exec $SHELL -l +} +## Generate a secure password +function passgen() { + LC_ALL=C tr -dc ${1:-"[:graph:]"} < /dev/urandom | head -c ${2:-20} +} +## Encode/Decode string using base64 +function b64e() { + echo "$@" | base64 +} + +function b64d() { + echo "$@" | base64 -D +} +# Search through all man pages +function fman() { + man -k . | fzf -q "$1" --prompt='man> ' --preview $'echo {} | tr -d \'()\' | awk \'{printf "%s ", $2} {print $1}\' | xargs -r man' | tr -d '()' | awk '{printf "%s ", $2} {print $1}' | xargs -r man +} +# Back up a file. Usage "backupthis " +backupthis() { + cp -riv $1 ${1}-$(date +%Y%m%d%H%M).backup; +} + +# Spawn a clone of current terminal +putstate () { + declare +x >~/environment.tmp + declare -x >>~/environment.tmp + echo cd "$PWD" >>~/environment.tmp +} + +getstate () { + . ~/environment.tmp +} + +# use ctrl-z to toggle in and out of bg +function toggle_fg_bg() { + if [[ $#BUFFER -eq 0 ]]; then + BUFFER="fg" + zle accept-line + else + BUFFER="" + zle clear-screen + fi +} +zle -N toggle_fg_bg +bindkey '^Z' toggle_fg_bg + +# Tmux layout +openSession () { + tmux split-window -h -t + tmux split-window -v -t + tmux resize-pane -U 5 +} + +# archive compress +compress() { + if [[ -n "$1" ]]; then + local file=$1 + shift + case "$file" in + *.tar ) tar cf "$file" "$*" ;; + *.tar.bz2 ) tar cjf "$file" "$*" ;; + *.tar.gz ) tar czf "$file" "$*" ;; + *.tgz ) tar czf "$file" "$*" ;; + *.zip ) zip "$file" "$*" ;; + *.rar ) rar "$file" "$*" ;; + * ) tar zcvf "$file.tar.gz" "$*" ;; + esac + else + echo 'usage: compress ./foo ./bar' + fi +} + +# archive extract +extract() { + if [[ -f "$1" ]] ; then + local filename=$(basename "$1") + local foldername=${filename%%.*} + local fullpath=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$1") + local didfolderexist=false + if [[ -d "$foldername" ]]; then + didfolderexist=true + read -p "$foldername already exists, do you want to overwrite it? (y/n) " -n 1 + echo + if [[ "$REPLY" =~ ^[Nn]$ ]]; then + return + fi + fi + mkdir -p "$foldername" && cd "$foldername" + case "$1" in + *.tar.bz2) tar xjf "$fullpath" ;; + *.tar.gz) tar xzf "$fullpath" ;; + *.tar.xz) tar Jxvf "$fullpath" ;; + *.tar.Z) tar xzf "$fullpath" ;; + *.tar) tar xf "$fullpath" ;; + *.taz) tar xzf "$fullpath" ;; + *.tb2) tar xjf "$fullpath" ;; + *.tbz) tar xjf "$fullpath" ;; + *.tbz2) tar xjf "$fullpath" ;; + *.tgz) tar xzf "$fullpath" ;; + *.txz) tar Jxvf "$fullpath" ;; + *.zip) unzip "$fullpath" ;; + *) echo "'$1' cannot be extracted via extract()" \ + && cd .. \ + && ! "$didfolderexist" \ + && rm -r "$foldername" ;; + esac + else + echo "'$1' is not a valid file" + fi +} +## Extract with one command +#extract () { +# if [ -f $1 ] ; then +# case $1 in +# *.tar.bz2) tar xjf $1 ;; +# *.tar.gz) tar xzf $1 ;; +# *.bz2) bunzip2 $1 ;; +# *.rar) rar 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 +#} + +ports() { + local result + result=$(sudo netstat -tulpn | grep LISTEN) + echo "$result" | fzf +} + +trash() { + case "$1" in + --list) + ls -A1 ~/.local/share/Trash/files/ + ;; + --empty) + ls -A1 ~/.local/share/Trash/files/ && \rm -rfv ~/.local/share/Trash/files/* + ;; + --restore) + gio trash --restore "$(gio trash --list | fzf | cut -f 1)" + ;; + --delete) + trash_files=$(ls -A ~/.local/share/Trash/files/ | fzf --multi); echo $trash_files | xargs -I {} rm -rf ~/.local/share/Trash/files/{} + ;; + *) + gio trash "$@" + ;; + esac +} + +# Git +## Use gh instead of git (fast GitHub command line client). +#if type gh >/dev/null; then +# alias git=gh +# if type compdef >/dev/null 2>/dev/null; then +# compdef gh=git +# fi +#fi +#check_gh_installed() { +# if command -v gh &> /dev/null; then +# return 0 # gh is installed +# else +# return 1 # gh is not installed +# fi +#} +# +## Set alias for git to gh if gh is installed +#if check_gh_installed; then +# alias git=gh +#fi + +# No arguments: `git status` +# With arguments: acts like `git` +g() { + if [ $# -gt 0 ]; then + git "$@" # If arguments are provided, pass them to git + else + git status # Otherwise, show git status + fi +} + +# Complete g like git +compdef g=git + +# Define functions for common Git commands +ga() { g add "$@"; } # ga: Add files to the staging area +gaw() { g add -A && g diff --cached -w | g apply --cached -R; } # gaw: Add all changes to the staging area and unstage whitespace changes +grm() { g rm "$@"; } +gb() { g branch "$@"; } # gb: List branches +gbl() { g branch -l "$@"; } # gbl: List local branches +gbD() { g branch -D "$@"; } # gbD: Delete a branch +gbu() { g branch -u "$@"; } # gbu: Set upstream branch +ge() { g clone "$@"; } +gc() { g commit "$@"; } # gc: Commit changes +gcm() { g commit -m "$@"; } # gcm: Commit with a message +gca() { g commit -a "$@"; } # gca: Commit all changes +gcaa() { g commit -a --amend "$@"; } # gcaa: Amend the last commit +gcam() { g commit -a -m "$@"; } # gcam: Commit all changes with a message +gce() { g commit -e "$@"; } # gce: Commit with message and allow editing +gcfu() { g commit --fixup "$@"; } # gcfu: Commit fixes in the context of the previous commit +gco() { g checkout "$@"; } # gco: Checkout a branch or file +gcob() { g checkout -b "$@"; } # gcob: Checkout a new branch +gcoB() { g checkout -B "$@"; } # gcoB: Checkout a new branch, even if it exists +gcp() { g cherry-pick "$@"; } # gcp: Cherry-pick a commit +gcpc() { g cherry-pick --continue "$@"; } # gcpc: Continue cherry-picking after resolving conflicts +gd() { g diff "$@"; } # gd: Show changes +#gd^() { g diff HEAD^ HEAD "$@"; } # gd^: Show changes between HEAD^ and HEAD +gds() { g diff --staged "$@"; } # gds: Show staged changes +gl() { g lg "$@"; } # gl: Show a customized log +glg() { g log --graph --decorate --all "$@"; } # glg: Show a customized log with graph +gls() { # Query `glog` with regex query. + query="$1" + shift + glog --pickaxe-regex "-S$query" "$@" +} +gdc() { g diff --cached "$@"; } # gdc: Show changes between the working directory and the index +gu() { g pull "$@"} # gu: Pull +gp() { g push "$@"} # gp: Push +gpom() { g push origin main "$@"; } # gpom: Push changes to origin main +gr() { g remote "$@"; } # gr: Show remote +gra() { g rebase --abort "$@"; } # gra: Abort a rebase +grb() { g rebase --committer-date-is-author-date "$@"; } # grb: Rebase with the author date preserved +grbom() { grb --onto master "$@"; } # grbom: Rebase onto master +grbasi() { g rebase --autosquash --interactive "$@"; } # grbasi: Interactive rebase with autosquash +grc() { g rebase --continue "$@"; } # grc: Continue a rebase +grs() { g restore --staged "$@"; } # grs: Restore changes staged for the next commit +grv() { g remote -v "$@"; } # grv: Show remote URLs after each name +grh() { g reset --hard "$@"; } # grh: Reset the repository and the working directory +grH() { g reset HEAD "$@"; } # grH: Reset the index but not the working directory +#grH^() { g reset HEAD^ "$@"; } # grH^: Reset the index and working directory to the state of the HEAD's first parent +gs() { g status -sb "$@"; } # gs: Show the status of the working directory and the index +gsd() { g stash drop "$@"; } # gsd: Drop a stash +gsl() { g stash list --date=relative "$@"; } # gsl: List all stashes +gsp() { g stash pop "$@"; } # gsp: Apply and remove a single stash +gss() { g stash show "$@"; } # gss: Show changes recorded in the stash as a diff +gst() { g status "$@"; } # gst: Show the status of the working directory and the index +gsu() { g standup "$@"; } # gsu: Customized standup command +gforgotrecursive() { g submodule update --init --recursive --remote "$@"; } # gforgotrecursive: Update submodules recursively +gfp() { g commit --amend --no-edit && g push --force-with-lease "$@"; } # gfp: Amending the last commit and force-pushing diff --git a/linux/home/.config/zsh/user/options.zsh b/linux/home/.config/zsh/user/options.zsh new file mode 100644 index 0000000..0e97fed --- /dev/null +++ b/linux/home/.config/zsh/user/options.zsh @@ -0,0 +1,50 @@ + +# Let FZF use ripgrep by default +if type rg &> /dev/null; then + export FZF_DEFAULT_COMMAND='rg --files' + export FZF_DEFAULT_OPTS='-m --height 50% --border' +fi + + +# Allow nnn filemanager to cd on quit +nnn() { + declare -x +g NNN_TMPFILE=$(mktemp --tmpdir $0.XXXX) + trap "rm -f $NNN_TMPFILE" EXIT + =nnn $@ + [ -s $NNN_TMPFILE ] && source $NNN_TMPFILE +} + + +# NVM +#nvm() { +# local green_color +# green_color=$(tput setaf 2) +# local reset_color +# reset_color=$(tput sgr0) +# echo -e "${green_color}nvm${reset_color} $@" +#} +if [ -s "$NVM_DIR/nvm.sh" ]; then + nvm_cmds=(nvm node npm yarn) + for cmd in "${nvm_cmds[@]}"; do + alias "$cmd"="unalias ${nvm_cmds[*]} && unset nvm_cmds && . $NVM_DIR/nvm.sh && $cmd" + done +fi + +# Kubernetes +# kubernetes aliases +if command -v kubectl > /dev/null; then + replaceNS() { kubectl config view --minify --flatten --context=$(kubectl config current-context) | yq ".contexts[0].context.namespace=\"$1\"" ; } + alias kks='KUBECONFIG=<(replaceNS "kube-system") kubectl' + alias kam='KUBECONFIG=<(replaceNS "authzed-monitoring") kubectl' + alias kas='KUBECONFIG=<(replaceNS "authzed-system") kubectl' + alias kar='KUBECONFIG=<(replaceNS "authzed-region") kubectl' + alias kt='KUBECONFIG=<(replaceNS "tenant") kubectl' + + if command -v kubectl-krew > /dev/null; then + path=($XDG_CONFIG_HOME/krew/bin $path) + fi + + rmfinalizers() { + kubectl get deployment "$1" -o json | jq '.metadata.finalizers = null' | kubectl apply -f - + } +fi diff --git a/linux/home/.config/zsh/user/prompt.zsh b/linux/home/.config/zsh/user/prompt.zsh new file mode 100644 index 0000000..d9fc148 --- /dev/null +++ b/linux/home/.config/zsh/user/prompt.zsh @@ -0,0 +1,202 @@ +#!/bin/zsh + +########## Prompt(s) ########## + +terminfo_down_sc=$terminfo[cud1]$terminfo[cuu1]$terminfo[sc]$terminfo[cud1] + +autoload -Uz vcs_info +autoload -Uz add-zsh-hook +autoload -U colors && colors + +precmd_vcs_info() { vcs_info } + +precmd_functions+=( precmd_vcs_info ) + +setopt prompt_subst + +git_branch_test_color() { + local ref=$(git symbolic-ref --short HEAD 2> /dev/null) + if [ -n "${ref}" ]; then + if [ -n "$(git status --porcelain)" ]; then + local gitstatuscolor='%F{green}' + else + local gitstatuscolor='%F{82}' + fi + echo "${gitstatuscolor}${ref}" + else + echo "" + fi +} + +zstyle ':vcs_info:*' check-for-changes true +zstyle ':vcs_info:*' stagedstr ' +%F{15}staged%f' +zstyle ':vcs_info:*' unstagedstr ' -%F{15}unstaged%f' +zstyle ':vcs_info:*' actionformats '%F{5}%F{2}%b%F{3}|%F{1}%a%F{5}%f ' +zstyle ':vcs_info:*' formats '%F{208} '$'\uE0A0'' %f$(git_branch_test_color)%f%F{76}%c%F{3}%u%f ' +zstyle ':vcs_info:git*+set-message:*' hooks git-untracked +zstyle ':vcs_info:*' enable git + ++vi-git-untracked() { + if [[ $(git rev-parse --is-inside-work-tree 2> /dev/null) == 'true' ]] && \ + git status --porcelain | grep '??' &> /dev/null ; then + hook_com[unstaged]+='%F{196} !%f%F{15}untracked%f' + fi +} + +ssh_name() { + if [[ -n $SSH_CONNECTION ]]; then + local ssh_info + ssh_info="ssh:%F{green}%n$nc%f" + if [[ -n $SSH_CONNECTION ]]; then + local ip_address + ip_address=$(echo $SSH_CONNECTION | awk '{print $3}') + ssh_info="$ssh_info@%F{green}$ip_address%f" + fi + echo " ${ssh_info}" + fi +} + +function job_name() { + job_name="" + job_length=0 + if [ "${COLUMNS}" -gt 69 ]; then + job_length=$((${COLUMNS}-70)) + [ "${job_length}" -lt "0" ] && job_length=0 + fi + + if [ "${job_length}" -gt 0 ]; then + local job_count=$(jobs | wc -l) + if [ "${job_count}" -gt 0 ]; then + local title_jobs="jobs:" + job_name="${title_jobs}" + job_name+="%F{green}$(jobs | grep + | tr -s " " | cut -d " " -f 4- | cut -b 1-${job_length} | sed "s/\(.*\)/\1/")%f" + fi + fi + + echo "${job_name}" +} + +function job_count() { + local job_count + job_count=$(jobs -s | grep -c "suspended") + if [ "${job_count}" -gt 0 ]; then + echo "(${job_count})" + fi +} + +current_jobs=' $(job_name)$(job_count)' +user="%n" +at="%F{15}at%{$reset_color%}" +machine="%F{4}%m%{$reset_color%}" +relative_home="%F{4}%~%{$reset_color%}" +carriage_return=""$'\n'"" +empty_line_bottom="%r" +chevron_right="" +color_reset="%{$(tput sgr0)%}" +color_yellow="%{$(tput setaf 226)%}" +color_blink="%{$(tput blink)%}" +prompt_symbol="$" +dollar_sign="${color_yellow}${color_blink}${prompt_symbol}${color_reset}" +dollar="%(?:%F{2}${dollar_sign}:%F{1}${dollar_sign})" +space=" " +cmd_prompt="%(?:%F{2}${chevron_right} :%F{1}${chevron_right} )" +git_info="\$vcs_info_msg_0_" +v1="%{┌─[%}" +v2="%{]%}" +v3="└─[" +v4="]" + +function insert-mode () { echo "-- INSERT --" } +function normal-mode () { echo "-- NORMAL --" } + +vi-mode-indicator () { + if [[ ${KEYMAP} == vicmd || ${KEYMAP} == vi-cmd-mode ]]; then + echo -ne '\e[1 q' + vi_mode=$(normal-mode) + elif [[ ${KEYMAP} == main || ${KEYMAP} == viins || ${KEYMAP} == '' ]]; then + echo -ne '\e[5 q' + vi_mode=$(insert-mode) + fi +} + +function set-prompt () { + vi-mode-indicator + mode="%F{145}%{$terminfo_down_sc$vi_mode$terminfo[rc]%f%}" + #PS1="${relative_home}${vcs_info_msg_0_}${current_jobs} ${carriage_return}${mode}${dollar}${space}" + PS1="${v1}${user}${v2}${space}${relative_home}${vcs_info_msg_0_}${current_jobs}$(ssh_name) ${carriage_return}${mode}${v3}${dollar}${v4}${empty_line_bottom}" + #RPROMPT="$(ssh_name)" +} + +precmd () { + print -rP + vcs_info + set-prompt +} + +function update-mode-file() { + set-prompt + local current_mode=$(cat ~/.vi-mode) + local new_mode="$vi_mode" + if [[ "$new_mode" != "$current_mode" ]]; then + echo "$new_mode" >| ~/.vi-mode + fi + if command -v tmux &>/dev/null && [[ -n "$TMUX" ]]; then + tmux refresh-client -S + fi +} + +function check-nvim-running() { + if pgrep -x "nvim" > /dev/null; then + vi_mode="" + update-mode-file + if command -v tmux &>/dev/null && [[ -n "$TMUX" ]]; then + tmux refresh-client -S + fi + else + if [[ ${KEYMAP} == vicmd || ${KEYMAP} == vi-cmd-mode ]]; then + vi_mode=$(normal-mode) + elif [[ ${KEYMAP} == main || ${KEYMAP} == viins || ${KEYMAP} == '' ]]; then + vi_mode=$(insert-mode) + fi + update-mode-file + if command -v tmux &>/dev/null && [[ -n "$TMUX" ]]; then + tmux refresh-client -S + fi + fi +} + +function zle-line-init() { + zle reset-prompt + case "${KEYMAP}" in + vicmd) + echo -ne '\e[1 q' + ;; + main|viins|*) + echo -ne '\e[5 q' + ;; + esac +} + +function zle-keymap-select() { + update-mode-file + zle reset-prompt + case "${KEYMAP}" in + vicmd) + echo -ne '\e[1 q' + ;; + main|viins|*) + echo -ne '\e[5 q' + ;; + esac +} + +preexec () { print -rn -- $terminfo[el]; echo -ne '\e[5 q' ; } + +zle -N zle-line-init +zle -N zle-keymap-select + +TRAPWINCH() { + update-mode-file +} + +set-prompt -- cgit v1.2.3