diff --git a/zsh/.config/zsh/functions.zsh b/zsh/.config/zsh/functions.zsh index 42bd1d4..e57b9aa 100644 --- a/zsh/.config/zsh/functions.zsh +++ b/zsh/.config/zsh/functions.zsh @@ -1,20 +1,30 @@ -# Lazy load zoxide +#!/bin/zsh + +# NAVIGATION AND FILE SYSTEM z() { - # Remove the placeholder function unfunction "$0" - - # Load zoxide eval "$(zoxide init zsh)" - - # Execute the command $0 "$@" } -# Ensure we have all the zoxide command variants covered zi() { z "$@" } za() { z "$@" } zrm() { zoxide remove "$@" } +function open { + for i in $*; do + setsid nohup xdg-open $i > /dev/null 2> /dev/null + done +} + +function fopen() { + local selected + selected=$(fd "$@" | fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}') + [[ -n "$selected" ]] && setsid nohup xdg-open "$selected" >/dev/null 2>&1 & +} + +# DEVELOPMENT TOOLS +# Package manager detection with caching function _package_manager { local pkg_manager="" if [[ -f bun.lockb ]]; then @@ -29,15 +39,12 @@ function _package_manager { pkg_manager="pnpm" fi - # Check if the first argument is a script in package.json if [[ -f package.json ]] && [[ $1 != "run" ]] && [[ $1 != "install" ]] && [[ $1 != "add" ]] && [[ $1 != "remove" ]] && [[ $1 != "i" ]] && [[ $1 != "rm" ]]; then - # Check if the command exists in package.json scripts using jq if jq -e ".scripts[\"$1\"] != null" package.json >/dev/null 2>&1; then set -- "run" "$@" fi fi - # Use corepack when available if command -v corepack >/dev/null 2>&1; then corepack ${pkg_manager} "$@" else @@ -45,36 +52,95 @@ function _package_manager { fi } -yarn() { echo ๐Ÿ–•; } -yarnpkg() { echo ๐Ÿ–•; } -pnpm() { echo ๐Ÿ–•; } -pn() { echo ๐Ÿ–•; } -pnpx() { echo ๐Ÿ–•; } -npm() { echo ๐Ÿ–•; } +# Improved development commit with optional message +function dc() { + if ! git rev-parse --is-inside-work-tree &>/dev/null; then + echo "Error: Not in a git repository" + return 1 + fi -alias p='_package_manager' + if [[ -z $(git status --porcelain) ]]; then + echo "No changes to commit" + return 0 + fi -alias unChonk="echo '๐Ÿงน Starting the great node_modules purge...' && find . -name 'node_modules' -type d -prune -exec sh -c 'echo \"๐Ÿ’ฅ Deleting {}\" && rm -rf \"{}\"' \;" + git add . -# Open files using system default application -function open { - for i in $* - do - setsid nohup xdg-open $i > /dev/null 2> /dev/null - done + local commit_msg + if [[ -n "$1" ]]; then + commit_msg="$1" + else + local timestamp=$(date +"%Y-%m-%d %H:%M:%S") + commit_msg="dev: automated commit - ${timestamp}" + fi + + git commit -m "$commit_msg" --no-gpg-sign + git push &>/dev/null || { echo "Push failed"; return 1; } } -function fopen() { - local selected - selected=$(fd "$@" | fzf) - [[ -n "$selected" ]] && setsid nohup xdg-open "$selected" >/dev/null 2>&1 & +# Git branch cleanup helper +function git-clean() { + local current_branch=$(git rev-parse --abbrev-ref HEAD) + local branches_to_delete=$(git branch --merged | grep -v "^\*" | grep -v "master" | grep -v "main" | grep -v "develop") + + if [[ -z "$branches_to_delete" ]]; then + echo "No merged branches to clean up" + return 0 + fi + + echo "The following merged branches will be deleted:" + echo "$branches_to_delete" + echo -n "Continue? [y/N] " + read confirm + + if [[ "$confirm" =~ ^[Yy]$ ]]; then + echo "$branches_to_delete" | xargs git branch -d + echo "Branches deleted locally" + + echo -n "Delete remote branches too? [y/N] " + read confirm_remote + + if [[ "$confirm_remote" =~ ^[Yy]$ ]]; then + echo "$branches_to_delete" | xargs -I{} git push origin --delete {} + echo "Remote branches deleted" + fi + fi } -alias fo='fopen' +function sm { /opt/sublime_merge/sublime_merge $1; } +function vimrc { + cd $XDG_CONFIG_HOME/nvim + nvim + cd - >/dev/null +} + +function zshrc { + cd $XDG_CONFIG_HOME/zsh + nvim + cd - >/dev/null +} + +# FILE SHARING AND NETWORKING function upload_file() { + local usage="Usage: $0 [-o] " + local one_time=true + + # Parse options + while getopts ":o" opt; do + case ${opt} in + o ) one_time=false ;; + \? ) + echo "Invalid option: -$OPTARG" >&2 + echo $usage + return 1 ;; + esac + done + shift $((OPTIND -1)) + + # Check file argument if [[ -z "$1" ]]; then - echo "Usage: $0 " + echo $usage return 1 fi if [[ ! -f "$1" ]]; then @@ -82,121 +148,74 @@ function upload_file() { return 1 fi - local url="https://dump.mz.uy" - # local url="http://localhost:8080" - echo "Uploading $1 to $url..." - local full_response=$(curl -i -F"file=@$1" -F"one_time=" "$url") - # local full_response=$(curl -i -F"file=@$1" "$url") - local url_response=$(echo "$full_response" | tail -n 1) - local token=$(echo "$full_response" | grep -i "X-Token:" | awk '{print $2}' | tr -d '\r') + local url="https://drop.mz.uy" + echo "Uploading $1 to $url... (one-time: ${one_time})" - if [[ -n "$url_response" ]]; then - echo -n "$url_response" | wl-copy # Wayland - echo "โœ“ Uploaded: $url_response (copied to clipboard)" + # Prepare upload options + local form_data=("-F" "file=@$1") + if $one_time; then + form_data+=("-F" "one_time=") + fi - if [[ -n "$token" ]]; then - echo "Management token: $token" + # Try up to 3 times with a short delay between attempts + local max_attempts=3 + local attempt=1 + local success=false + + while (( attempt <= max_attempts )) && ! $success; do + if (( attempt > 1 )); then + echo "Retry attempt $attempt of $max_attempts..." + sleep 1 fi - else - echo "ร— Failed to upload file" + + local full_response=$(curl -i "${form_data[@]}" "$url" 2>/dev/null) + local curl_status=$? + + if [[ $curl_status -eq 0 ]]; then + local url_response=$(echo "$full_response" | tail -n 1) + local token=$(echo "$full_response" | grep -i "X-Token:" | awk '{print $2}' | tr -d '\r') + + if [[ -n "$url_response" ]]; then + echo -n "$url_response" | wl-copy + echo "โœ“ Uploaded: $url_response (copied to clipboard)" + + if [[ -n "$token" ]]; then + echo "Management token: $token" + fi + + success=true + break + fi + fi + + (( attempt++ )) + done + + if ! $success; then + echo "ร— Failed to upload file after $max_attempts attempts" return 1 fi } -# Create both commands as aliases to the same function -alias drop='upload_file' -alias dump='upload_file' - - -# Wacom tablet configuration -function wacom { - if [ "$XDG_SESSION_TYPE" = "wayland" ]; then - systemctl --user enable opentabletdriver --now - otd loadsettings ~/Sync/wacom/wacom.json - else - # Reset area and map the stylus to DisplayPort-0, then rotate - xsetwacom --set "Wacom One by Wacom S Pen stylus" ResetArea - xsetwacom --set "Wacom One by Wacom S Pen stylus" MapToOutput DisplayPort-0 - xsetwacom --set "Wacom One by Wacom S Pen stylus" Rotate half - - # Reset area and map the eraser to DisplayPort-0 - xsetwacom --set "Wacom One by Wacom S Pen eraser" ResetArea - xsetwacom --set "Wacom One by Wacom S Pen eraser" MapToOutput DisplayPort-0 - fi -} - -# Enhanced git clone function -function gc { - if [[ "$1" == */* ]] - then - git clone "https://github.com/$1" "${@:2}" - else - git clone "https://github.com/marianozunino/$1" "${@:2}" - fi -} - -# Improved file sharing with croc -function croc-send { - croc send --code mzunino "$@" -} - -function croc-receive { - croc --yes mzunino -} - -# Fix swaymsg when inside tmux -if [[ -v TMUX ]]; then - function swaymsg { - export SWAYSOCK=$XDG_RUNTIME_DIR/sway-ipc.$UID.$(pgrep -x sway).sock - command swaymsg "$@" - } -fi - -# Expose local port to internet function expose() { if [ -z "$1" ]; then echo "Usage: expose " - return + return 1 fi ssh marianozunino@srv.us -R 1:localhost:$1 } -# Helper function for command existence check -function _has { - return $( whence $1 >/dev/null ) -} - -# Sublime merge shortcut -function sm { - /opt/sublime_merge/sublime_merge $1 -} - -# Edit nvim config -function vimrc { - cd $XDG_CONFIG_HOME/nvim - nvim - cd - -} - -# Edit zsh config -function zshrc { - cd $XDG_CONFIG_HOME/zsh - nvim - cd - -} - -# Find process using a port function ppid { lsof -i :$1 } -alias pport=ppid +alias pport="ppid" -# Kubernetes port forwarding helper +# KUBERNETES AND DEVOPS function kf { if [ -z "$1" ]; then echo "Usage: kf [service-name]" - return + return 1 fi local namespace="oc-app" @@ -210,6 +229,36 @@ function kf { sudo -E kubefwd svc -n ${namespace} -x ${cluster} ${svc_filter} } +# SYSTEM AND UTILITY FUNCTIONS +# Lazy-load handler for heavy tools +function _lazy_load() { + local cmd="$1" + local loader="$2" + + eval "${cmd}() { + unfunction $cmd + eval \"\$($loader)\" + $cmd \"\$@\" + }" +} + +# Example: lazy load kubectl completion +_lazy_load kubectl "kubectl completion zsh" + +function wacom { + if [ "$XDG_SESSION_TYPE" = "wayland" ]; then + systemctl --user enable opentabletdriver --now + otd loadsettings ~/Sync/wacom/wacom.json + else + xsetwacom --set "Wacom One by Wacom S Pen stylus" ResetArea + xsetwacom --set "Wacom One by Wacom S Pen stylus" MapToOutput DisplayPort-0 + xsetwacom --set "Wacom One by Wacom S Pen stylus" Rotate half + + xsetwacom --set "Wacom One by Wacom S Pen eraser" ResetArea + xsetwacom --set "Wacom One by Wacom S Pen eraser" MapToOutput DisplayPort-0 + fi +} + function cat { if [ -n "$SSH_TTY" ] || [ -n "$SSH_CLIENT" ] || [ -n "$SSH_CONNECTION" ]; then bat --plain --paging=never "$@" @@ -218,101 +267,48 @@ function cat { fi } -# Enhanced PrivateBin sharing function -function pb { - local usage="Usage: pb [-b] [-e ] " - local burn_after_reading=false - local expiration="1week" - - while getopts ":be:" opt; do - case ${opt} in - b ) - burn_after_reading=true - ;; - e ) - expiration=$OPTARG - ;; - \? ) - echo "Invalid option: -$OPTARG" >&2 - echo $usage - return 1 - ;; - : ) - echo "Option -$OPTARG requires an argument." >&2 - echo $usage - return 1 - ;; - esac - done - shift $((OPTIND -1)) - - if [ $# -eq 0 ]; then - echo $usage - return 1 - fi - - local file=$1 - if [ ! -f "$file" ]; then - echo "Error: File '$file' not found." >&2 - return 1 - fi - - # Check for required commands - for cmd in privatebin wl-copy; do - if ! command -v $cmd &> /dev/null; then - echo "Error: '$cmd' command not found. Please install it." >&2 - return 1 - fi - done - - # Prepare the command - local cmd="privatebin create --filename $file --expire $expiration" - if $burn_after_reading; then - cmd="$cmd --burn-after-reading" - fi - - # Run command and handle result - local result - result=$(eval "$cmd" 2>&1) - if [ $? -ne 0 ]; then - echo "Error: Failed to upload file to PrivateBin. Details:" >&2 - echo "$result" >&2 - return 1 - fi - - echo $result - echo "$result" | wl-copy - echo "PrivateBin link copied to clipboard." - notify-send "PrivateBin" "Link copied to clipboard" 2>/dev/null || true +function _has { + return $( whence $1 >/dev/null ) } -# Load autocomplete files +# History-based directory navigation +function cdr { + local dir + dir=$(dirs -pl | awk '!x[$0]++' | fzf --height 40% --reverse) + [[ -n "$dir" ]] && cd "$dir" +} + +if [[ -v TMUX ]]; then + function swaymsg { + export SWAYSOCK=$XDG_RUNTIME_DIR/sway-ipc.$UID.$(pgrep -x sway).sock + command swaymsg "$@" + } +fi + +# COMPLETIONS for completion_file in ~/.local/share/zsh/*-autocomplete.zsh; do if [ -f "$completion_file" ]; then source "$completion_file" fi done -# Initialize completions for common tools if command -v rop &> /dev/null; then eval "$(rop completion zsh)"; fi if command -v goq &> /dev/null; then eval "$(goq completion zsh)"; fi if command -v kubefwd &> /dev/null; then eval "$(kubefwd completion zsh)"; fi if command -v bombadil &> /dev/null; then eval "$(bombadil generate-completions zsh)"; fi if command -v eza &> /dev/null; then compdef eza=ls; fi -function dc() { - if ! git rev-parse --is-inside-work-tree &>/dev/null; then - echo "Error: Not in a git repository" - return 1 - fi +# ALIASES +yarn() { echo ๐Ÿ–•; } +yarnpkg() { echo ๐Ÿ–•; } +pnpm() { echo ๐Ÿ–•; } +pn() { echo ๐Ÿ–•; } +pnpx() { echo ๐Ÿ–•; } +npm() { echo ๐Ÿ–•; } - if [[ -z $(git status --porcelain) ]]; then - echo "No changes to commit" - return 0 - fi - - git add . - local timestamp=$(date +"%Y-%m-%d %H:%M:%S") - git commit -m "dev: automated commit - ${timestamp}" --no-gpg-sign - git push &>/dev/null -} +alias p='_package_manager' +alias fo='fopen' +alias drop='upload_file' +alias dump='upload_file' +alias pport=ppid +alias unChonk="echo '๐Ÿงน Starting the great node_modules purge...' && find . -name 'node_modules' -type d -prune -exec sh -c 'echo \"๐Ÿ’ฅ Deleting {}\" && rm -rf \"{}\"' \;"