When the user input contains capital letters, use its case rather than the autosuggestion's case

Fixes https://github.com/fish-shell/fish-shell/issues/335
This commit is contained in:
ridiculousfish 2013-01-05 15:21:42 -08:00
parent 8d4a701f86
commit 85fdf587c0
4 changed files with 67 additions and 12 deletions

View file

@ -1022,6 +1022,18 @@ static void test_autosuggest_suggest_special()
system("rm -Rf ~/test_autosuggest_suggest_special/");
}
static void test_autosuggestion_combining()
{
say(L"Testing autosuggestion combining");
assert(combine_command_and_autosuggestion(L"alpha", L"alphabeta") == L"alphabeta");
// when the last token contains no capital letters, we use the case of the autosuggestion
assert(combine_command_and_autosuggestion(L"alpha", L"ALPHABETA") == L"ALPHABETA");
// when the last token contains capital letters, we use its case
assert(combine_command_and_autosuggestion(L"alPha", L"alphabeTa") == L"alPhabeTa");
}
/**
Test speed of completion calculations
@ -1625,6 +1637,7 @@ int main(int argc, char **argv)
test_word_motion();
test_is_potential_path();
test_colors();
test_autosuggestion_combining();
test_autosuggest_suggest_special();
history_tests_t::test_history();
history_tests_t::test_history_merge();

View file

@ -449,6 +449,53 @@ int reader_exit_forced()
return exit_forced;
}
/* Given a command line and an autosuggestion, return the string that gets shown to the user */
wcstring combine_command_and_autosuggestion(const wcstring &cmdline, const wcstring &autosuggestion)
{
// We want to compute the full line, containing the command line and the autosuggestion
// They may disagree on whether characters are uppercase or lowercase
// Here we do something funny: if the last token of the command line contains any uppercase characters, we use its case
// Otherwise we use the case of the autosuggestion
// This is an idea from https://github.com/fish-shell/fish-shell/issues/335
wcstring full_line;
if (autosuggestion.size() <= cmdline.size() || cmdline.empty())
{
// No or useless autosuggestion, or no command line
full_line = cmdline;
}
else if (string_prefixes_string(cmdline, autosuggestion))
{
// No case disagreements, or no extra characters in the autosuggestion
full_line = autosuggestion;
}
else
{
// We have an autosuggestion which is not a prefix of the command line, i.e. a case disagreement
// Decide whose case we want to use
const wchar_t *begin = NULL, *cmd = cmdline.c_str();
parse_util_token_extent(cmd, cmdline.size() - 1, &begin, NULL, NULL, NULL);
bool last_token_contains_uppercase = false;
if (begin)
{
const wchar_t *end = begin + wcslen(begin);
last_token_contains_uppercase = (std::find_if(begin, end, iswupper) != end);
}
if (! last_token_contains_uppercase)
{
// Use the autosuggestion's case
full_line = autosuggestion;
}
else
{
// Use the command line case for its characters, then append the remaining characters in the autosuggestion
// Note that we know that autosuggestion.size() > cmdline.size() due to the first test above
full_line = cmdline;
full_line.append(autosuggestion, cmdline.size(), autosuggestion.size() - cmdline.size());
}
}
return full_line;
}
/**
Repaint the entire commandline. This means reset and clear the
commandline, write the prompt, perform syntax highlighting, write
@ -457,10 +504,12 @@ int reader_exit_forced()
static void reader_repaint()
{
//Update the indentation
// Update the indentation
parser_t::principal_parser().test(data->command_line.c_str(), &data->indents[0], 0, 0);
wcstring full_line = (data->autosuggestion.empty() ? data->command_line : data->autosuggestion);
// Combine the command and autosuggestion into one string
wcstring full_line = combine_command_and_autosuggestion(data->command_line, data->autosuggestion);
size_t len = full_line.size();
if (len < 1)
len = 1;

View file

@ -214,5 +214,8 @@ int reader_shell_test(const wchar_t *b);
*/
int reader_search_mode();
/* Given a command line and an autosuggestion, return the string that gets shown to the user. Exposed for testing purposes only. */
wcstring combine_command_and_autosuggestion(const wcstring &cmdline, const wcstring &autosuggestion);
#endif

View file

@ -179,16 +179,6 @@ public:
\param indent the indent to use for the command line
\param cursor_pos where the cursor is
*/
void s_write(screen_t *s,
const wchar_t *left_prompt,
const wchar_t *right_prompt,
const wchar_t *commandline,
size_t explicit_len,
const int *colors,
const int *indent,
size_t cursor_pos);
void s_write(screen_t *s,
const wcstring &left_prompt,
const wcstring &right_prompt,