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/"); 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 Test speed of completion calculations
@ -1625,6 +1637,7 @@ int main(int argc, char **argv)
test_word_motion(); test_word_motion();
test_is_potential_path(); test_is_potential_path();
test_colors(); test_colors();
test_autosuggestion_combining();
test_autosuggest_suggest_special(); test_autosuggest_suggest_special();
history_tests_t::test_history(); history_tests_t::test_history();
history_tests_t::test_history_merge(); history_tests_t::test_history_merge();

View file

@ -449,6 +449,53 @@ int reader_exit_forced()
return 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 Repaint the entire commandline. This means reset and clear the
commandline, write the prompt, perform syntax highlighting, write commandline, write the prompt, perform syntax highlighting, write
@ -457,10 +504,12 @@ int reader_exit_forced()
static void reader_repaint() 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); 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(); size_t len = full_line.size();
if (len < 1) if (len < 1)
len = 1; len = 1;

View file

@ -214,5 +214,8 @@ int reader_shell_test(const wchar_t *b);
*/ */
int reader_search_mode(); 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 #endif

View file

@ -179,16 +179,6 @@ public:
\param indent the indent to use for the command line \param indent the indent to use for the command line
\param cursor_pos where the cursor is \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, void s_write(screen_t *s,
const wcstring &left_prompt, const wcstring &left_prompt,
const wcstring &right_prompt, const wcstring &right_prompt,