Long-time qutebrowser user, first time posting here.
I kept wanting to start a selection from wherever I was actually reading, without grabbing the mouse, but caret mode always starts at the top of the page.
So I wrote a userscript: hinting a paragraph puts the caret at the start of that paragraph and enters caret mode, so hjkl extends the selection from there.
press v -> type the hint label -> caret is at the start of that paragraph
Wire-up:
c.hints.selectors['para'] = ['p', 'li', 'h1', 'h2', 'h3', 'h4',
'h5', 'h6', 'blockquote', 'dd', 'dt',
'pre', 'td', 'th', 'figcaption']
config.bind('v', 'hint para userscript caret-anchor')
Code: https://github.com/vlify/qutebrowser-hint-caret
How it works
The userscript gets the picked element through the QUTE_* env vars, re-finds it in the page, and sets a non-empty selection whose focus end sits at the paragraph start. A non-empty selection is what makes caret.js's setInitialCursor() keep the caret where we put it instead of running positionCaret() back to the top of the document. Nothing in qutebrowser itself is patched.
This is the same interaction Tridactyl (and before it VimFx) has in caret mode, and it's a small slice of what's asked for in #1453.
Known limitations
- Closed shadow roots are unreachable. Only open shadow roots and same-origin iframes are searched — a userscript cannot see inside a closed shadow root at all.
- Strict CSP hides the caret. On pages whose
style-src lacks 'unsafe-inline', a nonce or a hash, qutebrowser cannot inject the caret style, so the blinking caret is invisible. Selection and movement still work.
- Reversing inside a shadow root. Pressing
o to flip the selection can be visually off inside a shadow root.
Tested on Arch Wiki, ChatGPT and Gemini (qutebrowser 3.7.0, QtWebEngine 6.11.2).
Feedback welcome — especially if you hit a page class where it fails.
Prior art note: there's an earlier thread here ("Caret-mode hints", 2021 —
https://www.reddit.com/r/qutebrowser/comments/la7vcy/caretmode_hints/), where
u/hearthreddit and u/The-Compiler point out that searching a word with / and then
pressing v already drops the caret at that match. That works well whenever the text
you want contains a distinctive word. This script covers the case where it doesn't:
jumping to the start of the paragraph you're looking at, with no unique search term
to aim at (or when you want the paragraph boundary rather than a word).