diff --git a/docs/shell/fish.mdx b/docs/shell/fish.mdx index 898f109..a3141c5 100644 --- a/docs/shell/fish.mdx +++ b/docs/shell/fish.mdx @@ -188,6 +188,7 @@ The header comment says the file should stay empty, but it holds the following: | ctrl-p | `_pj_bind`: `pj`, the task runner on the `pj` cable ([Scripts](/shell/scripts#pj)), then repaint | | ctrl-a | `omp-session`, then repaint: resume or start omp for the current repo by branch and session age, opening the `omp-sessions` cable only when nothing qualifies ([Scripts](/shell/scripts#omp-session)) | | ctrl-w | `atuin ai inline`: natural-language command overlay | +| ctrl-z | `_jobs_bind`: with one background job, `fg` it; with several, pick one from the `jobs` cable ([television](/tools/television#jobs)) and `fg` that; with none, nothing. While a job holds the terminal, ctrl-z is still the tty's suspend, so the key toggles suspend and resume | | ctrl-g | `lazygit` | | down | `_pj_bind_down`: opens the `pj` cable on an idle, empty prompt, otherwise fish's `down-or-search` | | ctrl-c | Clears the command line, runs `clear` (screen and kitty scrollback), repaints | @@ -211,6 +212,9 @@ The pickers run `tv --inline`, which opens on the line below the prompt and leav | `_tv_inline ARGS` | `tv ARGS --inline` | `\033[A` (cursor up), returns tv's status | | `_gho_bind` | `gho` | `\033[A` if the cwd did not change; `\n` after a cd, so the prompt lands below onefetch | | `_pj_bind [--quiet]` | `pj` with `PJ_STATE` set to a temp file | `\033[A` for `open` (cancelled) or empty (no task sources); `\n` for `ran` (the task printed output) | +| `_jobs_bind` | `fg` of the only job, or `jobs` with `TV_JOBS` set to a temp file holding the job table | `\033[A` (via `_tv_inline`) when the picker is cancelled | + +`_jobs_bind` runs `fg` by replacing the command line with ` __jobs_bind_fg ` (leading space: kept out of history) and executing it, not from inside the binding. A binding runs while fish's reader still owns the terminal with extended keys on, so a job started with `&` that had never held the terminal got ctrl-z and ctrl-c as escape sequences instead of signals. `__jobs_bind_fg` erases the echoed prompt line (`\033[A\033[2K` on `/dev/tty`) and runs `fg` with its "Send job … to foreground" message sent to `/dev/null`, so resuming leaves nothing on screen. Text already typed is put back at the next prompt by a one-shot `fish_prompt` handler. `omp-session` (ctrl-a) does its own `\033[A` when its `omp-sessions` picker is cancelled, so the binding only repaints. @@ -268,6 +272,7 @@ Every file in `functions/` is autoloaded by name. Several also exist as POSIX sc | `_nvm_version_deactivate` | nvm.fish internal: removes a version's `bin` from `PATH` | | `_gho_bind` | ctrl-o handler: `gho`, then cursor fix and repaint (see [Key bindings](#key-bindings)) | | `_pj_bind` | ctrl-p handler: `pj` with `PJ_STATE`, then cursor fix and repaint. `--quiet` sets `PJ_QUIET=1` | +| `_jobs_bind` | ctrl-z handler: `fg` the only job or pick one from the `jobs` cable (see [Key bindings](#key-bindings)) | | `_pj_bind_down` | Down-arrow handler: `_pj_bind --quiet` on an empty idle prompt, else `down-or-search` | | `_tv_inline` | `tv $argv --inline`, then moves the cursor up one line on `/dev/tty` | | `ai` | `gum choose` among `claude`, `opencode`, `codex`, `hermes`, `fractal`. `claude` runs with `--dangerously-skip-permissions` | diff --git a/docs/tools/television.mdx b/docs/tools/television.mdx index 75b6f16..96e4e47 100644 --- a/docs/tools/television.mdx +++ b/docs/tools/television.mdx @@ -62,7 +62,7 @@ Global keys added on top of the defaults: ## Sorting -Every custom cable except `agents` (a fixed list, see [agents](#agents)) and `omp-sessions` (sorted by [`omp-session`](/shell/scripts#omp-session) itself) pipes its source through [`mtime-sort`](/shell/scripts#mtime-sort), which orders lines newest-first by the mtime of the path in the line's last tab-separated field (`--repo` stats `/.git/index` first). tv then ranks match quality and frecency on top of that order. All custom cables set `shell = "bash"`, because `$SHELL` is fish. +Every custom cable except `agents` (a fixed list, see [agents](#agents)), `omp-sessions` (sorted by [`omp-session`](/shell/scripts#omp-session) itself), and `jobs` (fish's job order) pipes its source through [`mtime-sort`](/shell/scripts#mtime-sort), which orders lines newest-first by the mtime of the path in the line's last tab-separated field (`--repo` stats `/.git/index` first). tv then ranks match quality and frecency on top of that order. All custom cables set `shell = "bash"`, because `$SHELL` is fish. ## Custom cables @@ -75,8 +75,9 @@ Every custom cable except `agents` (a fixed list, see [agents](#agents)) and `om | [`obsidian`](#obsidian) | `cable/obsidian.toml` | `tv obsidian` | | [`agents`](#agents) | `cable/agents.toml` | `tv agents` | | [`omp-sessions`](#omp-sessions) | `cable/omp-sessions.toml` | `tv omp-sessions`, ctrl-a (`omp-session`) when it has nothing to resume | +| [`jobs`](#jobs) | `cable/jobs.toml` | ctrl-z in fish (`_jobs_bind`) with two or more background jobs | -The keys are bound in fish (`fish_user_key_bindings.fish`), zsh (`keybinds.zsh`), and bash (`keybinds.bash`); bash has no ctrl-a binding. See [fish](/shell/fish#key-bindings) and [bash and zsh](/shell/bash-zsh). +The keys are bound in fish (`fish_user_key_bindings.fish`), zsh (`keybinds.zsh`), and bash (`keybinds.bash`); bash has no ctrl-a binding, and ctrl-z is fish only. See [fish](/shell/fish#key-bindings) and [bash and zsh](/shell/bash-zsh). ### ghq-repos @@ -87,15 +88,18 @@ Entries are `namepath`: tv shows and matches the name and prints the path. | Repos | `ghq list` under `ghq root`, plus the chezmoi source (`~/.local/share/chezmoi`) listed as `github.com/prdlk/dotfiles` | `mtime-sort --repo` | | Vaults | Every directory under `~/Documents/Obsidian` (depth 3) that contains `.obsidian`, named relative to that directory | `mtime-sort` | -**Preview.** `onefetch --no-art` for git directories, otherwise `eza --tree --level 2` (falling back to `ls -la`). +**Preview.** Two commands; ctrl-f cycles. The default is the commit graph for git directories: `git log --graph --all`, newest 300 commits, as short hash, relative date, subject and refs. The second is `onefetch --no-art`. Non-git directories show `eza --tree --level 2` (falling back to `ls -la`) in both. + +[serie](https://github.com/lusingander/serie) cannot draw inside the preview pane: it is a fullscreen TUI that paints its graph with kitty images and has no print mode. ctrl-g opens it instead. | Key | Action | | --- | --- | | enter | Print the path. The `gho` function cds into it, clears, and runs `onefetch` in git repos | | ctrl-e | `edit`: `cd && nvim .` on `/dev/tty` | | ctrl-b | `browse`: `cd && gop` in fork mode, so tv stays open ([gop](/shell/scripts#gop)) | +| ctrl-g | `history`: `serie` on `/dev/tty` in fork mode for git directories; q returns to the picker | -**Needs:** `ghq`, `fd`, `onefetch`, `mtime-sort`. +**Needs:** `ghq`, `fd`, `git`, `serie`, `onefetch`, `mtime-sort`. ### git-files @@ -154,3 +158,16 @@ Source `omp-session --list`: the [omp](/ai/omp) sessions of the current git repo The preview runs `omp-session --preview`: title, last-write time and cwd, then the text of every user and assistant message. enter runs `resume` in execute mode, `omp-session --resume `, which `exec`s `omp --resume `. **Needs:** `omp-session`, `omp`. + +### jobs + +The current fish shell's background jobs, stopped or running, newest first. tv runs as a child process and cannot read the shell's job table, so `_jobs_bind` ([fish](/shell/fish#key-bindings)) writes it to a temp file named by `$TV_JOBS` and the source just `cat`s that file; opened any other way the list is empty. Entries are `% `; enter prints the id and the binding runs `fg %`. + +The preview finds the job's processes by process group (procps `ps -g` matches sessions, so it filters `ps -e -o pgid,pid`) and shows the first process's cwd and start time, then `ps --forest` with PID, STAT (`T` = stopped), elapsed time, CPU, RSS, and arguments. The preview script avoids `{`/`}` because tv would parse them as templates and leave `{split:…}` unexpanded. + +| Key | Action | +| --- | --- | +| enter | Print the job id; `_jobs_bind` runs `fg` on it | +| ctrl-d | `kill` then `reload_source`: SIGTERM to the job's process group, then SIGCONT so a stopped job receives it. Once the group is gone (polled up to 1 s) the row is removed from `$TV_JOBS`, so the reloaded list drops it; a job that ignores SIGTERM stays listed. Fish reports the termination at the next prompt | + +**Needs:** `ps`, fish.