diff options
| author | user <user@clank> | 2026-08-17 13:53:57 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-08-17 13:53:57 +0200 |
| commit | 2f9135d2810cfb38ccdd4f07e895c66430d066fe (patch) | |
| tree | 2816a6c2addf8c8181dddc51faa308188beccb10 /docs | |
| parent | sl0ppty: `set-name target="pane"`, so a script can overrule a program's title (diff) | |
| download | slosh-2f9135d2810cfb38ccdd4f07e895c66430d066fe.tar.gz slosh-2f9135d2810cfb38ccdd4f07e895c66430d066fe.tar.xz slosh-2f9135d2810cfb38ccdd4f07e895c66430d066fe.zip | |
sl0ppty: double-click a word to select it
`pane_select_word()` was written and never wired to anything: no declaration, no
caller, no way to reach it. This is the rest of it -- the gesture, the setting, and
the tests.
**The word is defined by what it stops at, not by what it is made of.** Anything
that is not blank and not a listed separator belongs to a word, so CJK, accented
letters and emoji need no table and come out whole; whitespace always separates,
listed or not, because a double-click that selected the line would be a different
gesture arrived at by surprise. Wide glyphs continue the run they are in rather than
each being their own word -- otherwise every CJK character is a word.
`word_separators` defaults to `"'`()[]{}<>;,|`, and what it leaves *out* is the
decision: `/ . - _ : = @ # % ? & + ~ $` stay inside words, so a path, a dotted
name, a snake_case identifier, a key=value pair, a URL and `src/app.c:1234` are
each one thing you double-clicked to copy whole. `:` is the difference between
copying an error location and copying half of one, which is why kitty keeps it too.
The gesture reuses what selecting already has: the press starts a selection at the
cell -- which anchors a drag out of the double-click -- then widens it to the word,
and the release path that already copies a drag copies this. So the word *is* the
copy, in the one place that rule lives, and the highlight is the copied span rather
than an approximation of it. Tracked per cell as well as per pane, so clicking two
different words quickly selects the second rather than everything between them.
A program that asked for the mouse still keeps its clicks, with shift as the escape
hatch, exactly as the drag has it.
**One thing this needed on the way: quoted values were dumped unescaped.** The
default separator set opens with a quote, and `cb_add(&b, "key \"%s\"\n", ...)`
wrote it raw -- so `--dump-config` produced a file that no longer parsed, breaking
the property the dump exists for. The escaping loop already existed inside
`cb_chord`, for the same reason and with the reasoning written down; it is now
`cb_qval`/`cb_qstr` and every string setting goes through it: the marks, `shell`,
`editor`, `shader_dir`, `project_roots`, `project_layout`. Latent for all of those,
load-bearing for this one.
**And `--dump-config` does not do what four comments and the docs said it did.** It
calls `config_dump_defaults()`: every setting with its *default*, never the value
your config gives it. The function name was the honest one. Corrected in
`docs/config.md`, `config/config.kdl`, `main.c`, `config.c`, `app.c` and the test's
own docstring, rather than changing what the flag does -- starting a config from it
is the documented use, and `--check` is what reads yours. There is no way to ask for
the effective config; that is a gap, not a lie, and it can be a flag when somebody
wants it.
Verified: 22 checks in `tests/test_clipboard.py`. An error location, an identifier
stopping at a bracket, a URL, a word inside quotes and a run of CJK; the highlight
being exactly as wide as the copy; a separator, a blank cell and a single click each
leaving the clipboard alone; two clicks on different cells not being a double; two
slow clicks not being one; the separator set honoured from a config, including a
quote and a backslash carried through KDL escaping; a word in a scrolled pane coming
from the row on screen; and a mouse-tracking program keeping its double-clicks until
shift takes them back. Three of those failed first because the test asked for the
answer twice -- a second `worded()` call is a second pair of clicks -- and one
because it mapped string indices to columns without counting wide glyphs as two.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/config.md | 11 | ||||
| -rw-r--r-- | docs/panes.md | 6 |
2 files changed, 12 insertions, 5 deletions
diff --git a/docs/config.md b/docs/config.md index a197052..db9da89 100644 --- a/docs/config.md +++ b/docs/config.md @@ -22,10 +22,11 @@ plugin that replaced one already loaded needs a new session. ## Two files worth knowing -- **`sl0ppty --dump-config`** writes every setting with the value it currently - has. It is generated from the code, so it cannot drift from the defaults, and - it is a supported way to start a config: - `sl0ppty --dump-config > ~/.config/sl0ppty/config.kdl`. +- **`sl0ppty --dump-config`** writes every setting with its *default* value — + not the value your config gives it. It is generated from the code, so it + cannot drift, and it is a supported way to start a config: + `sl0ppty --dump-config > ~/.config/sl0ppty/config.kdl`. To see what your own + file does, `sl0ppty --check` reads it and reports what it understood. - **`config/config.kdl`** in the source tree is the same list with the *reasoning* attached — what each setting is for, what it cost to get right, and which ones are opinions. When @@ -110,7 +111,7 @@ theme { frame_focus "#00ff88" } // ...but that one colour is mine |---|---| | geometry | `gap` `gap_aspect` `padding` `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` `hover_delay_ms` `double_click_ms` `anim_ms` `modal_scrim` `dim_unfocused` `keep_dead` `in_band_shaders` `shell` `editor` `shader_dir` | +| behaviour | `focus_follows_mouse` `scroll_lines` `scrollback` `scrollback_bytes` `toast_ms` `hover_delay_ms` `double_click_ms` `word_separators` `anim_ms` `modal_scrim` `dim_unfocused` `keep_dead` `in_band_shaders` `shell` `editor` `shader_dir` | | colour | `theme { }` | | effects | `shaders { }`, `states { }` — see [shaders](shaders.md) and [chrome](chrome.md) | | keys | `keys { }` — see [keys](keys.md) | diff --git a/docs/panes.md b/docs/panes.md index 70dafc7..fd3bcee 100644 --- a/docs/panes.md +++ b/docs/panes.md @@ -119,6 +119,12 @@ either, whatever its width says. - **Select text to copy it.** Release the mouse and it is on your clipboard, sent to your terminal over ssh as well as locally. Middle click pastes. +- **Double-click a word to select it**, and it is copied the same way a drag is: + the highlight *is* the copy. What counts as one word is `word_separators`, + which lists what a word stops at rather than what it is made of — so + `src/app.c:1234`, `https://a.b/c?d=1`, `snake_case` and a run of CJK each come + out whole, while a quote or a bracket ends one. A click on a blank cell or on + a separator selects nothing and leaves your clipboard as it was. - **Images work.** Kitty graphics pass through to your terminal, including the half of the protocol other multiplexers drop, where a program uploads an image once and places it every frame. Your terminal's cell size is carried through to |
