diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a991d8..dad8450e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,9 @@ (https://codeberg.org/dnkl/foot/issues/42). * Key bindings in _scollback search_ mode are now configurable. * `--check-config` command line option. +* **pipe-selected** key binding. Works like **pipe-visible** and + **pipe-scrollback**, but only pipes the currently selected text, if + any (https://codeberg.org/dnkl/foot/issues/51). ### Deprecated diff --git a/config.c b/config.c index a1329573..6d2c3541 100644 --- a/config.c +++ b/config.c @@ -66,6 +66,7 @@ static const char *const binding_action_map[] = { [BIND_ACTION_FULLSCREEN] = "fullscreen", [BIND_ACTION_PIPE_SCROLLBACK] = "pipe-scrollback", [BIND_ACTION_PIPE_VIEW] = "pipe-visible", + [BIND_ACTION_PIPE_SELECTED] = "pipe-selected", }; static_assert(ALEN(binding_action_map) == BIND_ACTION_COUNT, diff --git a/doc/footrc.5.scd b/doc/footrc.5.scd index c148d27f..c112a257 100644 --- a/doc/footrc.5.scd +++ b/doc/footrc.5.scd @@ -251,11 +251,11 @@ e.g. *search-start=none*. *fullscreen* Toggles the fullscreen state. Default: _not bound_. -*pipe-visible*, *pipe-scrollback* - Pipes the currently visible text, or the entire scrollback, to an - external tool. The syntax for this option is a bit special; the - first part of the value is the command to execute enclosed in - "[]", followed by the binding(s). +*pipe-visible*, *pipe-scrollback*, *pipe-selected* + Pipes the currently visible text, the entire scrollback, or the + currently selected text to an external tool. The syntax for this + option is a bit special; the first part of the value is the + command to execute enclosed in "[]", followed by the binding(s). You can configure multiple pipes as long as the command strings are different and the key bindings are unique. diff --git a/footrc b/footrc index b088c165..87fb6fe6 100644 --- a/footrc +++ b/footrc @@ -64,6 +64,8 @@ # fullscreen=none # pipe-visible=[sh -c "xurls | bemenu | xargs -r firefox"] none # pipe-scrollback=[sh -c "xurls | bemenu | xargs -r firefox"] none +# pipe-selected=[xargs -r firefox] none + [search-bindings] # cancel=Control+g Escape diff --git a/input.c b/input.c index fcf79111..c3231a09 100644 --- a/input.c +++ b/input.c @@ -145,7 +145,8 @@ execute_binding(struct seat *seat, struct terminal *term, break; case BIND_ACTION_PIPE_SCROLLBACK: - case BIND_ACTION_PIPE_VIEW: { + case BIND_ACTION_PIPE_VIEW: + case BIND_ACTION_PIPE_SELECTED: { if (pipe_argv == NULL) break; @@ -171,9 +172,27 @@ execute_binding(struct seat *seat, struct terminal *term, goto pipe_err; } - bool success = action == BIND_ACTION_PIPE_SCROLLBACK - ? term_scrollback_to_text(term, &text, &len) - : term_view_to_text(term, &text, &len); + bool success; + switch (action) { + case BIND_ACTION_PIPE_SCROLLBACK: + success = term_scrollback_to_text(term, &text, &len); + break; + + case BIND_ACTION_PIPE_VIEW: + success = term_view_to_text(term, &text, &len); + break; + + case BIND_ACTION_PIPE_SELECTED: + text = selection_to_text(term); + success = text != NULL; + len = text != NULL ? strlen(text) : 0; + break; + + default: + assert(false); + success = false; + break; + } if (!success) goto pipe_err; diff --git a/selection.c b/selection.c index ffe06c27..8dd93028 100644 --- a/selection.c +++ b/selection.c @@ -204,9 +204,12 @@ extract_one_const_wrapper(struct terminal *term, return extract_one(term, row, cell, col, data); } -static char * -extract_selection(const struct terminal *term) +char * +selection_to_text(const struct terminal *term) { + if (term->selection.end.row == -1) + return NULL; + struct extraction_context *ctx = extract_begin(term->selection.kind); if (ctx == NULL) return NULL; @@ -873,7 +876,7 @@ selection_to_clipboard(struct seat *seat, struct terminal *term, uint32_t serial return; /* Get selection as a string */ - char *text = extract_selection(term); + char *text = selection_to_text(term); if (!text_to_clipboard(seat, term, text, serial)) free(text); } @@ -1074,7 +1077,7 @@ selection_to_primary(struct seat *seat, struct terminal *term, uint32_t serial) return; /* Get selection as a string */ - char *text = extract_selection(term); + char *text = selection_to_text(term); if (!text_to_primary(seat, term, text, serial)) free(text); } diff --git a/selection.h b/selection.h index bd995855..639c36e9 100644 --- a/selection.h +++ b/selection.h @@ -30,6 +30,7 @@ void selection_mark_word( void selection_mark_row( struct seat *seat, struct terminal *term, int row, uint32_t serial); +char *selection_to_text(const struct terminal *term); void selection_to_clipboard( struct seat *seat, struct terminal *term, uint32_t serial); void selection_from_clipboard( diff --git a/wayland.h b/wayland.h index 3b815b6a..3dbd034c 100644 --- a/wayland.h +++ b/wayland.h @@ -41,6 +41,7 @@ enum bind_action_normal { BIND_ACTION_FULLSCREEN, BIND_ACTION_PIPE_SCROLLBACK, BIND_ACTION_PIPE_VIEW, + BIND_ACTION_PIPE_SELECTED, BIND_ACTION_COUNT, };