dotfiles/zsh/.config/zsh/functions.zsh

418 lines
11 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/zsh
eval "$(zoxide init zsh)"
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
pkg_manager="bun"
elif [[ -f pnpm-lock.yaml ]]; then
pkg_manager="pnpm"
elif [[ -f yarn.lock ]]; then
pkg_manager="yarn"
elif [[ -f package-lock.json ]]; then
pkg_manager="npm"
else
pkg_manager="pnpm"
fi
if [[ -f package.json ]] && [[ $1 != "run" ]] && [[ $1 != "install" ]] && [[ $1 != "add" ]] && [[ $1 != "remove" ]] && [[ $1 != "i" ]] && [[ $1 != "rm" ]]; then
if jq -e ".scripts[\"$1\"] != null" package.json >/dev/null 2>&1; then
set -- "run" "$@"
fi
fi
if command -v corepack >/dev/null 2>&1; then
corepack ${pkg_manager} "$@"
else
command ${pkg_manager} "$@"
fi
}
# 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
if [[ -z $(git status --porcelain) ]]; then
echo "No changes to commit"
return 0
fi
git add .
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
# pass other args
git commit -m "$commit_msg" --no-gpg-sign "$@"
git push &>/dev/null || { echo "Push failed"; return 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
}
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] <file>"
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
return 1
fi
if [[ ! -f "$1" ]]; then
echo "Error: File not found: $1"
return 1
fi
local url="https://drop.mz.uy"
echo "Uploading $1 to $url... (one-time: ${one_time})"
# Prepare upload options
local form_data=("-F" "file=@$1")
if $one_time; then
form_data+=("-F" "one_time=")
fi
# 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
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
}
function expose() {
if [ -z "$1" ]; then
echo "Usage: expose <port>"
return 1
fi
ssh marianozunino@srv.us -R 1:localhost:$1
}
function ppid {
lsof -i :$1
}
alias pport="ppid"
# KUBERNETES AND DEVOPS
function kf {
if [ -z "$1" ]; then
echo "Usage: kf <cluster> [service-name]"
return 1
fi
local namespace="oc-app"
local cluster="oc-$1-eks-cluster"
local svc_filter=""
if [ ! -z "$2" ]; then
svc_filter="-l app.kubernetes.io/instance=$2"
fi
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 "$@"
else
bat "$@"
fi
}
function toggle_resolution() {
local mirror_mode=false
# Verificar flags
while [[ $# -gt 0 ]]; do
case $1 in
-m|--mirror)
mirror_mode=true
shift
;;
*)
shift
;;
esac
done
# Obtener estado actual del monitor interno
current_state=$(swaymsg -t get_outputs | jq -r '.[] | select(.name == "eDP-1") | "\(.current_mode.width)x\(.current_mode.height):\(.scale)"')
# Detectar monitores externos conectados
external_monitor=""
if swaymsg -t get_outputs | jq -r '.[].name' | grep -q "DP-2"; then
external_monitor="DP-2"
elif swaymsg -t get_outputs | jq -r '.[].name' | grep -q "HDMI-A-1"; then
external_monitor="HDMI-A-1"
fi
if [[ "$mirror_mode" == true ]] || [[ -n "$external_monitor" ]]; then
echo "Switching to mirror mode (1920x1080)..."
# Configurar monitor interno a 1920x1080
swaymsg output eDP-1 resolution 1920x1080@120Hz scale 1.0 pos 0 0
# Configurar monitor externo si está conectado
if [[ -n "$external_monitor" ]]; then
swaymsg output "$external_monitor" resolution 1920x1080@60Hz pos 0 0
echo "Mirror mode enabled: eDP-1 + $external_monitor at 1920x1080"
else
echo "Monitor interno configurado a 1920x1080 (sin monitor externo detectado)"
fi
elif [[ "$current_state" == "2880x1920:2.0" ]]; then
echo "Switching to 1920x1080 (16:9)..."
swaymsg output eDP-1 resolution 1920x1080@120Hz scale 1.0
# Deshabilitar mirroring si hay monitor externo
if [[ -n "$external_monitor" ]]; then
swaymsg output "$external_monitor" pos 1920 0
echo "Extended mode: $external_monitor positioned to the right"
fi
else
echo "Switching to 2880x1920 (3:2) native..."
swaymsg output eDP-1 resolution 2880x1920@120Hz scale 2.0
# Deshabilitar mirroring si hay monitor externo
if [[ -n "$external_monitor" ]]; then
swaymsg output "$external_monitor" pos 1440 0
echo "Extended mode: $external_monitor positioned to the right"
fi
fi
# Mostrar estado final
echo "Current configuration:"
swaymsg -t get_outputs | jq -r '.[] | select(.active == true) | " \(.name): \(.current_mode.width)x\(.current_mode.height)@\(.current_mode.refresh/1000)Hz scale:\(.scale) pos:(\(.rect.x),\(.rect.y))"'
}
function cb {
export GTK_THEME=HighContrast
export GDK_THEME=HighContrast
export QT_STYLE_OVERRIDE=HighContrast
export XDG_CURRENT_DESKTOP=GNOME
# Reiniciar configuración GTK
unset GTK2_RC_FILES
unset GTK_RC_FILES
exec /usr/bin/codeblocks "$@"
}
function zrepo() {
if [ -z "$1" ]; then
echo "Usage: zrepo <repo>"
return 1
fi
local REPO="$1"
local SERVER="git@zvps"
local PATH_ON_SERVER="/var/git/$REPO.git"
ssh $SERVER "
if [ -d $PATH_ON_SERVER ]; then
echo 'Error: repo already exists'
exit 1
fi
mkdir -p $PATH_ON_SERVER &&
git init --bare $PATH_ON_SERVER &&
chown -R git:git $PATH_ON_SERVER &&
chmod -R 755 $PATH_ON_SERVER
" || return 1
echo "Repo created on $SERVER:$PATH_ON_SERVER"
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
git remote add origin "$SERVER:$PATH_ON_SERVER"
echo "Remote 'origin' added to your local repo."
else
echo "Run 'git clone $SERVER:$PATH_ON_SERVER' to clone the repo."
fi
}
function _has {
return $( whence $1 >/dev/null )
}
# 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
echo $completion_file
if [ -f "$completion_file" ]; then
source "$completion_file"
fi
done
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
alias dev='~/Dev/marianozunino/dev/dev'
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 \"{}\"' \;"