mirror of
https://github.com/prdlk/dotfiles.git
synced 2026-11-02 19:32:43 +00:00
66 lines
5.2 KiB
Plaintext
66 lines
5.2 KiB
Plaintext
---
|
|||
|
|
title: iris
|
||
|
|
description: Inline completion menu that wraps fish and zsh in its own pty, with zoxide cd suggestions, and how the shells' bindings coexist with it.
|
||
|
|
---
|
||
|
|
|
||
|
|
[iris](https://github.com/versenilvis/iris) draws an IntelliSense-style completion menu inline in the terminal. It runs the shell inside its own pty and reads keys before the shell does. fish and zsh start it; bash does not.
|
||
|
|
|
||
|
|
| Source (repo) | Target | Notes |
|
||
|
|
| --- | --- | --- |
|
||
|
|
| `dot_config/iris/config.toml` | `~/.config/iris/config.toml` | symlink |
|
||
|
|
|
||
|
|
iris is the AUR package `iris-autocomplete`, not in `.chezmoidata/packages.yaml`. State and history live in `~/.local/share/iris` (not in the repo); `state.toml` remembers the last menu mode.
|
||
|
|
|
||
|
|
## Startup
|
||
|
|
|
||
|
|
`config.fish` ends with the iris block and `.zshrc` runs `iris init zsh` just before zsh-syntax-highlighting; both skip it where iris is not installed. The init script has two halves:
|
||
|
|
|
||
|
|
1. In an interactive shell without `IRIS_PID`, it exports `IRIS_ACTIVE_SHELL` and `exec`s `iris`, which starts a second copy of that shell inside its pty. That shell runs the whole config again.
|
||
|
|
2. Inside iris (`IRIS_PID` and `IRIS_FD` set), it installs hooks that report the cwd, the current line (zsh), and command start/stop to iris over `$IRIS_FD`. fish also loses its autosuggestions.
|
||
|
|
|
||
|
|
`IRIS_RESCUE=1 fish` or `IRIS_RESCUE=1 zsh` skips the `exec` and gives a plain shell, for when iris itself misbehaves.
|
||
|
|
|
||
|
|
Two shell settings change for iris:
|
||
|
|
|
||
|
|
| Shell | Setting | Why |
|
||
|
|
| --- | --- | --- |
|
||
|
|
| fish | `fish_features=no-query-term`, exported before `exec iris` | fish's terminal query turns on kitty's keyboard protocol in kitty, which encodes keys as `CSI u` escapes; iris cannot parse them, so the menu never opened in kitty (it did in tmux, which lacks the protocol) |
|
||
|
|
| zsh | `unsetopt PROMPT_SP` inside iris | zsh's partial-line marker pads each prompt with spaces and a carriage return; iris read the echo as a typed space, so prompts opened with a stale query and inserted a stray suggestion (`4channels`) on the next key |
|
||
|
|
|
||
|
|
### Key bindings that run programs
|
||
|
|
|
||
|
|
iris only knows a command is running from the shell's preexec/postexec hooks, and programs started by key bindings never fire those. While tv, yazi, or lazygit ran from a binding, iris kept treating the screen as an idle prompt: it swallowed arrows and <kbd>tab</kbd> (Down never reached a tv picker) and could draw its menu on top. Every such binding now wraps the program in `_iris_busy start` / `_iris_busy stop`, which send `IRIS_CMD_START` and `IRIS_CMD_STOP:0` on `$IRIS_FD`, the same messages the hooks send ([fish](/shell/fish#key-bindings), [zsh](/shell/bash-zsh#zsh-key-bindings)).
|
||
|
|
|
||
|
|
The old <kbd>down</kbd> → `pj` binding is gone from fish, zsh, and bash: it opened the `pj` picker inside iris's pty and the two fought over the screen. `pj` stays on <kbd>ctrl-p</kbd>.
|
||
|
|
|
||
|
|
## Config
|
||
|
|
|
||
|
|
Every key from iris's sample config is listed, so `iris config show` and the file agree. Changes from the defaults:
|
||
|
|
|
||
|
|
| Key | Value | Why |
|
||
|
|
| --- | --- | --- |
|
||
|
|
| `core.shell` | `""` | Auto-detect. `IRIS_ACTIVE_SHELL`, exported by `iris init <shell>`, decides which shell starts, so one config serves fish and zsh |
|
||
|
|
| `core.mode` | `"spec"` | Every shell opens with Fig-style completions (subcommands, flags, paths). The default `"last"` restores whatever mode the last shell ended in, so one stray <kbd>ctrl-r</kbd> left every new shell showing history |
|
||
|
|
| `core.atuin-history` | `0` | Shell history only; atuin is not used under iris |
|
||
|
|
| `updater.check-on-startup` | `false` | The package manager owns updates; `iris update` would replace a pacman-owned binary |
|
||
|
|
| `zoxide.extend-cd` | `true` | `cd <partial>` suggests directories from zoxide's database, not just the current directory |
|
||
|
|
|
||
|
|
AI suggestions stay off (`ai.enabled = false`). The Groq provider reads `GROQ_API_KEY` from the environment (`conf.d/secrets.fish`) through `api_key_env`; no key is stored in the file. `debug` stays off because iris then logs every keystroke.
|
||
|
|
|
||
|
|
## Keys
|
||
|
|
|
||
|
|
iris consumes these keys; the shell never sees them while iris runs:
|
||
|
|
|
||
|
|
| Key | iris action |
|
||
|
|
| --- | --- |
|
||
|
|
| <kbd>tab</kbd> | Accept the selected suggestion (replaces the shell's tab completion) |
|
||
|
|
| <kbd>shift-tab</kbd> | Hide or show the menu for this shell session |
|
||
|
|
| <kbd>ctrl-r</kbd> | Switch between spec and history mode for this shell session (shadows `tv init`'s history binding) |
|
||
|
|
| <kbd>up</kbd> / <kbd>down</kbd> | Move the selection in the menu; on a closed menu, browse iris's history (`navigate-closed = "history"`, the default) |
|
||
|
|
| <kbd>right</kbd> | Accept ghost text |
|
||
|
|
|
||
|
|
Every other key in [fish's](/shell/fish#key-bindings) and [zsh's](/shell/bash-zsh#zsh-key-bindings) bindings (<kbd>ctrl-a</kbd>, <kbd>ctrl-e</kbd>, <kbd>ctrl-o</kbd>, <kbd>ctrl-p</kbd>, <kbd>ctrl-z</kbd>, <kbd>ctrl-c</kbd>, …) and fish vi mode's <kbd>esc</kbd> still reach the shell.
|
||
|
|
|
||
|
|
## When the menu appears
|
||
|
|
|
||
|
|
Like Fig, the menu opens by itself about 20 ms after each keystroke on a non-empty line (`ghost-text = 1`: menu plus inline ghost text) and closes on an empty line or while a command runs. It only appears in shells that iris started, so shells opened before iris was set up (for example long-running herdr or tmux panes) show nothing until they are reopened.
|