Make history search smartcase

This makes history searches case-insensitive, unless the search string
contains an uppercase character.

This is what vim calls "smartcase".

Fixes #7273.
This commit is contained in:
Fabian Homborg 2020-09-22 16:11:39 +02:00
parent 0a0149cc2a
commit 1da56f9937
4 changed files with 18 additions and 3 deletions

View file

@ -112,6 +112,7 @@ Interactive improvements
- ``diff`` will now colourise output, if supported (#7308).
- The command-not-found handling has been simplified. When it can't find a command, fish now just executes a function called ``fish_command_not_found`` instead of firing an event, making it easier to replace and reason about. Shims for backwards-compatibility have been added (#7293).
- Control-C no longer occasionally prints an "unknown command" error (#7145).
- History search is now case-insensitive unless the search string contains an uppercase character (#7273).
New or improved bindings

View file

@ -1718,7 +1718,7 @@ After a command has been executed, it is remembered in the history list. Any dup
By pressing :kbd:`Alt`\ +\ :kbd:`↑` and :kbd:`Alt`\ +\ :kbd:`↓`, a history search is also performed, but instead of searching for a complete commandline, each commandline is broken into separate elements just like it would be before execution, and the history is searched for an element matching that under the cursor.
History searches can be aborted by pressing the escape key.
History searches are case-insensitive unless the search string contains an uppercase character, and they can be aborted by pressing the escape key.
Prefixing the commandline with a space will prevent the entire line from being stored in the history.

View file

@ -398,11 +398,15 @@ class reader_history_search_t {
matches_ = {text};
match_index_ = 0;
mode_ = mode;
history_search_flags_t flags = history_search_no_dedup;
// Make the search case-insensitive unless we have an uppercase character.
wcstring low = wcstolower(text);
if (low == text) flags |= history_search_ignore_case;
// We can skip dedup in history_search_t because we do it ourselves in skips_.
search_ = history_search_t(
*hist, text,
by_prefix() ? history_search_type_t::prefix : history_search_type_t::contains,
history_search_no_dedup);
flags);
}
/// Reset to inactive search.
@ -935,7 +939,7 @@ void reader_data_t::paint_layout(const wchar_t *reason) {
if (!conf.in_silent_mode && !data.history_search_text.empty()) {
const wcstring &needle = data.history_search_text;
const wcstring &haystack = cmd_line->text();
size_t match_pos = haystack.find(needle);
size_t match_pos = ifind(haystack,needle);
if (match_pos != wcstring::npos) {
for (size_t i = 0; i < needle.size(); i++) {
colors.at(match_pos + i).background = highlight_role_t::search_match;

View file

@ -132,3 +132,13 @@ expect_re("count again 1\r\n")
# Verify that the $history var has the expected content.
sendline("echo history2=$history\[2\]")
expect_re("history2=echo count AGAIN .*\r\n")
# Verify that history search is case-insensitive by default
sendline("echo term")
expect_str("term")
sendline("echo TERM")
expect_str("TERM")
sendline("echo banana")
expect_str("banana")
send("ter\x1b[A") # up-arrow
expect_re("echo TERM")