diff options
| author | Peter Geissler <peter@haxx.in> | 2026-08-28 14:41:42 +0200 |
|---|---|---|
| committer | Peter Geissler <peter@haxx.in> | 2026-08-28 14:41:42 +0200 |
| commit | 2fbd36c1cef6ea6c9fcf9c36afb5209089288257 (patch) | |
| tree | c95a97a4277306eddc7daeb67dddac6daa1e943d /docs | |
| parent | windows build: re-stamp version.h when the version changes (diff) | |
| download | slosh-2fbd36c1cef6ea6c9fcf9c36afb5209089288257.tar.gz slosh-2fbd36c1cef6ea6c9fcf9c36afb5209089288257.tar.xz slosh-2fbd36c1cef6ea6c9fcf9c36afb5209089288257.zip | |
ctrl_d_exits: Ctrl-D at a prompt, where the tty cannot do it
Windows has no VEOF. The console driver does not know the character, so
^D arrives at cmd.exe and PowerShell as an ordinary keystroke and they
ignore it -- it even echoes, which is how you find out: the line reads
`echo hello^D`. The one key that closes a pane on every other platform
does nothing at all, and closing a pane becomes a word you have to type.
That you can type `exit` instead is the tell: the intent was never
ambiguous, only unspoken. So slosh speaks it. What goes to the pane is
the word, not a signal and not a close from outside -- the shell runs
its own cleanup, returns its own status, and keep_dead decides what is
left behind, all three of which reaching past it would skip. It is also
what the user would have typed, so there is nothing new to explain.
The knob is what makes it honest, because a wrong guess costs a pane.
It fires only with the shell itself in the foreground (a program that
is running may want the EOF for itself -- `cat` reading to end is the
whole job), only on the primary screen (in an editor or a pager ^D is
half a page down, and the alternate screen is the pane stating that
rather than us matching process names), and only on an empty line
(POSIX sends EOF there; what it does not do is discard what you typed).
The line is an estimate. The shell's editor is on the far side of a
pty, so pane_send_key counts what it forwarded since the last Enter.
Editing it does not model -- a recalled history entry, ^U, completion
-- leaves the count too high, which forgets to exit. That is the
direction to be wrong in; the other one throws away a half-typed
command.
Default true on Windows, false on POSIX, where the line discipline
already does this and does it properly: ^D there is also EOF for `cat`
and every REPL, none of which is ours to intercept. A knob rather than
an #ifdef so the guards are the same code everywhere and can be tested
where the test suite runs -- test_ctrl_d.py turns it on and drives all
four decisions, plus the case that does exit.
Telling trapped from forwarded needs a program that reports what it
received: on POSIX a forwarded ^D also ends an idle shell, and looking
for the word `exit` cannot separate them either, because bash prints
`exit` itself on EOF.
Verified on the Windows box as well, where it is the default: ^D at an
idle cmd.exe prompt takes the pane (and with it the session, having no
panes left), `more` in the foreground keeps its own EOF, and a
half-typed line survives with the line still on screen.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/config.md | 2 | ||||
| -rw-r--r-- | docs/slosh.5 | 10 | ||||
| -rw-r--r-- | docs/windows.md | 11 |
3 files changed, 22 insertions, 1 deletions
diff --git a/docs/config.md b/docs/config.md index c954de2..86cfc79 100644 --- a/docs/config.md +++ b/docs/config.md @@ -113,7 +113,7 @@ theme { frame_focus "#00ff88" } // ...but that one colour is mine |---|---| | geometry | `gap` `gap_aspect` `padding` `compact` `rounded` `title_align` `title_inset` `min_pane` `min_split` | | chrome | `status_bar` `status_line` `status_pad` `hints` `version_banner` `pane_buttons` `bell_indicator` and the marks (`zoom_mark` `zoom_on_mark` `close_mark` `min_mark` `newtab_mark` `bell_mark`) | -| behaviour | `focus_follows_mouse` `scroll_lines` `scrollback` `scrollback_bytes` `toast_ms` `splash_ms` `hover_delay_ms` `double_click_ms` `word_separators` `anim_ms` `modal_scrim` `dim_unfocused` `float_shadow` `keep_dead` `in_band_shaders` `shell` `editor` `shader_dir` | +| behaviour | `focus_follows_mouse` `ctrl_d_exits` `scroll_lines` `scrollback` `scrollback_bytes` `toast_ms` `splash_ms` `hover_delay_ms` `double_click_ms` `word_separators` `anim_ms` `modal_scrim` `dim_unfocused` `float_shadow` `keep_dead` `in_band_shaders` `shell` `editor` `shader_dir` | | projects | `project_roots` `project_layout` (see [workspaces](workspaces.md)) | | colour | `theme { }` | | effects | `shaders { }`, `states { }` (see [shaders](shaders.md) and [chrome](chrome.md)) | diff --git a/docs/slosh.5 b/docs/slosh.5 index ec862b5..59465b2 100644 --- a/docs/slosh.5 +++ b/docs/slosh.5 @@ -147,6 +147,16 @@ The glyphs themselves, each one string. Hovering focuses \(em never at the cost of what you were doing: not during a prefix, a drag, or a modal. .TP +.BI ctrl_d_exits\ bool +Ctrl-D at an idle shell prompt sends +.B exit +to that shell, standing in for the EOF the tty would deliver on POSIX. +On by default on Windows, which has no VEOF and so ignores the key +entirely; off elsewhere, where the line discipline already does it. +Only with the shell itself in the foreground, on the primary screen, +and on an empty line \(em in an editor or a pager Ctrl-D is half a page +down, and a line with something on it is not an EOF. +.TP .BI scroll_lines\ n Rows per wheel notch. .TP diff --git a/docs/windows.md b/docs/windows.md index 861a3cd..4d01a0d 100644 --- a/docs/windows.md +++ b/docs/windows.md @@ -126,6 +126,17 @@ the session on the one program that misbehaves. Whoever finishes last frees. `tcgetpgrp()` would have named. Windows offers the image name rather than a full argv without reading another process's memory, so pane titles are correspondingly shorter. +- **No `VEOF`, so Ctrl-D is made to mean something.** The console driver has + no EOF character: `^D` reaches cmd.exe and PowerShell as an ordinary + keystroke and they ignore it, so the key that closes a pane on every other + platform does nothing at all. `ctrl_d_exits` (on by default here, off + elsewhere) sends the shell the word `exit` instead — which is what you would + have typed, and what makes the pane end through the shell's own cleanup and + exit status rather than by being closed from outside. It stays out of the + way unless all three hold: the shell itself in the foreground, the primary + screen, and an empty line. A program that is running may want the EOF + itself; in an editor or a pager `^D` is half a page down; and a line with + something on it is not an EOF anywhere. - **No editor is guaranteed.** `C-a e` prefers whichever console editor is actually installed — `nvim`, `vim`, `vi`, `nano`, `micro`, `hx`, `edit` — because the obvious fallback is the wrong shape: `notepad` is a GUI program, |
