From 22266e384bab0c211d9ea7901bf6b5cfe64341a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 27 Jan 2022 18:34:27 +0100 Subject: [PATCH 1/5] search: refactor: add add_wchars(), make search_add_chars() use it search_add_chars() converts the incoming UTF-8 string into a wide-char string, and then calls add_wchars(). add_wchars() inserts the string into the search buffer, at the current cursor position. --- search.c | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/search.c b/search.c index 817f18b5..2ef6a44f 100644 --- a/search.c +++ b/search.c @@ -398,6 +398,33 @@ search_find_next(struct terminal *term) #undef ROW_DEC } +static void +add_wchars(struct terminal *term, wchar_t *src, size_t count) +{ + /* Strip non-printable characters */ + for (size_t i = 0, j = 0, orig_count = count; i < orig_count; i++) { + if (iswprint(src[i])) + src[j++] = src[i]; + else + count--; + } + + if (!search_ensure_size(term, term->search.len + count)) + return; + + xassert(term->search.len + count < term->search.sz); + + memmove(&term->search.buf[term->search.cursor + count], + &term->search.buf[term->search.cursor], + (term->search.len - term->search.cursor) * sizeof(wchar_t)); + + memcpy(&term->search.buf[term->search.cursor], src, count * sizeof(wchar_t)); + + term->search.len += count; + term->search.cursor += count; + term->search.buf[term->search.len] = L'\0'; +} + void search_add_chars(struct terminal *term, const char *src, size_t count) { @@ -414,29 +441,7 @@ search_add_chars(struct terminal *term, const char *src, size_t count) ps = (mbstate_t){0}; wchar_t wcs[wchars + 1]; mbsnrtowcs(wcs, &_src, count, wchars, &ps); - - /* Strip non-printable characters */ - for (size_t i = 0, j = 0, orig_wchars = wchars; i < orig_wchars; i++) { - if (iswprint(wcs[i])) - wcs[j++] = wcs[i]; - else - wchars--; - } - - if (!search_ensure_size(term, term->search.len + wchars)) - return; - - xassert(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)); - - memcpy(&term->search.buf[term->search.cursor], wcs, wchars * sizeof(wchar_t)); - - term->search.len += wchars; - term->search.cursor += wchars; - term->search.buf[term->search.len] = L'\0'; + add_wchars(term, wcs, wchars); } static void From 739e7d76b4b70da91c50a53026a83d382dd73bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 27 Jan 2022 18:36:28 +0100 Subject: [PATCH 2/5] search: remember last searched-for string between searches Regardless of how we exit search mode (commit or cancel), the search string is remembered. The next time we enter search mode, the last searched-for string will be used when searching for the next/prev match (ctrl+r, ctrl+s), and the search query is empty. --- search.c | 32 +++++++++++++++++++++++++++----- terminal.c | 1 + terminal.h | 5 +++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/search.c b/search.c index 2ef6a44f..8c5051af 100644 --- a/search.c +++ b/search.c @@ -94,10 +94,16 @@ search_cancel_keep_selection(struct terminal *term) struct wl_window *win = term->window; wayl_win_subsurface_destroy(&win->search); - free(term->search.buf); + if (term->search.len > 0) { + free(term->search.last.buf); + term->search.last.buf = term->search.buf; + term->search.last.len = term->search.len; + } else + free(term->search.buf); + term->search.buf = NULL; - term->search.len = 0; - term->search.sz = 0; + term->search.len = term->search.sz = 0; + term->search.cursor = 0; term->search.match = (struct coord){-1, -1}; term->search.match_len = 0; @@ -630,7 +636,15 @@ execute_binding(struct seat *seat, struct terminal *term, return true; case BIND_ACTION_SEARCH_FIND_PREV: - if (term->search.match_len > 0) { + if (term->search.last.buf != NULL && term->search.len == 0) { + add_wchars(term, term->search.last.buf, term->search.last.len); + + free(term->search.last.buf); + term->search.last.buf = NULL; + term->search.last.len = 0; + } + + else if (term->search.match_len > 0) { int new_col = term->search.match.col - 1; int new_row = term->search.match.row; @@ -648,7 +662,15 @@ execute_binding(struct seat *seat, struct terminal *term, return true; case BIND_ACTION_SEARCH_FIND_NEXT: - if (term->search.match_len > 0) { + if (term->search.last.buf != NULL && term->search.len == 0) { + add_wchars(term, term->search.last.buf, term->search.last.len); + + free(term->search.last.buf); + term->search.last.buf = NULL; + term->search.last.len = 0; + } + + else if (term->search.match_len > 0) { int new_col = term->search.match.col + 1; int new_row = term->search.match.row; diff --git a/terminal.c b/terminal.c index c639d3d1..84a43290 100644 --- a/terminal.c +++ b/terminal.c @@ -1638,6 +1638,7 @@ term_destroy(struct terminal *term) &term->custom_glyphs.legacy, GLYPH_LEGACY_COUNT); free(term->search.buf); + free(term->search.last.buf); if (term->render.workers.threads != NULL) { for (size_t i = 0; i < term->render.workers.count; i++) { diff --git a/terminal.h b/terminal.h index e6c82f41..1ff4b3b6 100644 --- a/terminal.h +++ b/terminal.h @@ -514,6 +514,11 @@ struct terminal { bool view_followed_offset; struct coord match; size_t match_len; + + struct { + wchar_t *buf; + size_t len; + } last; } search; struct wayland *wl; From 749d4c076696efdfddca9d8b4cf27ded90160aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 27 Jan 2022 18:39:12 +0100 Subject: [PATCH 3/5] doc: foot.1: shortcuts: mention that there are more actions than listed here --- doc/foot.1.scd | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 6843af1e..10f09853 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -160,13 +160,12 @@ In all other cases, the exit code is that of the client application # KEYBOARD SHORTCUTS -The following keyboard shortcuts are available. +The following keyboard shortcuts are available by default. They can be +changed in *foot.ini*(5). There are also more actions (disabled by +default) available; see *foot.ini*(5). ## NORMAL MODE -Note that these are just the defaults; they can be changed in -*foot.ini(5)*. - *shift*+*page up*/*page down* Scroll up/down in history From 1537fd02bdff5216be5a16239ed9183f7bbb3b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 27 Jan 2022 18:39:46 +0100 Subject: [PATCH 4/5] doc: foot.1: describe how to search for the previous search string --- doc/foot.1.scd | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/foot.1.scd b/doc/foot.1.scd index 10f09853..e990ca0d 100644 --- a/doc/foot.1.scd +++ b/doc/foot.1.scd @@ -202,10 +202,12 @@ default) available; see *foot.ini*(5). ## SCROLLBACK SEARCH *ctrl*+*r* - Search _backward_ for the next match + Search _backward_ for the next match. If the search string is + empty, the last searched-for string is used. *ctrl*+*s* - Search _forward_ for the next match + Search _forward_ for the next match. If the search string is + empty, the last searched-for string is used. *ctrl*+*w* Extend current selection (and thus the search criteria) to the end From eb33a0529ffaa64ea0da6a46ccacfd89131122fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 27 Jan 2022 18:40:04 +0100 Subject: [PATCH 5/5] changelog: search for last searched-for string --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ca77fb5..ea3d2d24 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,8 @@ - `DECSTBM` - _Set Top and Bottom Margins_ - `SGR` - _Set Graphic Rendition_ - `DECSCUSR` - _Set Cursor Style_ +* Support for searching for the last searched-for string in scrollback + search (search for next/prev match with an empty search string). ### Changed