# Set case insensitive shell completion if [ -n "$BASH_VERSION" ]; then bind "set completion-ignore-case on"; alias fcp='HISTFILE=/dev/null bash -i' fi # New no-history shell in ZSH if [ -n "$ZSH_VERSION" ]; then alias fcp="fc -p" fi # Space added in order to allow alias expansion alias sudo='sudo ' # mixed usefull things #alias nano='nano -c' #alias nano='SUDO_EDITOR="nano -c" sudoedit' alias gistory="history | grep -i $1" alias untar="tar -xvf" alias cd..="cd .." # Copy file(s) showing progress info alias rcp='rsync -ahWIU --no-owner --no-group --no-inc-recursive --info=progress2' alias rcpv='rsync -ahvWIU --no-owner --no-group --no-inc-recursive --info=flist,progress1,progress2' # Human readable filesizes alias df="df -h" alias du="du -h" # Some usefull network related aliases alias ip="ip -c" alias iplist="ip -br -c addr show" alias maclist="ip -o link | awk '$2 != "lo:" {print $2, $17}'" alias routelist="ip -c r" # --- alias ipa=iplist alias ipm=maclist alias ipr=routelist alias ipp="ss -tulpn" alias ipar="ipa && echo && ipr" # Create parent directory on demand if needed alias mksdir='mkdir -pv' # Watch with color for commands like "service" alias watchc="watch -c SYSTEMD?COLORS=1" # Disable history and clear itself from history; if inside tmux change to red the background color of the pane alias nohistory="set +o history && history -d -1 && if [ $TMUX ]; then tmux select-pane -P 'bg=#440000'; fi" # Check and use eza in place of standard ls if command -v eza 2>&1 >/dev/null then #alias eza="eza --icons" alias ls="eza --group-directories-first" #alias ll="eza --group-directories-first --long --all --octal-permissions --no-permissions --group --header --time-style=long-iso" alias ll="eza --group-directories-first --long --all -a --group --header --time-style=long-iso" else alias ls="ls --color=auto" alias ll="ls -alFh" fi # Grep custom shortcuts alias grep='grep --color=auto' alias egrep='egrep --color=auto' alias fgrep='fgrep --color=auto' # Less custom shortcut alias gless='less -G' alias gview='view "+normal G$"' # Check and replace standard cat with bat if command -v batcat 2>&1 >/dev/null then # require batcat installed: `sudo apt install bat` alias cat="batcat --paging=never --style=plain" alias bat="batcat --paging=never" fi # Hashing shortcuts alias sha1="sha1sum" alias md5="md5sum" alias sha512="sha512sum" alias sha256="sha256sum" # Check if veracrypt is installed and add shortcuts if command -v veracrypt 2>&1 >/dev/null then alias vu="veracrypt -u" fi # Check if uv is installed and add shortcuts if command -v uv 2>&1 >/dev/null then alias uvr="uv run" alias uvp="uv run python" alias uvm="uv run python manage.py" fi # Recursive clean current folder fronl python cache and compiled files pycclean() { find . -type f -name '*.py[co]' -delete -o -type d -name __pycache__ -delete -delete } # Ipscan via nmap icmp test ipscan() { # Check if an argument (IP or subnet) was provided if [ -z "$1" ]; then echo "Error: you must specify a subnet or an IP." echo "Usage: ipscan <192.168.x.x/24>" return 1 fi # Execute the command using the provided argument nmap -sn -PE "$1" -oG - | awk '/Up$/{print $2}' } # Perform apt update as sudo, # then list upgradable packages # and ask to proceed with upgrade alias supdate='sudo apt update && apt list --upgradable && read -t 10 -p "Press [ENTER] or wait 10 seconds..."; sudo NEEDRESTART_MODE=a apt dist-upgrade -y && sudo apt autoremove -y && sudo apt clean -y' # pi-agend sandbox via docker pi-sandbox-docker() { docker run --rm -it \ -v "${PWD}:/workspace" \ -v "pi-agent-home:/root/.pi/agent" \ pi-sandbox "$@" } # start pi coding agent in lxc container pi-sandbox-incus-shared() { emulate -L zsh setopt localtraps local instance="pi-sandbox" local source_dir local project_name local safe_name local hash local device local target local exit_code=0 local mounted=0 local cleaning=0 local active_sessions=0 source_dir="$(realpath -- "$PWD")" || return 1 project_name="$(basename -- "$source_dir")" safe_name="$(printf '%s' "$project_name" | sed 's/[^[:alnum:]_.-]/-/g')" hash="$(printf '%s' "$source_dir" | sha256sum | cut -c1-5)" device="piw-${safe_name}-${hash}" target="/ws/${safe_name}-${hash}" _pi_sandbox_shared_cleanup() { (( cleaning )) && return cleaning=1 if (( mounted )); then echo "Restoring ownership: $source_dir" incus exec "$instance" -- sh -c \ 'cd "$1" && find . -xdev -exec chown --no-dereference --reference=. {} +' \ _ "$target" #echo "Removing workspace device: $device" incus config device remove "$instance" "$device" mounted=0 fi active_sessions="$( incus config device list "$instance" 2>/dev/null | grep -Ec '^piw-.*-[[:xdigit:]]{5}$' || true )" if (( active_sessions == 0 )); then if incus info "$instance" 2>/dev/null | grep -q '^Status: RUNNING$'; then incus stop "$instance" fi printf '%s \033[31mstopped\033[0m\n' "$instance" elif (( active_sessions == 1 )); then printf '1 active session, %s \033[33mstill running\033[0m\n' "$instance" else printf '%s active sessions, %s \033[33mstill running\033[0m\n' \ "$active_sessions" "$instance" fi } trap '_pi_sandbox_shared_cleanup; return 130' INT trap '_pi_sandbox_shared_cleanup; return 143' TERM trap '_pi_sandbox_shared_cleanup; return 129' HUP # Remove a stale device left by an interrupted previous execution. if incus config device list "$instance" 2>/dev/null | grep -Fxq "$device"; then if incus info "$instance" 2>/dev/null | grep -q '^Status: RUNNING$'; then echo "Error: project is already mounted: $target" return 1 fi incus config device remove "$instance" "$device" || return 1 fi if ! incus info "$instance" 2>/dev/null | grep -q '^Status: RUNNING$'; then incus start "$instance" || return 1 fi incus config device add "$instance" "$device" disk \ source="$source_dir" \ path="$target" \ shift=true || return 1 mounted=1 if [[ "$1" == "shell" ]]; then shift incus exec "$instance" --cwd "$target" -- bash "$@" elif [[ "$1" == "list" ]]; then shift incus exec "$instance" --cwd /workspace -- bash -c ' package="" while IFS= read -r line; do trimmed="${line#"${line%%[![:space:]]*}"}" [[ -z "$trimmed" ]] && continue if [[ "$trimmed" == "User packages:" ]]; then printf "%s\n" "$trimmed" continue fi if [[ "$trimmed" == /* ]]; then path="$trimmed" version="" if [[ -f "$path/package.json" ]]; then version="$(node -p "require(process.argv[1]).version || \"\"" "$path/package.json" 2>/dev/null)" fi if [[ -n "$package" ]]; then if [[ -n "$version" ]]; then printf " %s - %s\n" "$package" "$version" else printf " %s\n" "$package" fi fi printf "\033[90m %s\033[0m\n" "$path" package="" else package="$trimmed" fi done < <(pi list "$@") if [[ -n "$package" ]]; then printf " %s\n" "$package" fi ' _ "$@" else incus exec "$instance" --cwd "$target" -- pi "$@" fi exit_code=$? _pi_sandbox_shared_cleanup trap - INT TERM HUP unfunction _pi_sandbox_shared_cleanup 2>/dev/null return "$exit_code" } alias pi='pi-sandbox-incus-shared' # minimal docker ps colored tab docker-ps() { docker ps -a --format "table {{.ID}}\t{{.Names}}\t{{.Status}}" \ | awk ' NR == 1 { print; next } /Up / { printf "\033[32m%s\033[0m\n", $0; next } /Exited / { printf "\033[31m%s\033[0m\n", $0; next } { print } ' } # Wrap nano to track the absolute path of a single edited (ALT+S to save readonly in nanorc) file and always enable cursor position display. unalias nano 2>/dev/null nano() { if [[ $# -eq 1 ]]; then NANO_CURRENT_FILE="$(realpath -m -- "$1")" command nano -c "$1" else command nano -c "$@" fi } # Lazy command to perform git status-add-commit and skippable push lazygit() { if [[ -n "${ZSH_VERSION:-}" ]]; then emulate -L zsh setopt ksh_arrays fi local message="" arg choice local skip_push=0 file_index=0 tracked_count=0 local -a changed_files=() for arg in "$@"; do if [[ "$arg" == "-np" ]]; then skip_push=1 elif [[ -z "$message" ]]; then message="$arg" else printf 'Usage: lazygit "commit message" [-np]\n' return 1 fi done if [[ -z "$message" ]]; then printf 'Usage: lazygit "commit message" [-np]\n' return 1 fi git status || return 1 while true; do printf 'Proceed, differences, or abort/quit? [P/d/a/q] ' IFS= read -r choice || return 1 case "$choice" in ''|[pP]*) break ;; [dD]*) git diff --stat --color=always || return 1 while true; do printf 'Proceed, review, or abort/quit? [P/r/a/q] ' IFS= read -r choice || return 1 case "$choice" in ''|[pP]*) break 2 ;; [rR]*) while IFS= read -r -d '' arg; do changed_files+=("$arg") done < <(git diff HEAD --name-only -z) tracked_count=${#changed_files[@]} while IFS= read -r -d '' arg; do changed_files+=("$arg") done < <(git ls-files --others --exclude-standard -z) if (( ${#changed_files[@]} == 0 )); then printf 'No changed files to review.\n' continue fi file_index=0 while true; do if (( file_index < tracked_count )); then git diff --color=always HEAD -- "${changed_files[$file_index]}" || return 1 else git diff --color=always --no-index -- /dev/null "${changed_files[$file_index]}" (( $? <= 1 )) || return 1 fi while true; do if (( file_index == ${#changed_files[@]} - 1 )); then printf 'Continue, previous, next, or abort/quit? [C/p/n/a/q] ' else printf 'Continue, previous, next, or abort/quit? [c/p/N/a/q] ' fi IFS= read -r choice || return 1 if [[ -z "$choice" ]]; then if (( file_index == ${#changed_files[@]} - 1 )); then choice=c else choice=n fi fi case "$choice" in [cC]*) break 4 ;; [pP]*) if (( file_index > 0 )); then ((file_index -= 1)) break fi printf 'Already at the first file.\n' ;; [nN]*) if (( file_index < ${#changed_files[@]} - 1 )); then ((file_index += 1)) break fi printf 'Already at the last file.\n' ;; [aA]*|[qQ]*) return 1 ;; *) printf 'Please choose continue, previous, next, or abort/quit.\n' ;; esac done done ;; [aA]*|[qQ]*) return 1 ;; *) printf 'Please choose proceed, review, or abort/quit.\n' ;; esac done ;; [aA]*|[qQ]*) return 1 ;; *) printf 'Please choose proceed, differences, or abort/quit.\n' ;; esac done git add . && git commit -m "$message" || return 1 printf '\033[7;32m Committed \033[0m\n' if (( ! skip_push )); then git push || return 1 printf '\033[7;32m Pushed \033[0m\n' else printf '\033[7;33m Push skipped \033[0m\n' fi printf '\n' git show --stat --oneline --color=always HEAD }