mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
search: add {clipboard,primary}-paste key bindings
These bindings copy from the clipboard or primary selection into the search buffer. Default bindings: * clipboard-paste: ctrl+v, ctrl+y * primary-paste: shift+insert
This commit is contained in:
parent
43f293f22e
commit
f3e6941c9a
8 changed files with 90 additions and 25 deletions
|
|
@ -47,6 +47,10 @@
|
|||
font is used (https://codeberg.org/dnkl/foot/issues/169).
|
||||
* Drag & drop support; text, files and URLs can now be dropped in a
|
||||
foot terminal window (https://codeberg.org/dnkl/foot/issues/175).
|
||||
* **clipboard-paste** and **primary-paste** scrollback search
|
||||
bindings. By default, they are bound to `ctrl+v ctrl+y` and
|
||||
`shift+insert` respectively, and lets you paste from the clipboard
|
||||
or primary selection into the search buffer.
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
|
|||
|
|
@ -162,6 +162,12 @@ These are the default shortcuts. See `man foot.ini` and the example
|
|||
: Same as <kbd>ctrl</kbd>+<kbd>w</kbd>, except that the only word
|
||||
separating characters are whitespace characters.
|
||||
|
||||
<kbd>ctrl</kbd>+<kbd>v</kbd>
|
||||
: Paste from clipboard into the search buffer.
|
||||
|
||||
<kbd>shift</kbd>+<kbd>insert</kbd>
|
||||
: Paste from primary selection into the search buffer.
|
||||
|
||||
<kbd>escape</kbd>, <kbd>ctrl</kbd>+<kbd>g</kbd>
|
||||
: Cancel the search
|
||||
|
||||
|
|
|
|||
6
config.c
6
config.c
|
|
@ -108,6 +108,8 @@ static const char *const search_binding_action_map[] = {
|
|||
[BIND_ACTION_SEARCH_DELETE_NEXT_WORD] = "delete-next-word",
|
||||
[BIND_ACTION_SEARCH_EXTEND_WORD] = "extend-to-word-boundary",
|
||||
[BIND_ACTION_SEARCH_EXTEND_WORD_WS] = "extend-to-next-whitespace",
|
||||
[BIND_ACTION_SEARCH_CLIPBOARD_PASTE] = "clipboard-paste",
|
||||
[BIND_ACTION_SEARCH_PRIMARY_PASTE] = "primary-paste",
|
||||
};
|
||||
|
||||
static_assert(ALEN(search_binding_action_map) == BIND_ACTION_SEARCH_COUNT,
|
||||
|
|
@ -1840,6 +1842,7 @@ add_default_search_bindings(struct config *conf)
|
|||
const struct config_key_modifiers none = {0};
|
||||
const struct config_key_modifiers alt = {.alt = true};
|
||||
const struct config_key_modifiers ctrl = {.ctrl = true};
|
||||
const struct config_key_modifiers shift = {.shift = true};
|
||||
const struct config_key_modifiers ctrl_shift = {.ctrl = true, .shift = true};
|
||||
|
||||
add_binding(BIND_ACTION_SEARCH_CANCEL, ctrl, XKB_KEY_g);
|
||||
|
|
@ -1867,6 +1870,9 @@ add_default_search_bindings(struct config *conf)
|
|||
add_binding(BIND_ACTION_SEARCH_DELETE_NEXT_WORD, alt, XKB_KEY_d);
|
||||
add_binding(BIND_ACTION_SEARCH_EXTEND_WORD, ctrl, XKB_KEY_w);
|
||||
add_binding(BIND_ACTION_SEARCH_EXTEND_WORD_WS, ctrl_shift, XKB_KEY_W);
|
||||
add_binding(BIND_ACTION_SEARCH_CLIPBOARD_PASTE, ctrl, XKB_KEY_v);
|
||||
add_binding(BIND_ACTION_SEARCH_CLIPBOARD_PASTE, ctrl, XKB_KEY_y);
|
||||
add_binding(BIND_ACTION_SEARCH_PRIMARY_PASTE, shift, XKB_KEY_Insert);
|
||||
|
||||
#undef add_binding
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,6 +186,12 @@ Note that these are just the defaults; they can be changed in
|
|||
Same as *ctrl*+*w*, except that the only word separating
|
||||
characters are whitespace characters.
|
||||
|
||||
*ctrl*+*v*, *ctrl*+*y*
|
||||
Paste from clipboard into the searh buffer.
|
||||
|
||||
*shift*+*insert*
|
||||
Paste from primary selection into the search buffer.
|
||||
|
||||
*escape*, *ctrl*+*g*
|
||||
Cancel the search
|
||||
|
||||
|
|
|
|||
|
|
@ -452,6 +452,13 @@ scrollback search mode. The syntax is exactly the same as the regular
|
|||
Extend the current selection to the next whitespace. Default:
|
||||
_Control+Shift+W_.
|
||||
|
||||
*clipboard-paste*
|
||||
Paste from the _clipboard_ into the search buffer. Default:
|
||||
_Control+v Control+y_.
|
||||
|
||||
*primary-paste*
|
||||
Paste from the _primary selection_ into the search
|
||||
buffer. Default: _Shift+Insert_.
|
||||
|
||||
# SECTION: mouse-bindings
|
||||
|
||||
|
|
|
|||
2
foot.ini
2
foot.ini
|
|
@ -102,6 +102,8 @@
|
|||
# delete-next-word=Mod1+d Control+Delete
|
||||
# extend-to-word-boundary=Control+w
|
||||
# extend-to-next-whitespace=Control+Shift+W
|
||||
# clipboard-paste=Control+v Control+y
|
||||
# primary-paste=Shift+Insert
|
||||
|
||||
[mouse-bindings]
|
||||
# primary-paste=BTN_MIDDLE
|
||||
|
|
|
|||
82
search.c
82
search.c
|
|
@ -332,6 +332,35 @@ search_find_next(struct terminal *term)
|
|||
#undef ROW_DEC
|
||||
}
|
||||
|
||||
static void
|
||||
add_chars(struct terminal *term, const char *src, size_t count)
|
||||
{
|
||||
mbstate_t ps = {0};
|
||||
size_t wchars = mbsnrtowcs(NULL, &src, count, 0, &ps);
|
||||
|
||||
if (wchars == -1) {
|
||||
LOG_ERRNO("failed to convert %.*s to wchars", (int)count, src);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!search_ensure_size(term, term->search.len + wchars))
|
||||
return;
|
||||
|
||||
assert(term->search.len + wchars < term->search.sz);
|
||||
|
||||
memmove(&term->search.buf[term->search.cursor + wchars],
|
||||
&term->search.buf[term->search.cursor],
|
||||
(term->search.len - term->search.cursor) * sizeof(wchar_t));
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
mbsnrtowcs(&term->search.buf[term->search.cursor], &src, count,
|
||||
wchars, &ps);
|
||||
|
||||
term->search.len += wchars;
|
||||
term->search.cursor += wchars;
|
||||
term->search.buf[term->search.len] = L'\0';
|
||||
}
|
||||
|
||||
static void
|
||||
search_match_to_end_of_word(struct terminal *term, bool spaces_only)
|
||||
{
|
||||
|
|
@ -461,6 +490,23 @@ distance_prev_word(const struct terminal *term)
|
|||
return term->search.cursor - cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
from_clipboard_cb(char *text, size_t size, void *user)
|
||||
{
|
||||
struct terminal *term = user;
|
||||
add_chars(term, text, size);
|
||||
}
|
||||
|
||||
static void
|
||||
from_clipboard_done(void *user)
|
||||
{
|
||||
struct terminal *term = user;
|
||||
|
||||
LOG_DBG("search: buffer: %ls", term->search.buf);
|
||||
search_find_next(term);
|
||||
render_refresh_search(term);
|
||||
}
|
||||
|
||||
static bool
|
||||
execute_binding(struct seat *seat, struct terminal *term,
|
||||
enum bind_action_search action, uint32_t serial)
|
||||
|
|
@ -609,6 +655,16 @@ execute_binding(struct seat *seat, struct terminal *term,
|
|||
search_match_to_end_of_word(term, true);
|
||||
return false;
|
||||
|
||||
case BIND_ACTION_SEARCH_CLIPBOARD_PASTE:
|
||||
text_from_clipboard(
|
||||
seat, term, &from_clipboard_cb, &from_clipboard_done, term);
|
||||
return false;
|
||||
|
||||
case BIND_ACTION_SEARCH_PRIMARY_PASTE:
|
||||
text_from_primary(
|
||||
seat, term, &from_clipboard_cb, &from_clipboard_done, term);
|
||||
return false;
|
||||
|
||||
case BIND_ACTION_SEARCH_COUNT:
|
||||
assert(false);
|
||||
return false;
|
||||
|
|
@ -666,31 +722,7 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key,
|
|||
if (count == 0)
|
||||
return;
|
||||
|
||||
const char *src = (const char *)buf;
|
||||
mbstate_t ps = {0};
|
||||
size_t wchars = mbsnrtowcs(NULL, &src, count, 0, &ps);
|
||||
|
||||
if (wchars == -1) {
|
||||
LOG_ERRNO("failed to convert %.*s to wchars", count, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!search_ensure_size(term, term->search.len + wchars))
|
||||
return;
|
||||
|
||||
assert(term->search.len + wchars < term->search.sz);
|
||||
|
||||
memmove(&term->search.buf[term->search.cursor + wchars],
|
||||
&term->search.buf[term->search.cursor],
|
||||
(term->search.len - term->search.cursor) * sizeof(wchar_t));
|
||||
|
||||
memset(&ps, 0, sizeof(ps));
|
||||
mbsnrtowcs(&term->search.buf[term->search.cursor], &src, count,
|
||||
wchars, &ps);
|
||||
|
||||
term->search.len += wchars;
|
||||
term->search.cursor += wchars;
|
||||
term->search.buf[term->search.len] = L'\0';
|
||||
add_chars(term, (const char *)buf, count);
|
||||
|
||||
update_search:
|
||||
LOG_DBG("search: buffer: %ls", term->search.buf);
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ enum bind_action_search {
|
|||
BIND_ACTION_SEARCH_DELETE_NEXT_WORD,
|
||||
BIND_ACTION_SEARCH_EXTEND_WORD,
|
||||
BIND_ACTION_SEARCH_EXTEND_WORD_WS,
|
||||
BIND_ACTION_SEARCH_CLIPBOARD_PASTE,
|
||||
BIND_ACTION_SEARCH_PRIMARY_PASTE,
|
||||
BIND_ACTION_SEARCH_COUNT,
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue