functions.zsh 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. #!/bin/zsh
  2. # =============================================================================
  3. # NAVIGATION UTILITIES
  4. # =============================================================================
  5. eval "$(zoxide init zsh)"
  6. # Zoxide aliases with better names
  7. zcd() { z "$@" }
  8. zadd() { z "$@" }
  9. zremove() { zoxide remove "$@" }
  10. # Legacy aliases for backward compatibility
  11. alias zi=zcd
  12. alias za=zadd
  13. alias zrm=zremove
  14. # Open files with xdg-open (non-blocking)
  15. function open {
  16. if [[ $# -eq 0 ]]; then
  17. echo "Usage: open <file1> [file2] ..."
  18. echo "Opens files using the system default application"
  19. return 1
  20. fi
  21. for i in "$@"; do
  22. if [[ ! -e "$i" ]]; then
  23. echo "Warning: '$i' does not exist" >&2
  24. continue
  25. fi
  26. setsid nohup xdg-open "$i" > /dev/null 2> /dev/null &
  27. done
  28. }
  29. # Find and open files with fzf
  30. function fopen() {
  31. if ! command -v fd >/dev/null 2>&1; then
  32. echo "Error: fd is not installed" >&2
  33. return 1
  34. fi
  35. if ! command -v fzf >/dev/null 2>&1; then
  36. echo "Error: fzf is not installed" >&2
  37. return 1
  38. fi
  39. local selected
  40. selected=$(fd "$@" | fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}')
  41. [[ -n "$selected" ]] && setsid nohup xdg-open "$selected" >/dev/null 2>&1 &
  42. }
  43. # =============================================================================
  44. # DEVELOPMENT TOOLS
  45. # =============================================================================
  46. # Smart package manager detection and execution
  47. function _package_manager {
  48. local pkg_manager=""
  49. # Detect package manager based on lock files
  50. if [[ -f bun.lockb ]]; then
  51. pkg_manager="bun"
  52. elif [[ -f pnpm-lock.yaml ]]; then
  53. pkg_manager="pnpm"
  54. elif [[ -f yarn.lock ]]; then
  55. pkg_manager="yarn"
  56. elif [[ -f package-lock.json ]]; then
  57. pkg_manager="npm"
  58. else
  59. pkg_manager="pnpm" # Default fallback
  60. fi
  61. # Auto-detect npm scripts if command exists in package.json
  62. if [[ -f package.json ]] && [[ $1 != "run" ]] && [[ $1 != "install" ]] && [[ $1 != "add" ]] && [[ $1 != "remove" ]] && [[ $1 != "i" ]] && [[ $1 != "rm" ]]; then
  63. if command -v jq >/dev/null 2>&1 && jq -e ".scripts[\"$1\"] != null" package.json >/dev/null 2>&1; then
  64. set -- "run" "$@"
  65. fi
  66. fi
  67. # Execute with corepack if available, otherwise direct command
  68. if command -v corepack >/dev/null 2>&1; then
  69. corepack ${pkg_manager} "$@"
  70. else
  71. command ${pkg_manager} "$@"
  72. fi
  73. }
  74. # Quick development commit with auto-push
  75. function dc() {
  76. # Show help if requested
  77. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  78. echo "Usage: dc [commit_message]"
  79. echo "Quickly commit all changes and push to remote"
  80. echo "If no message provided, uses timestamp-based message"
  81. return 0
  82. fi
  83. if ! git rev-parse --is-inside-work-tree &>/dev/null; then
  84. echo "Error: Not in a git repository" >&2
  85. return 1
  86. fi
  87. if [[ -z $(git status --porcelain) ]]; then
  88. echo "No changes to commit"
  89. return 0
  90. fi
  91. git add .
  92. local commit_msg
  93. if [[ -n "$1" ]]; then
  94. commit_msg="$1"
  95. else
  96. local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
  97. commit_msg="dev: automated commit - ${timestamp}"
  98. fi
  99. # Commit with message and push
  100. if git commit -m "$commit_msg" --no-gpg-sign; then
  101. if git push &>/dev/null; then
  102. echo "Committed and pushed successfully"
  103. else
  104. echo "Warning: Commit successful but push failed" >&2
  105. return 1
  106. fi
  107. else
  108. echo "Commit failed" >&2
  109. return 1
  110. fi
  111. }
  112. # Clean up merged git branches
  113. function git-clean() {
  114. # Show help if requested
  115. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  116. echo "Usage: git-clean"
  117. echo "Safely delete merged branches (both local and optionally remote)"
  118. echo "Protects main, master, and develop branches"
  119. return 0
  120. fi
  121. if ! git rev-parse --is-inside-work-tree &>/dev/null; then
  122. echo "Error: Not in a git repository" >&2
  123. return 1
  124. fi
  125. local current_branch=$(git rev-parse --abbrev-ref HEAD)
  126. local branches_to_delete=$(git branch --merged | grep -v "^\*" | grep -v "master" | grep -v "main" | grep -v "develop")
  127. if [[ -z "$branches_to_delete" ]]; then
  128. echo "No merged branches to clean up"
  129. return 0
  130. fi
  131. echo "The following merged branches will be deleted:"
  132. echo "$branches_to_delete"
  133. echo -n "Continue? [y/N] "
  134. read confirm
  135. if [[ "$confirm" =~ ^[Yy]$ ]]; then
  136. echo "$branches_to_delete" | xargs git branch -d
  137. echo "Branches deleted locally"
  138. echo -n "Delete remote branches too? [y/N] "
  139. read confirm_remote
  140. if [[ "$confirm_remote" =~ ^[Yy]$ ]]; then
  141. echo "$branches_to_delete" | xargs -I{} git push origin --delete {}
  142. echo "Remote branches deleted"
  143. fi
  144. else
  145. echo "Operation cancelled"
  146. fi
  147. }
  148. # Quick access to Neovim config
  149. function vimrc {
  150. if [[ -z "$XDG_CONFIG_HOME" ]]; then
  151. echo "Error: XDG_CONFIG_HOME not set" >&2
  152. return 1
  153. fi
  154. local original_dir=$(pwd)
  155. cd "$XDG_CONFIG_HOME/nvim" || {
  156. echo "Error: Cannot access $XDG_CONFIG_HOME/nvim" >&2
  157. return 1
  158. }
  159. nvim
  160. cd "$original_dir"
  161. }
  162. function nixrc {
  163. if [[ -z "$XDG_CONFIG_HOME" ]]; then
  164. echo "Error: XDG_CONFIG_HOME not set" >&2
  165. return 1
  166. fi
  167. local original_dir=$(pwd)
  168. cd "$XDG_CONFIG_HOME/nixos" || {
  169. echo "Error: Cannot access $XDG_CONFIG_HOME/nixos" >&2
  170. return 1
  171. }
  172. nvim
  173. cd "$original_dir"
  174. }
  175. # Quick access to Zsh config
  176. function zshrc {
  177. if [[ -z "$XDG_CONFIG_HOME" ]]; then
  178. echo "Error: XDG_CONFIG_HOME not set" >&2
  179. return 1
  180. fi
  181. local original_dir=$(pwd)
  182. cd "$XDG_CONFIG_HOME/zsh" || {
  183. echo "Error: Cannot access $XDG_CONFIG_HOME/zsh" >&2
  184. return 1
  185. }
  186. nvim
  187. cd "$original_dir"
  188. }
  189. # Expose local port through SSH tunnel
  190. function expose() {
  191. # Show help if requested
  192. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  193. echo "Usage: expose <port>"
  194. echo "Create SSH tunnel to expose local port through remote server"
  195. echo "Example: expose 3000 # Exposes localhost:3000"
  196. return 0
  197. fi
  198. if [[ -z "$1" ]]; then
  199. echo "Error: Port number required" >&2
  200. echo "Usage: expose <port>" >&2
  201. return 1
  202. fi
  203. # Validate port number
  204. if ! [[ "$1" =~ ^[0-9]+$ ]] || [[ "$1" -lt 1 ]] || [[ "$1" -gt 65535 ]]; then
  205. echo "Error: Invalid port number. Must be between 1-65535" >&2
  206. return 1
  207. fi
  208. # Check if port is already in use
  209. if lsof -i ":$1" >/dev/null 2>&1; then
  210. echo "Warning: Port $1 is already in use" >&2
  211. echo "Current processes using port $1:"
  212. lsof -i ":$1"
  213. echo -n "Continue anyway? [y/N] "
  214. read confirm
  215. if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
  216. echo "Operation cancelled"
  217. return 1
  218. fi
  219. fi
  220. echo "Creating SSH tunnel for port $1..."
  221. ssh marianozunino@srv.us -R 1:localhost:"$1"
  222. }
  223. # Find process using a specific port
  224. function ppid {
  225. # Show help if requested
  226. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  227. echo "Usage: ppid <port>"
  228. echo "Find processes using the specified port"
  229. echo "Alias: pport"
  230. return 0
  231. fi
  232. if [[ -z "$1" ]]; then
  233. echo "Error: Port number required" >&2
  234. echo "Usage: ppid <port>" >&2
  235. return 1
  236. fi
  237. # Validate port number
  238. if ! [[ "$1" =~ ^[0-9]+$ ]] || [[ "$1" -lt 1 ]] || [[ "$1" -gt 65535 ]]; then
  239. echo "Error: Invalid port number. Must be between 1-65535" >&2
  240. return 1
  241. fi
  242. lsof -i ":$1"
  243. }
  244. # Alias for ppid function
  245. alias pport="ppid"
  246. # =============================================================================
  247. # KUBERNETES AND DEVOPS
  248. # =============================================================================
  249. # # Kubernetes port forwarding with kubefwd
  250. # function kf {
  251. # if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  252. # echo "Usage: kf <cluster> [service-name]"
  253. # echo "Forward Kubernetes services using kubefwd"
  254. # echo "Example: kf prod my-service"
  255. # return 0
  256. # fi
  257. #
  258. # if [[ -z "$1" ]]; then
  259. # echo "Error: Cluster name required" >&2
  260. # echo "Usage: kf <cluster> [service-name]" >&2
  261. # return 1
  262. # fi
  263. #
  264. # local namespace="oc-app"
  265. # local cluster="$1"
  266. # local svc_filter=""
  267. #
  268. # if [[ -n "$2" ]]; then
  269. # svc_filter="-l app.kubernetes.io/instance=$2"
  270. # fi
  271. #
  272. # if ! command -v kubefwd >/dev/null 2>&1; then
  273. # echo "Error: kubefwd is not installed" >&2
  274. # return 1
  275. # fi
  276. #
  277. # echo "Starting kubefwd for cluster: $cluster"
  278. # kubefwd svc -n "${namespace}" -x "${cluster}" ${svc_filter} --nonsudo
  279. # }
  280. #
  281. # Forward multiple services from a given namespace
  282. function kf {
  283. # Show help
  284. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  285. echo "Usage: kf <cluster> [service-name[:port]] [service-name[:port]] ..."
  286. echo "Example: kf oc-dev-internal-eks-cluster oc-activate-web"
  287. echo "Example: kf oc-dev-internal-eks-cluster oc-activate-web:8080"
  288. echo "Example: kf oc-dev-internal-eks-cluster oc-activate-web:8080 oc-member-dossier:8081"
  289. return 0
  290. fi
  291. local cluster="$1"
  292. shift
  293. if [[ -z "$cluster" ]]; then
  294. echo "Error: Missing cluster" >&2
  295. echo "Usage: kf <cluster> [service-name[:port]] [service-name[:port]] ..." >&2
  296. return 1
  297. fi
  298. # Show available services if none specified
  299. if [[ $# -eq 0 ]]; then
  300. echo "🔌 Available services in cluster: $cluster"
  301. kubectl --context "$cluster" -n oc-app get svc -o name | sed 's/service\// - /'
  302. return 0
  303. fi
  304. echo "🔌 Forwarding services (cluster: $cluster)"
  305. # Clean up existing port-forwards
  306. local existing_pids
  307. existing_pids=$(pgrep -f "kubectl.*port-forward" || true)
  308. if [[ -n "$existing_pids" ]]; then
  309. echo "$existing_pids" | xargs kill 2>/dev/null || true
  310. existing_pids=$(pgrep -f "kubectl.*port-forward" || true)
  311. if [[ -n "$existing_pids" ]]; then
  312. echo "$existing_pids" | xargs kill -9 2>/dev/null || true
  313. sleep 0.5
  314. fi
  315. fi
  316. local pids=()
  317. # Process each service
  318. for service_spec in "$@"; do
  319. # Parse service:port format
  320. local service_name local_port
  321. if [[ "$service_spec" == *":"* ]]; then
  322. service_name="${service_spec%:*}"
  323. local_port="${service_spec##*:}"
  324. else
  325. service_name="$service_spec"
  326. local_port=""
  327. fi
  328. # Find service in oc-app namespace
  329. local svc
  330. svc=$(kubectl --context "$cluster" -n oc-app get svc -o name | grep "^service/$service_name$" || true)
  331. if [[ -z "$svc" ]]; then
  332. echo "⚠️ Service '$service_name' not found in namespace 'oc-app' - skipping"
  333. echo " Available services:"
  334. kubectl --context "$cluster" -n oc-app get svc -o name | sed 's/service\// - /' | head -5
  335. continue
  336. fi
  337. local name="${svc#service/}"
  338. local service_port
  339. service_port=$(kubectl --context "$cluster" -n oc-app get "svc/$name" -o jsonpath='{.spec.ports[0].port}')
  340. local forward_port="${local_port:-$service_port}"
  341. # Check if port is in use
  342. local port_info
  343. port_info=$(lsof -i :$forward_port 2>/dev/null)
  344. if [[ -n "$port_info" ]]; then
  345. local pid=$(echo "$port_info" | tail -n +2 | awk '{print $2}' | head -1)
  346. local process=$(echo "$port_info" | tail -n +2 | awk '{print $1}' | head -1)
  347. echo "⚠️ Port $forward_port in use by $process (PID: $pid) - skipping $name"
  348. continue
  349. fi
  350. # Start port-forward
  351. if [[ -n "$local_port" ]]; then
  352. echo "→ Forwarding $name (service port $service_port) to local port $forward_port"
  353. else
  354. echo "→ Forwarding $name on port $forward_port"
  355. fi
  356. kubectl --context "$cluster" -n oc-app port-forward "svc/$name" "$forward_port:$service_port" >/dev/null 2>&1 &
  357. local pid=$!
  358. # Verify port-forward started successfully
  359. sleep 0.5
  360. if ! kill -0 $pid 2>/dev/null; then
  361. echo "❌ Failed to start port-forward for $name on port $forward_port"
  362. continue
  363. fi
  364. pids+=($pid)
  365. done
  366. if [[ ${#pids[@]} -eq 0 ]]; then
  367. echo "❌ No port-forwards were started successfully"
  368. return 1
  369. fi
  370. echo "→ All forwards running (PIDs: ${pids[*]})"
  371. echo "→ Press Ctrl+C to stop"
  372. # Handle Ctrl+C cleanup
  373. trap 'echo; echo "🛑 Stopping port-forwards..."; for pid in ${pids[*]}; do kill $pid 2>/dev/null; done; sleep 1; for pid in ${pids[*]}; do kill -9 $pid 2>/dev/null; done; wait ${pids[*]} 2>/dev/null; return 0' INT
  374. wait
  375. }
  376. # =============================================================================
  377. # SYSTEM AND UTILITY FUNCTIONS
  378. # =============================================================================
  379. # Lazy-load handler for heavy tools
  380. function _lazy_load() {
  381. local cmd="$1"
  382. local loader="$2"
  383. eval "${cmd}() {
  384. unfunction $cmd
  385. eval \"\$($loader)\"
  386. $cmd \"\$@\"
  387. }"
  388. }
  389. # Example: lazy load kubectl completion
  390. _lazy_load kubectl "kubectl completion zsh"
  391. # Configure Wacom tablet for current session
  392. function wacom {
  393. # Show help if requested
  394. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  395. echo "Usage: wacom"
  396. echo "Configure Wacom tablet for current display session"
  397. echo "Supports both Wayland and X11 sessions"
  398. return 0
  399. fi
  400. if [[ "$XDG_SESSION_TYPE" = "wayland" ]]; then
  401. if ! command -v otd >/dev/null 2>&1; then
  402. echo "Error: opentabletdriver (otd) not found" >&2
  403. return 1
  404. fi
  405. systemctl --user enable opentabletdriver --now
  406. local config_file="$HOME/Sync/System/Configs/wacom/wacom.json"
  407. if [[ -f "$config_file" ]]; then
  408. otd loadsettings "$config_file"
  409. echo "Wacom configured for Wayland"
  410. else
  411. echo "Warning: Config file not found at $config_file" >&2
  412. fi
  413. else
  414. if ! command -v xsetwacom >/dev/null 2>&1; then
  415. echo "Error: xsetwacom not found" >&2
  416. return 1
  417. fi
  418. xsetwacom --set "Wacom One by Wacom S Pen stylus" ResetArea
  419. xsetwacom --set "Wacom One by Wacom S Pen stylus" MapToOutput DisplayPort-0
  420. xsetwacom --set "Wacom One by Wacom S Pen stylus" Rotate half
  421. xsetwacom --set "Wacom One by Wacom S Pen eraser" ResetArea
  422. xsetwacom --set "Wacom One by Wacom S Pen eraser" MapToOutput DisplayPort-0
  423. echo "Wacom configured for X11"
  424. fi
  425. }
  426. # Enhanced cat with bat, context-aware display
  427. function cat {
  428. # Show help if requested
  429. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  430. echo "Usage: cat [file1] [file2] ..."
  431. echo "Enhanced cat using bat with syntax highlighting"
  432. echo "Automatically adjusts output for SSH sessions"
  433. return 0
  434. fi
  435. if ! command -v bat >/dev/null 2>&1; then
  436. echo "Warning: bat not found, falling back to system cat" >&2
  437. command cat "$@"
  438. return $?
  439. fi
  440. if [[ -n "$SSH_TTY" ]] || [[ -n "$SSH_CLIENT" ]] || [[ -n "$SSH_CONNECTION" ]]; then
  441. bat --plain --paging=never "$@"
  442. else
  443. bat "$@"
  444. fi
  445. }
  446. # Toggle display resolution and configuration
  447. function toggle_resolution() {
  448. # Show help if requested
  449. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  450. echo "Usage: toggle_resolution [-m|--mirror]"
  451. echo "Toggle between different display resolutions and modes"
  452. echo "Options:"
  453. echo " -m, --mirror Force mirror mode"
  454. return 0
  455. fi
  456. local mirror_mode=false
  457. # Parse flags
  458. while [[ $# -gt 0 ]]; do
  459. case $1 in
  460. -m|--mirror)
  461. mirror_mode=true
  462. shift
  463. ;;
  464. *)
  465. shift
  466. ;;
  467. esac
  468. done
  469. # Check if swaymsg is available
  470. if ! command -v swaymsg >/dev/null 2>&1; then
  471. echo "Error: swaymsg not found. This function requires Sway window manager" >&2
  472. return 1
  473. fi
  474. # Check if jq is available
  475. if ! command -v jq >/dev/null 2>&1; then
  476. echo "Error: jq not found. Required for JSON parsing" >&2
  477. return 1
  478. fi
  479. # Get current state of internal monitor
  480. local current_state
  481. current_state=$(swaymsg -t get_outputs | jq -r '.[] | select(.name == "eDP-1") | "\(.current_mode.width)x\(.current_mode.height):\(.scale)"')
  482. # Detect connected external monitors
  483. local external_monitor=""
  484. if swaymsg -t get_outputs | jq -r '.[].name' | grep -q "DP-2"; then
  485. external_monitor="DP-2"
  486. elif swaymsg -t get_outputs | jq -r '.[].name' | grep -q "HDMI-A-1"; then
  487. external_monitor="HDMI-A-1"
  488. fi
  489. if [[ "$mirror_mode" == true ]] || [[ -n "$external_monitor" ]]; then
  490. echo "Switching to mirror mode (1920x1080)..."
  491. # Configure internal monitor to 1920x1080
  492. swaymsg output eDP-1 resolution 1920x1080@120Hz scale 1.0 pos 0 0
  493. # Configure external monitor if connected
  494. if [[ -n "$external_monitor" ]]; then
  495. swaymsg output "$external_monitor" resolution 1920x1080@60Hz pos 0 0
  496. echo "Mirror mode enabled: eDP-1 + $external_monitor at 1920x1080"
  497. else
  498. echo "Internal monitor configured to 1920x1080 (no external monitor detected)"
  499. fi
  500. elif [[ "$current_state" == "2880x1920:2.0" ]]; then
  501. echo "Switching to 1920x1080 (16:9)..."
  502. swaymsg output eDP-1 resolution 1920x1080@120Hz scale 1.0
  503. # Disable mirroring if external monitor is present
  504. if [[ -n "$external_monitor" ]]; then
  505. swaymsg output "$external_monitor" pos 1920 0
  506. echo "Extended mode: $external_monitor positioned to the right"
  507. fi
  508. else
  509. echo "Switching to 2880x1920 (3:2) native..."
  510. swaymsg output eDP-1 resolution 2880x1920@120Hz scale 2.0
  511. # Disable mirroring if external monitor is present
  512. if [[ -n "$external_monitor" ]]; then
  513. swaymsg output "$external_monitor" pos 1440 0
  514. echo "Extended mode: $external_monitor positioned to the right"
  515. fi
  516. fi
  517. # Show final state
  518. echo "Current configuration:"
  519. 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))"'
  520. }
  521. # Launch Code::Blocks with high contrast theme
  522. function cb {
  523. # Show help if requested
  524. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  525. echo "Usage: cb [codeblocks-args]"
  526. echo "Launch Code::Blocks with high contrast theme"
  527. return 0
  528. fi
  529. if [[ ! -f /usr/bin/codeblocks ]]; then
  530. echo "Error: Code::Blocks not found at /usr/bin/codeblocks" >&2
  531. return 1
  532. fi
  533. # Store original values
  534. local original_gtk_theme="$GTK_THEME"
  535. local original_gdk_theme="$GDK_THEME"
  536. local original_qt_style="$QT_STYLE_OVERRIDE"
  537. local original_xdg_desktop="$XDG_CURRENT_DESKTOP"
  538. # Set high contrast theme temporarily
  539. GTK_THEME=HighContrast \
  540. GDK_THEME=HighContrast \
  541. QT_STYLE_OVERRIDE=HighContrast \
  542. XDG_CURRENT_DESKTOP=GNOME \
  543. GTK2_RC_FILES="" \
  544. GTK_RC_FILES="" \
  545. /usr/bin/codeblocks "$@"
  546. # Restore original values
  547. export GTK_THEME="$original_gtk_theme"
  548. export GDK_THEME="$original_gdk_theme"
  549. export QT_STYLE_OVERRIDE="$original_qt_style"
  550. export XDG_CURRENT_DESKTOP="$original_xdg_desktop"
  551. }
  552. # Create a new git repository on remote server
  553. function zrepo() {
  554. # Show help if requested
  555. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  556. echo "Usage: zrepo <repo-name>"
  557. echo "Create a new bare git repository on remote server"
  558. echo "Example: zrepo my-project"
  559. return 0
  560. fi
  561. if [[ -z "$1" ]]; then
  562. echo "Error: Repository name required" >&2
  563. echo "Usage: zrepo <repo-name>" >&2
  564. return 1
  565. fi
  566. # Validate repository name (basic check)
  567. if [[ ! "$1" =~ ^[a-zA-Z0-9_-]+$ ]]; then
  568. echo "Error: Repository name contains invalid characters" >&2
  569. echo "Use only letters, numbers, hyphens, and underscores" >&2
  570. return 1
  571. fi
  572. local REPO="$1"
  573. local SERVER="git@zvps"
  574. local PATH_ON_SERVER="/var/git/$REPO.git"
  575. echo "Creating repository '$REPO' on $SERVER..."
  576. ssh "$SERVER" "
  577. if [ -d $PATH_ON_SERVER ]; then
  578. echo 'Error: Repository '$REPO' already exists'
  579. exit 1
  580. fi
  581. mkdir -p $PATH_ON_SERVER &&
  582. git init --bare $PATH_ON_SERVER &&
  583. chown -R git:git $PATH_ON_SERVER &&
  584. chmod -R 755 $PATH_ON_SERVER
  585. " || {
  586. echo "Failed to create repository" >&2
  587. return 1
  588. }
  589. echo "Repository created on $SERVER:$PATH_ON_SERVER"
  590. if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
  591. git remote add origin "$SERVER:$PATH_ON_SERVER"
  592. echo "Remote 'origin' added to your local repository"
  593. else
  594. echo "To clone this repository, run:"
  595. echo " git clone $SERVER:$PATH_ON_SERVER"
  596. fi
  597. }
  598. # Check if a command exists
  599. function _has {
  600. if [[ $# -eq 0 ]]; then
  601. echo "Usage: _has <command>" >&2
  602. return 1
  603. fi
  604. whence "$1" >/dev/null 2>&1
  605. }
  606. # History-based directory navigation with fzf
  607. function cdr {
  608. # Show help if requested
  609. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  610. echo "Usage: cdr"
  611. echo "Navigate to recently visited directories using fzf"
  612. return 0
  613. fi
  614. if ! command -v fzf >/dev/null 2>&1; then
  615. echo "Error: fzf is not installed" >&2
  616. return 1
  617. fi
  618. local dir
  619. dir=$(dirs -pl | awk '!x[$0]++' | fzf --height 40% --reverse)
  620. [[ -n "$dir" ]] && cd "$dir"
  621. }
  622. # Fix swaymsg when running inside tmux
  623. if [[ -v TMUX ]]; then
  624. function swaymsg {
  625. export SWAYSOCK=$XDG_RUNTIME_DIR/sway-ipc.$UID.$(pgrep -x sway).sock
  626. command swaymsg "$@"
  627. }
  628. fi
  629. # =============================================================================
  630. # ALIASES
  631. # =============================================================================
  632. # Development aliases
  633. alias dev='~/Dev/marianozunino/dev/dev'
  634. alias p='_package_manager'
  635. alias fo='fopen'
  636. alias pport='ppid'
  637. # Node.js cleanup alias
  638. alias unChonk="echo 'Starting the great node_modules purge...' && find . -name 'node_modules' -type d -prune -exec sh -c 'echo \"Deleting {}\" && rm -rf \"{}\"' \;"
  639. # Font management
  640. alias fm='font-manager'
  641. alias fml='font-manager list'
  642. alias fms='font-manager status'
  643. alias fmc='font-manager clean'
  644. alias fma='font-manager all'
  645. # Advanced font management function
  646. function font-switch() {
  647. # Show help if requested
  648. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  649. echo "Usage: font-switch [font-name]"
  650. echo "Quickly switch between font sets"
  651. echo "Example: font-switch jetbrains-mono"
  652. return 0
  653. fi
  654. if [[ -z "$1" ]]; then
  655. echo "Available fonts:"
  656. font-manager list
  657. return 0
  658. fi
  659. local font_name="$1"
  660. # Check if font exists
  661. if ! font-manager list | grep -q "$font_name"; then
  662. echo "Error: Font '$font_name' not found" >&2
  663. echo "Available fonts:" >&2
  664. font-manager list >&2
  665. return 1
  666. fi
  667. echo "Switching to $font_name fonts..."
  668. font-manager clean
  669. font-manager extract "$font_name"
  670. # Reload terminal if in kitty
  671. if [[ "$TERM" == "xterm-kitty" ]] && command -v kitty >/dev/null 2>&1; then
  672. echo "Reloading kitty configuration..."
  673. kitty @ set-colors --all ~/.config/kitty/kitty.conf
  674. fi
  675. echo "Font switch complete!"
  676. }
  677. # Font preview function
  678. function font-preview() {
  679. # Show help if requested
  680. if [[ "$1" == "-h" || "$1" == "--help" ]]; then
  681. echo "Usage: font-preview [font-name]"
  682. echo "Preview fonts in terminal"
  683. echo "Example: font-preview jetbrains-mono"
  684. return 0
  685. fi
  686. if [[ -z "$1" ]]; then
  687. echo "Error: Font name required" >&2
  688. echo "Usage: font-preview [font-name]" >&2
  689. return 1
  690. fi
  691. local font_name="$1"
  692. local preview_text="The quick brown fox jumps over the lazy dog
  693. ABCDEFGHIJKLMNOPQRSTUVWXYZ
  694. abcdefghijklmnopqrstuvwxyz
  695. 0123456789
  696. !@#$%^&*()_+-=[]{}|;':\",./<>?"
  697. echo "Previewing font: $font_name"
  698. echo "----------------------------------------"
  699. echo "$preview_text" | font-manager extract "$font_name" && echo "$preview_text"
  700. }
  701. yay() {
  702. case "$1" in
  703. # System update
  704. update|"-Syu")
  705. echo "Updating NixOS system..."
  706. nh os switch ~/.config/nixos --update --ask
  707. ;;
  708. # Search packages
  709. search|"-Ss")
  710. [ -z "$2" ] && { echo "Usage: yay search <package>"; return 1; }
  711. echo "Searching for '$2'..."
  712. nix search nixpkgs "$2" 2>/dev/null || nix-env -qaP | grep -i "$2"
  713. ;;
  714. # Install package to user environment
  715. install|"-S")
  716. [ -z "$2" ] && { echo "Usage: yay install <package>"; return 1; }
  717. echo "Installing $2..."
  718. nix-env -iA nixpkgs.$2
  719. ;;
  720. # Remove package
  721. remove|"-R")
  722. [ -z "$2" ] && { echo "Usage: yay remove <package>"; return 1; }
  723. echo "Removing $2..."
  724. nix-env -e "$2"
  725. ;;
  726. # List installed packages
  727. list|"-Q")
  728. echo "Installed packages:"
  729. nix-env -q
  730. ;;
  731. # nix-shell quick run
  732. shell|"-p")
  733. shift
  734. if [ $# -eq 0 ]; then
  735. echo "Usage: yay shell <pkg1> [pkg2 ...]"
  736. return 1
  737. fi
  738. echo "Starting nix-shell with: $*"
  739. nix-shell -p "$@"
  740. ;;
  741. # Clean up
  742. clean|"-Sc")
  743. echo "Cleaning nix store..."
  744. nix-collect-garbage
  745. sudo nix-collect-garbage -d
  746. ;;
  747. # Help
  748. help|"-h")
  749. bat -Pp << 'EOF'
  750. yay - Simple NixOS package manager wrapper
  751. Commands:
  752. yay Rebuild system
  753. yay update Update system
  754. yay search <pkg> Search packages
  755. yay install <pkg> Install package (user)
  756. yay remove <pkg> Remove package
  757. yay list List installed packages
  758. yay shell <pkg...> Start nix-shell with packages
  759. yay clean Clean package cache
  760. yay help Show this help
  761. Note: For system packages, edit ~/.config/nixos/configuration.nix
  762. EOF
  763. ;;
  764. # Default: rebuild system
  765. "")
  766. echo "Rebuilding NixOS system..."
  767. nh os switch ~/.config/nixos --ask
  768. ;;
  769. # Try to install unknown commands
  770. *)
  771. if [[ ! "$1" =~ ^- ]]; then
  772. echo "Installing '$1'..."
  773. nix-env -iA nixpkgs.$1
  774. else
  775. echo "Unknown option: $1"
  776. echo "Run 'yay help' for available commands"
  777. return 1
  778. fi
  779. ;;
  780. esac
  781. }
  782. function nas() {
  783. rclone mount --vfs-cache-mode writes --dir-cache-time 5s --no-check-certificate --allow-other nas: /home/mzunino/nas
  784. }
  785. function ocr(){
  786. grim -g "$(slurp)" - \
  787. | magick - -colorspace gray -negate -brightness-contrast 15x40 -sharpen 0x2 -threshold 60% - \
  788. | tesseract stdin stdout -l eng+equ --psm 6 --oem 3 \
  789. -c preserve_interword_spaces=1 \
  790. -c tessedit_char_blacklist='‘’”“”´`–—•' \
  791. | sed -E '
  792. s/[“”]/"/g;
  793. s/[‘’]/"/g;
  794. s/’/'"'"'/g;
  795. s/[éèê]/8/g;
  796. s/í/i/g;
  797. s/—/-/g;
  798. s/“/"/g;
  799. ' \
  800. | wl-copy
  801. notify-send "✅ OCR copied to clipboard"
  802. }