From 0692ae332bb865f17cc20220fbe13b3d67ab65e7 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Mon, 5 Oct 2026 09:15:20 -0400 Subject: [PATCH] feat(config): integrate iris and streamline keybindings --- dot_config/bash/keybinds.bash | 23 +---- dot_config/fish/conf.d/atuin.env.fish | 2 - dot_config/fish/config.fish | 70 ++++------------ dot_config/fish/functions/_bind_run.fish | 6 ++ dot_config/fish/functions/_gho_bind.fish | 2 + dot_config/fish/functions/_iris_busy.fish | 15 ++++ dot_config/fish/functions/_pj_bind.fish | 7 +- dot_config/fish/functions/_pj_bind_down.fish | 21 ----- dot_config/fish/functions/_tv_inline.fish | 2 + .../functions/fish_user_key_bindings.fish | 24 +++--- dot_config/iris/config.toml | 73 ++++++++++++++++ dot_config/zsh/functions/czs.zsh | 35 ++++++++ dot_config/zsh/functions/y.zsh | 2 + dot_config/zsh/keybinds.zsh | 84 +++++++++++++++---- dot_zshrc | 39 +++++++-- 15 files changed, 268 insertions(+), 137 deletions(-) delete mode 100644 dot_config/fish/conf.d/atuin.env.fish create mode 100644 dot_config/fish/functions/_bind_run.fish create mode 100644 dot_config/fish/functions/_iris_busy.fish delete mode 100644 dot_config/fish/functions/_pj_bind_down.fish create mode 100644 dot_config/iris/config.toml create mode 100644 dot_config/zsh/functions/czs.zsh create mode 100644 dot_config/zsh/functions/y.zsh diff --git a/dot_config/bash/keybinds.bash b/dot_config/bash/keybinds.bash index 669a6ff..f6458e0 100644 --- a/dot_config/bash/keybinds.bash +++ b/dot_config/bash/keybinds.bash @@ -1,7 +1,7 @@ # ~/.config/bash/keybinds.bash — readline ports of the television keys in # fish_user_key_bindings.fish / zsh keybinds.zsh: # ctrl-o → gho (ghq-repos cable, cd) ctrl-e → tv git-files (nvim) -# ctrl-p → pj (pj cable) down → pj on an empty prompt +# ctrl-p → pj (pj cable) # ctrl-t → tv smart autocomplete (tv init bash ships no ctrl-t) # Keys owned by kitty.conf never reach the shell: ctrl-h/j/k/l (pass_keys.py). # @@ -19,12 +19,12 @@ _kb_git_files() { } bind -x '"\C-e": _kb_git_files' -# ctrl-p, and down on an empty prompt. pj reports through $PJ_STATE: `open` -# = cancelled, `ran` = a task printed output, empty = no task sources. +# ctrl-p. pj reports through $PJ_STATE: `open` = cancelled, `ran` = a task +# printed output, empty = no task sources. _kb_pj() { local state state=$(mktemp) || return - PJ_STATE=$state pj "$@" /dev/tty - - # Run atuin ai inline, swapping stdout and stderr - set -l output (atuin ai inline --hook 3>&1 1>&2 2>&3 | string collect) - - if string match --quiet '__atuin_ai_print__:*' "$output" - echo (string replace "__atuin_ai_print__:" "" -- "$output" | string collect) - commandline -f repaint - else if test "$output" = "__atuin_ai_cancel__" - commandline -f repaint - else if string match --quiet '__atuin_ai_execute__:*' "$output" - # Execute the command immediately - set -l cmd (string replace "__atuin_ai_execute__:" "" -- "$output" | string collect) - commandline -r "$cmd" - commandline -f repaint - commandline -f execute - else if string match --quiet '__atuin_ai_insert__:*' "$output" - # Insert the command for editing - set -l cmd (string replace "__atuin_ai_insert__:" "" -- "$output" | string collect) - commandline -r "$cmd" - commandline -f repaint - else if test -n "$output" - # Default: insert for editing - commandline -r "$output" - commandline -f repaint - else - commandline -f repaint - end - else if not contains -- "$fish_key_bindings" fish_vi_key_bindings fish_hybrid_key_bindings - # Not at empty prompt, just insert the question mark - commandline -i "?" - end -end - -# Set up keybindings -bind "?" _atuin_ai_question_mark - eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv fish)" + +# iris (~/.config/iris/config.toml). The init's first half `exec`s iris from an +# interactive fish, which then starts this config again inside its pty; the +# second half installs the cwd/command hooks there. Skipped where iris is not +# installed. `IRIS_RESCUE=1 fish` opens a plain fish (e.g. if iris breaks). +if command -q iris + # fish's `query-term` feature asks the terminal for its capabilities and, + # in kitty, turns on the kitty keyboard protocol (keys as CSI-u escapes). + # iris reads raw key bytes and cannot parse those, so its menu never + # opened in kitty. Feature flags are read at startup, so export the opt-out + # before `exec iris`: the fish iris starts inherits it. + if status is-interactive; and not set -q IRIS_PID; and not set -q IRIS_RESCUE + set -gx fish_features no-query-term + end + iris init fish | source +end diff --git a/dot_config/fish/functions/_bind_run.fish b/dot_config/fish/functions/_bind_run.fish new file mode 100644 index 0000000..c26174c --- /dev/null +++ b/dot_config/fish/functions/_bind_run.fish @@ -0,0 +1,6 @@ +function _bind_run --description 'run a command from a key binding (iris-aware), then repaint' + _iris_busy start + $argv + _iris_busy stop + commandline -f repaint +end diff --git a/dot_config/fish/functions/_gho_bind.fish b/dot_config/fish/functions/_gho_bind.fish index 3518ae6..ce0b8da 100644 --- a/dot_config/fish/functions/_gho_bind.fish +++ b/dot_config/fish/functions/_gho_bind.fish @@ -1,6 +1,8 @@ function _gho_bind --description 'ctrl-o: gho (tv --inline), then redraw the prompt in the right place' set -l before $PWD + _iris_busy start gho + _iris_busy stop if test "$PWD" = "$before" # Cancelled (or the nvim action ran): tv --inline left the cursor on # the line below the prompt; step back so repaint redraws in place. diff --git a/dot_config/fish/functions/_iris_busy.fish b/dot_config/fish/functions/_iris_busy.fish new file mode 100644 index 0000000..20b6ba5 --- /dev/null +++ b/dot_config/fish/functions/_iris_busy.fish @@ -0,0 +1,15 @@ +function _iris_busy --description 'tell iris a key binding is running a program (start|stop)' + # iris (~/.config/iris) learns a command is running from fish_preexec / + # fish_postexec, which never fire for programs a key binding starts. Without + # this, iris keeps treating the screen as an idle prompt while tv, yazi or + # lazygit run: it swallows up/down/tab and can draw its menu over them. + # Same messages as iris's own hooks; a no-op outside iris. + set -q IRIS_FD; or return 0 + switch "$argv[1]" + case start + printf 'IRIS_CMD_START\x00' >&$IRIS_FD 2>/dev/null + case stop + printf 'IRIS_CMD_STOP:0\x00' >&$IRIS_FD 2>/dev/null + end + return 0 +end diff --git a/dot_config/fish/functions/_pj_bind.fish b/dot_config/fish/functions/_pj_bind.fish index bc265d7..9e65325 100644 --- a/dot_config/fish/functions/_pj_bind.fish +++ b/dot_config/fish/functions/_pj_bind.fish @@ -1,14 +1,13 @@ -function _pj_bind --description 'ctrl-p / down: pj (tv --inline), then redraw the prompt in the right place' +function _pj_bind --description 'ctrl-p: pj (tv --inline), then redraw the prompt in the right place' # pj reports through $PJ_STATE: `open` = the picker was cancelled and # left the cursor on the line below the prompt; empty = no task sources, # nothing drawn — but fish's repaint after an external command still # lands one line low, so both step back up. `ran` = a task printed # output: new line, prompt below it. set -lx PJ_STATE (mktemp) - if contains -- --quiet $argv - set -lx PJ_QUIET 1 - end + _iris_busy start pj + _iris_busy stop set -l state (cat $PJ_STATE) switch "$state" case open '' diff --git a/dot_config/fish/functions/_pj_bind_down.fish b/dot_config/fish/functions/_pj_bind_down.fish deleted file mode 100644 index 948aa39..0000000 --- a/dot_config/fish/functions/_pj_bind_down.fish +++ /dev/null @@ -1,21 +0,0 @@ -function _pj_bind_down --description "down arrow: pj tv cable 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 - down-or-search - return - end - - # _pj_bind runs ~/.local/bin/pj (also ctrl-p), which opens the `pj` tv - # cable. --quiet (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 per press. - _pj_bind --quiet -end diff --git a/dot_config/fish/functions/_tv_inline.fish b/dot_config/fish/functions/_tv_inline.fish index af2b544..2ce7ff9 100644 --- a/dot_config/fish/functions/_tv_inline.fish +++ b/dot_config/fish/functions/_tv_inline.fish @@ -3,8 +3,10 @@ function _tv_inline --description 'tv --inline below the prompt, cursor back on # its own first row when it exits; step back up so the following # `commandline -f repaint` redraws the prompt in place instead of one line # lower. /dev/tty keeps the move out of callers that capture stdout (gho). + _iris_busy start tv $argv --inline set -l st $status + _iris_busy stop printf '\033[A' >/dev/tty return $st end diff --git a/dot_config/fish/functions/fish_user_key_bindings.fish b/dot_config/fish/functions/fish_user_key_bindings.fish index 9206e5d..71e99c3 100644 --- a/dot_config/fish/functions/fish_user_key_bindings.fish +++ b/dot_config/fish/functions/fish_user_key_bindings.fish @@ -10,33 +10,29 @@ function fish_user_key_bindings # Keys owned by kitty.conf never reach fish and are NOT bound here: # ctrl-g → lazygit overlay, ctrl-y → yazi vsplit, # ctrl-h/j/k/l → vim-aware split nav (pass_keys.py). - # ctrl-e: tv git-files (bat preview, enter opens nvim). ctrl-o, ctrl-p - # and down also open tv cables — same keys in zsh and bash. tv runs + # ctrl-e: tv git-files (bat preview, enter opens nvim). ctrl-o and + # ctrl-p also open tv cables — same keys in zsh and bash. tv runs # --inline below the prompt; _tv_inline/_gho_bind/_pj_bind put the # prompt back in place (or below any output) afterwards. ctrl-a: # omp-session resumes or starts omp for the repo (same in zsh); when it # opens the omp-sessions cable and it is cancelled, it steps back up. + # Every binding that runs a program tells iris via _iris_busy + # (_bind_run, _tv_inline, _gho_bind, _pj_bind), or iris would keep + # its prompt key handling while tv/yazi/lazygit own the screen. bind -M $mode ctrl-e '_tv_inline git-files; commandline -f repaint' - bind -M $mode ctrl-b purple repaint - bind -M $mode ctrl-y clip-last + bind -M $mode ctrl-b '_bind_run purple' + bind -M $mode ctrl-y '_bind_run clip-last' bind -M $mode ctrl-o _gho_bind bind -M $mode ctrl-p _pj_bind - bind -M $mode ctrl-a 'omp-session; commandline -f repaint' - bind -M $mode ctrl-w 'atuin ai inline; commandline -f repaint' + bind -M $mode ctrl-a '_bind_run omp-session' # ctrl-z at the prompt: fg the only background job, or pick one from # the jobs tv cable when there are several (_jobs_bind). bind -M $mode ctrl-z _jobs_bind - # Arrow keys: atuin owns up (bound from config.fish, survives the - # fish_vi_key_bindings reset above because that only erases presets), - # down opens the pj tv cable — but only on an idle, empty prompt; see - # _pj_bind_down. - bind -M $mode down _pj_bind_down - # ctrl-f: yazi (cd's to yazi's exit dir on quit). - bind -M $mode ctrl-f 'yy; commandline -f repaint' - bind -M $mode ctrl-g 'lazygit; commandline -f repaint' + bind -M $mode ctrl-f '_bind_run yy' + bind -M $mode ctrl-g '_bind_run lazygit' # ctrl-c routes through the clear wrapper (kitty scrollback + prompt # pinned to the bottom) AND wipes any text typed on the command line. diff --git a/dot_config/iris/config.toml b/dot_config/iris/config.toml new file mode 100644 index 0000000..0eb047c --- /dev/null +++ b/dot_config/iris/config.toml @@ -0,0 +1,73 @@ +# iris (https://github.com/versenilvis/iris): inline completion menu that wraps +# the shell in its own pty. Started from fish and zsh (`iris init ` in +# config.fish / .zshrc). `iris config show` prints the merged result; missing +# keys fall back to iris's defaults. + +[core] +version = 1 # config schema version +shell = "" # auto-detect; `iris init ` exports IRIS_ACTIVE_SHELL, which wins anyway +shell-login = false # run shell as a login shell (also: iris --shell-login) +# Every shell opens in spec mode: Fig-style completions (subcommands, flags, +# paths) pop up as you type. ctrl+r still flips to history for that session; +# "last" would carry a stray ctrl+r into every later shell. +mode = "spec" # "last", "spec", or "history" +debug = false # verbose logging to iris.log (also: iris -d); logs every keystroke +expand-alias = true # expand aliases before matching +auto-execute = false # run suggestion immediately instead of inserting it +atuin-history = 0 # shell history only: atuin is not used under iris +atuin-db-path = "" # path to atuin's history.db, empty = use default +cobra-probe-enabled = true # fall back to probing cobra binaries for completions +# Menu closed: up/down browse iris's own history (Fig-style). No shell binds +# up/down; handing them to the shell ran the old down -> pj picker inside +# iris's pty, and the two fought over the screen. +navigate-closed = "history" + +[ui] +style = "modern" # "modern" or "classic" +ghost-text = 1 # 0 = off, 1 = menu + ghost text, 2 = ghost text only +hidden-files = false # include dotfiles in suggestions +max-suggestions = 100 # max suggestions ranked before display +max-height = 6 # max visible rows in the menu +max-width = 0 # menu width: columns (80) or a share ("80%"), 0 = default +nerd-fonts = true # use nerd-font icons (Victor Mono Nerd Font) + +# ctrl+r, tab, shift+tab, up and down never reach the shell while iris runs; +# tv's own ctrl-r history binding (`tv init`) is shadowed by toggle-mode. +[keybindings] +toggle-mode = "ctrl+r" # switch spec/history mode +toggle-menu = "shift+tab" # show or hide the suggestion menu +select = "tab" # accept the selected suggestion +navigate-up = "up" # select up (menu open) +navigate-down = "down" # select down (menu open) +navigate-right = "right" # accept ghost text + +[git] +filter-active-branch = true # exclude current branch from suggestions +deduplicate-branches = true # merge same-name local/remote branches + +# Installed from the AUR (iris-autocomplete): pacman/paru owns updates, so iris +# neither checks nor installs on its own. +[updater] +check-on-startup = false +channel = "stable" +check-interval = "24h" +auto-update = 0 + +[zoxide] +extend-cd = true # complete `cd` from zoxide's database (conf.d/40-tools.fish runs `zoxide init fish`) + +[ai] +enabled = false +provider = "groq" # "groq" or "ollama" +debounce_ms = 400 # ms to wait before querying the AI + +[ai.providers.groq] +endpoint = "https://api.groq.com/openai/v1/chat/completions" +api_key_env = "GROQ_API_KEY" # read from the environment, never stored here +model = "llama-3.3-70b-versatile" +timeout_ms = 3000 + +[ai.providers.ollama] +endpoint = "http://localhost:11434/v1/chat/completions" +model = "qwen2.5-coder" +timeout_ms = 5000 diff --git a/dot_config/zsh/functions/czs.zsh b/dot_config/zsh/functions/czs.zsh new file mode 100644 index 0000000..a094476 --- /dev/null +++ b/dot_config/zsh/functions/czs.zsh @@ -0,0 +1,35 @@ +# czs: chezmoi re-add drifted files, then commit + push the source repo. +# Port of functions/czs.fish. Optional targets scope the status view and the +# re-add (e.g. `czs ~/.config/fish`); no args = all managed files. +czs() { + local drift src ahead + drift=$(chezmoi status "$@") || return + + if [[ -n $drift ]]; then + print -r -- $drift + # re-add takes the local (destination) contents as truth for modified + # files; templates are never overwritten, non-file entries are ignored. + chezmoi re-add "$@" || return + else + echo "chs: in sync — nothing to re-add" + fi + + # Commit + sync the source repo (~/.local/share/chezmoi). + src=$(chezmoi source-path) + if [[ -n $(git -C $src status --porcelain) ]]; then + git -C $src add -A && + git -C $src commit --quiet -m 'chs: re-add drifted files' || return + echo "chs: committed $(git -C $src rev-parse --short HEAD)" + fi + + # Push anything unpushed: this commit and leftovers from a failed push. + # --autostash tolerates post-commit hooks re-dirtying the tree mid-sync. + ahead=$(git -C $src rev-list --count @{upstream}..HEAD 2>/dev/null || echo 0) + if (( ahead > 0 )); then + git -C $src pull --rebase --autostash --quiet && + git -C $src push --quiet && + echo "chs: pushed $ahead commit(s) to $(git -C $src remote get-url origin)" + else + echo "chs: remote up to date" + fi +} diff --git a/dot_config/zsh/functions/y.zsh b/dot_config/zsh/functions/y.zsh new file mode 100644 index 0000000..67ec71e --- /dev/null +++ b/dot_config/zsh/functions/y.zsh @@ -0,0 +1,2 @@ +# y: same as yy (fish has both names) — yazi, then cd to its exit directory. +y() { yy "$@"; } diff --git a/dot_config/zsh/keybinds.zsh b/dot_config/zsh/keybinds.zsh index da679d1..1a39e0e 100644 --- a/dot_config/zsh/keybinds.zsh +++ b/dot_config/zsh/keybinds.zsh @@ -5,6 +5,20 @@ bindkey -e # pin emacs keymap ($EDITOR containing "vi" would pick viins) unsetopt flow_control # free ^Q/^S in zle so the ctrl-q exit bind fires +# iris (~/.config/iris) learns a command is running from the preexec/precmd +# hooks, which never fire for programs a widget starts. Without this, iris +# keeps treating the screen as an idle prompt while tv, yazi or lazygit run: +# it swallows up/down/tab and can draw its menu over them. Same messages as +# iris's own hooks; a no-op outside iris. fish: functions/_iris_busy.fish. +_iris_busy() { + [[ -n $IRIS_FD ]] || return 0 + case $1 in + start) print -u $IRIS_FD -N -r -- IRIS_CMD_START 2>/dev/null ;; + stop) print -u $IRIS_FD -N -r -- IRIS_CMD_STOP:0 2>/dev/null ;; + esac + return 0 +} + # Generic runner: widget `run-` executes (function or binary) with # the tty as stdin, then repaints — fish's `commandline -f repaint`. # cwd changes from gho/yy persist: widgets run in the shell process. @@ -13,7 +27,9 @@ unsetopt flow_control # free ^Q/^S in zle so the ctrl-q exit bind fires _zle-run() { local cmd=${WIDGET#run-} zle -I + _iris_busy start $cmd /dev/tty zle reset-prompt } @@ -42,7 +60,9 @@ zle -N tv-git-files _zle-tv-git-files _zle-gho() { local before=$PWD zle -I + _iris_busy start gho /dev/tty zle reset-prompt @@ -50,23 +70,15 @@ _zle-gho() { } zle -N gho-inline _zle-gho -# ctrl-p, and down on an idle empty prompt (fish's _pj_bind_down; otherwise -# normal history / multiline movement). pj reports through $PJ_STATE: `open` -# = cancelled, `ran` = a task printed output, empty = no task sources -# (PJ_QUIET keeps down silent outside projects). +# ctrl-p: pj. pj reports through $PJ_STATE: `open` = cancelled, `ran` = a task +# printed output, empty = no task sources. _zle-pj() { - if [[ $WIDGET == pj-down && -n $BUFFER ]]; then - zle down-line-or-history - return - fi local state state=$(mktemp) || return zle -I - if [[ $WIDGET == pj-down ]]; then - PJ_STATE=$state PJ_QUIET=1 pj /dev/tty; zle reset-prompt ;; ran) ;; @@ -75,7 +87,48 @@ _zle-pj() { rm -f $state } zle -N pj-inline _zle-pj -zle -N pj-down _zle-pj + +# ctrl-z at the prompt (fish's _jobs_bind): fg the only job, or pick one from +# the `jobs` tv cable, which reads the job table from $TV_JOBS (records: +# "% ", id, process group). While a job holds the +# terminal ctrl-z is still the tty's suspend, so the key toggles. +# fg runs as a real command line (push-input keeps typed text for the next +# prompt); __jobs_bind_fg erases that echoed line and fg's "[1] continued" +# notice. The leading space keeps it out of history (HIST_IGNORE_SPACE). +__jobs_bind_fg() { + printf '\033[A\033[2K\r' >/dev/tty + fg %$1 2>/dev/null +} +_zle-jobs() { + local -a ids recs + local id pick file + ids=(${(On)${(k)jobstates}}) + (( $#ids )) || return 0 + for id in $ids; do + recs+=("$(printf '%%%s %-9s %s\t%s\t%s' $id ${jobstates[$id]%%:*} \ + "${jobtexts[$id]}" $id ${${jobstates[$id]#*:*:}%%=*})") + done + if (( $#ids == 1 )); then + pick=$ids[1] + else + file=$(mktemp) || return + print -rl -- $recs >$file + zle -I + _iris_busy start + pick=$(TV_JOBS=$file tv jobs --inline /dev/tty + rm -f $file + if [[ -z $pick ]]; then + zle reset-prompt + return + fi + fi + zle push-input + BUFFER=" __jobs_bind_fg $pick" + zle accept-line +} +zle -N jobs-fg _zle-jobs bindkey '^E' tv-git-files bindkey '^B' run-purple @@ -88,8 +141,7 @@ bindkey '^A' run-omp-session # ctrl-f: yazi; yy cd's to yazi's exit dir on quit. bindkey '^F' run-yy bindkey '^G' run-lazygit -bindkey '^[[B' pj-down -bindkey '^[OB' pj-down +bindkey '^Z' jobs-fg # ctrl-q mirrors ctrl-d's preset (`exit`) — quit the shell. _zle-exit() { exit } diff --git a/dot_zshrc b/dot_zshrc index a090a3a..897fbf3 100644 --- a/dot_zshrc +++ b/dot_zshrc @@ -4,7 +4,9 @@ HISTFILE="$HOME/.zsh_history" HISTSIZE=10000 SAVEHIST=10000 -setopt SHARE_HISTORY HIST_IGNORE_DUPS +# HIST_IGNORE_SPACE: a leading space keeps a line out of history, as in fish +# (the ctrl-z binding's hidden ` __jobs_bind_fg` relies on it). +setopt SHARE_HISTORY HIST_IGNORE_DUPS HIST_IGNORE_SPACE # Completion autoload -Uz compinit && compinit @@ -20,6 +22,10 @@ export GOPATH="$HOME/.local/share/go" export GOBIN="$GOPATH/bin" case ":$PATH:" in *":$GOBIN:"*) ;; *) PATH="$GOBIN:$PATH" ;; esac +# mise: tool shims and env (GOROOT above comes from it), as fish's +# conf.d/40-tools.fish does for every fish. +command -v mise >/dev/null 2>&1 && eval "$(mise activate zsh)" + # Repo roots (ghq) — same as fish's conf.d/10-env.fish; the ghq-repos tv # cable (ctrl-o) lists this root. export GHQ_ROOT="$HOME/Code" @@ -65,10 +71,33 @@ command -v suv >/dev/null 2>&1 && eval "$(suv init zsh)" # Prompt — starship, consistent with fish command -v starship >/dev/null 2>&1 && eval "$(starship init zsh)" -# television: ctrl-t smart autocomplete (its ctrl-r is taken over by atuin -# below, as in fish) +# Material You terminal colors generated from the wallpaper (quickshell), +# replayed like fish's conf.d/40-tools.fish. +_qs_seq="$HOME/.local/state/quickshell/user/generated/terminal/sequences.txt" +[ -f "$_qs_seq" ] && cat "$_qs_seq" +unset _qs_seq + +# zoxide: `z` / `zi`, plus the cd wrapper's fallback (functions/cd.zsh). +command -v zoxide >/dev/null 2>&1 && eval "$(zoxide init zsh)" + +# television: ctrl-t smart autocomplete (its ctrl-r is shadowed by iris's +# mode toggle, as in fish) command -v tv >/dev/null 2>&1 && eval "$(tv init zsh)" +# iris (~/.config/iris/config.toml): inline completion menu, same as fish. +# The init's first half `exec`s iris from an interactive zsh on a tty; iris +# starts a second zsh in its pty, which runs this file again, and there the +# second half installs the line/cwd/command hooks. `IRIS_RESCUE=1 zsh` skips +# it. Placed before syntax highlighting, which must stay last. +if command -v iris >/dev/null 2>&1; then + eval "$(iris init zsh)" + # Inside iris: PROMPT_SP pads the line with spaces + CR before each prompt + # (the inverse `%` partial-line marker). iris reads that echo as a typed + # space, so every prompt opened with a stale query and a stray first + # suggestion (`4channels`) got inserted on the next key. + [[ -n $IRIS_PID ]] && unsetopt PROMPT_SP +fi + # Fish-style syntax highlighting (zsh-users/zsh-syntax-highlighting). # MUST stay last in .zshrc: it wraps every zle widget defined above # (keybinds, compinit, suv/starship hooks). @@ -80,10 +109,6 @@ for _zsh_hl in \ done unset _zsh_hl -. "$HOME/.atuin/bin/env" - -eval "$(atuin init zsh)" - # >>> termium >>> case ":$PATH:" in *:'/home/prad/.local/bin':*) ;; *) export PATH='/home/prad/.local/bin':"$PATH" ;; esac # <<< termium <<<