From c47d31012b4ca3e26df7801eeda8629cd163b421 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Sat, 29 Aug 2026 17:40:52 -0400 Subject: [PATCH] feat(config): add scratch terminal binding and window rule, remove pj function --- dot_config/fish/functions/_pj_bind_down.fish | 11 ++- dot_config/fish/functions/pj.fish | 88 -------------------- dot_config/hypr/bindings.lua | 7 ++ dot_config/hypr/hyprland.lua | 5 ++ 4 files changed, 19 insertions(+), 92 deletions(-) delete mode 100644 dot_config/fish/functions/pj.fish diff --git a/dot_config/fish/functions/_pj_bind_down.fish b/dot_config/fish/functions/_pj_bind_down.fish index 87b8669..6d18641 100644 --- a/dot_config/fish/functions/_pj_bind_down.fish +++ b/dot_config/fish/functions/_pj_bind_down.fish @@ -1,18 +1,21 @@ -function _pj_bind_down --description "down arrow: pj on an idle empty prompt, else the preset down-or-search" +function _pj_bind_down --description "down arrow: pj on an idle empty prompt, else fish's down-or-search" # Mirror of atuin's up binding (atuin owns up, this owns down). Everything # that legitimately needs the arrow keys keeps them: # - non-empty buffer → multiline cursor movement / forward history search # - paging mode → tab-completion pager navigation (tab on an empty # line opens the pager with an empty buffer) # - search mode → history-search navigation + # down-or-search is fish's own input function, called as a command exactly + # the way atuin's _atuin_bind_up calls up-or-search. set -l buf (commandline | string collect) if test -n "$buf"; or commandline --paging-mode; or commandline --search-mode - commandline -f down-or-search + down-or-search return end - # PJ_QUIET keeps pj silent when the tree has no package.json, so down is a - # no-op outside JS projects instead of printing an error on every press. + # pj is ~/.local/bin/pj (shared with the zsh ctrl-p binding). PJ_QUIET + # keeps it silent when the tree has no task source at all, so down is a + # no-op outside projects instead of printing an error on every press. PJ_QUIET=1 pj commandline -f repaint end diff --git a/dot_config/fish/functions/pj.fish b/dot_config/fish/functions/pj.fish deleted file mode 100644 index dd37c21..0000000 --- a/dot_config/fish/functions/pj.fish +++ /dev/null @@ -1,88 +0,0 @@ -function pj --description "fzf package.json script runner with auto-detected package manager" - # ── Locate nearest package.json (walk up) ────────────────────────── - set -l dir (pwd) - set -l pkg "" - while true - if test -f "$dir/package.json" - set pkg "$dir/package.json" - break - end - test "$dir" = / && break - set dir (path dirname $dir) - end - - if test -z "$pkg" - # PJ_QUIET: called from the down-arrow binding, where a missing - # package.json is the normal case and must not print anything. - test -n "$PJ_QUIET"; or echo "pj: no package.json found in this tree" >&2 - return 1 - end - set -l root (path dirname $pkg) - - # ── Detect package manager ───────────────────────────────────────── - # Priority: packageManager field (corepack) → lockfiles (walking up - # past $root to catch monorepo-root locks) → npm fallback - set -l pm (jq -r '.packageManager // empty' $pkg | string split '@')[1] - - if test -z "$pm" - set -l d $root - while test -z "$pm" - if test -f "$d/bun.lockb" -o -f "$d/bun.lock" - set pm bun - else if test -f "$d/pnpm-lock.yaml" - set pm pnpm - else if test -f "$d/yarn.lock" - set pm yarn - else if test -f "$d/package-lock.json" - set pm npm - end - test "$d" = / && break - set d (path dirname $d) - end - test -z "$pm" && set pm npm - end - - # ── Pick a script ────────────────────────────────────────────────── - set -l script (jq -r '.scripts // {} | keys[]' $pkg | fzf \ - --prompt="$pm run ❯ " \ - --header="$root" \ - --height=40% --layout=reverse --border \ - --preview="jq -r --arg s {} '.scripts[\$s]' $pkg" \ - --preview-window=up:2:wrap) - - test -z "$script" && return 0 - - # ── Run (npm needs `--` to forward extra args) ──────────────────── - set -l extra $argv - if test "$pm" = npm -a (count $extra) -gt 0 - set extra -- $extra - end - - # Wrap long-running server scripts in openlogs (live log tail for agents). - # Matches dev/start/serve and namespaced variants like dev:web, start:api. - set -l wrapper - if string match -qr '^(dev|start|serve|watch)(:.*)?$' -- $script - # Resolve the binary: PATH → mise resolution → mise installs glob - set -l ol (command -s openlogs) - if test -z "$ol"; and command -sq mise - set ol (mise which openlogs 2>/dev/null) - end - if test -z "$ol" - set ol ~/.local/share/mise/installs/node/*/bin/openlogs - set ol $ol[1] - end - - if test -n "$ol" -a -x "$ol" - set wrapper $ol - else - echo "pj: openlogs not found, running unwrapped" >&2 - end - end - if test -n "$wrapper" - echo "→ $wrapper $pm run $script $argv" >&2 - $wrapper $pm run $script $extra - else - echo "→ $pm run $script $argv" >&2 - $pm run $script $extra - end -end diff --git a/dot_config/hypr/bindings.lua b/dot_config/hypr/bindings.lua index 6cfcb46..87ebc90 100644 --- a/dot_config/hypr/bindings.lua +++ b/dot_config/hypr/bindings.lua @@ -65,6 +65,13 @@ o.bind("SUPER + CTRL + K", "Previous workspace", hl.dsp.focus({ workspace = "e-1 hl.unbind("SUPER + CTRL + S") -- was: share menu o.bind("SUPER + CTRL + S", "Toggle scratchpad", hl.dsp.workspace.toggle_special("scratchpad")) +-- Mod+A is the scratch terminal: the same scratchpad toggle, except an empty +-- scratchpad starts kitty with ~/.config/kitty/herdr.conf (class kitty-herdr, +-- pinned to the scratchpad by the window rule in hypr/hyprland.lua) instead of +-- sliding an empty workspace into view. SUPER + A is free in Omarchy. +-- Needs ~/.local/bin/omarchy-toggle-scratch. +o.bind("SUPER + A", "Toggle scratch terminal", "omarchy-toggle-scratch") + -- Workspaces 1 to 5 on the home row of the left half: ALT to focus, -- ALT + SHIFT to send the window there. No Omarchy default uses ALT with a -- letter, so nothing is unbound. diff --git a/dot_config/hypr/hyprland.lua b/dot_config/hypr/hyprland.lua index 91e2a83..286a8f4 100644 --- a/dot_config/hypr/hyprland.lua +++ b/dot_config/hypr/hyprland.lua @@ -42,3 +42,8 @@ o.window([[^brave-youtube\.com__-Default$]], { workspace = "1" }) o.window([[^brave-www\.tldraw\.com__-Default$]], { workspace = "3" }) o.window([[^com\.fastmail\.Fastmail$]], { workspace = "4" }) o.window([[^Beeper$]], { workspace = "4" }) + +-- The SUPER + A scratch terminal (kitty --config ~/.config/kitty/herdr.conf). +-- Pinning it here means it lands on the scratchpad no matter who starts it; +-- "silent" leaves the reveal to omarchy-toggle-scratch. +o.window([[^kitty-herdr$]], { workspace = "special:scratchpad silent" })