mirror of
https://github.com/fish-shell/fish-shell
synced 2025-01-13 05:28:49 +00:00
Next stab at abbreviations. Highlighting should work.
This commit is contained in:
parent
92099c7af2
commit
f9c2a77c67
4 changed files with 64 additions and 54 deletions
|
@ -535,21 +535,19 @@ static void test_utils()
|
|||
|
||||
const wchar_t *begin = NULL, *end = NULL;
|
||||
parse_util_cmdsubst_extent(a, 0, &begin, &end);
|
||||
if (begin != a || end - begin != wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
parse_util_cmdsubst_extent(a, 1, &begin, &end);
|
||||
if (begin != a || end - begin != wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
parse_util_cmdsubst_extent(a, 2, &begin, &end);
|
||||
if (begin != a || end - begin != wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
parse_util_cmdsubst_extent(a, 3, &begin, &end);
|
||||
if (begin != a || end - begin != wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
|
||||
parse_util_cmdsubst_extent(a, 8, &begin, &end);
|
||||
if (begin != a + wcslen(L"echo (")) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
|
||||
parse_util_cmdsubst_extent(a, 17, &begin, &end);
|
||||
if (begin != a + wcslen(L"echo (echo (")) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
|
||||
|
||||
}
|
||||
|
||||
class lru_node_test_t : public lru_node_t
|
||||
|
@ -707,15 +705,6 @@ static void test_abbreviations(void)
|
|||
{
|
||||
say(L"Testing abbreviations");
|
||||
|
||||
const wchar_t *buff = L"echo (echo (echo (gc";
|
||||
size_t cursor_pos = wcslen(buff) - 2;
|
||||
const wchar_t *cmdsub_begin = NULL, *cmdsub_end = NULL;
|
||||
parse_util_cmdsubst_extent(buff, cursor_pos, &cmdsub_begin, &cmdsub_end);
|
||||
assert(cmdsub_begin != NULL && cmdsub_begin >= buff);
|
||||
assert(cmdsub_end != NULL && cmdsub_end >= cmdsub_begin);
|
||||
fprintf(stderr, "cmdsub of '%ls' at %lu is '%ls'\n", buff, cursor_pos, wcstring(cmdsub_begin, cmdsub_end).c_str());
|
||||
exit(0);
|
||||
|
||||
const wchar_t *abbreviations =
|
||||
L"gc=git checkout" ARRAY_SEP_STR
|
||||
L"foo=" ARRAY_SEP_STR
|
||||
|
@ -742,24 +731,31 @@ static void test_abbreviations(void)
|
|||
if (result != L"bar") err(L"Wrong abbreviation result for foo");
|
||||
|
||||
bool expanded;
|
||||
expanded = reader_expand_abbreviation_in_command(L"just a command", wcslen(L"just "), &result);
|
||||
expanded = reader_expand_abbreviation_in_command(L"just a command", 3, &result);
|
||||
if (expanded) err(L"Command wrongly expanded on line %ld", (long)__LINE__);
|
||||
expanded = reader_expand_abbreviation_in_command(L"gc somebranch", 0, &result);
|
||||
if (expanded) err(L"Command wrongly expanded on line %ld", (long)__LINE__);
|
||||
expanded = reader_expand_abbreviation_in_command(L"gc somebranch", 1, &result);
|
||||
if (expanded) err(L"Command wrongly expanded on line %ld", (long)__LINE__);
|
||||
if (! expanded) err(L"Command not expanded on line %ld", (long)__LINE__);
|
||||
|
||||
expanded = reader_expand_abbreviation_in_command(L"gc somebranch", wcslen(L"gc "), &result);
|
||||
expanded = reader_expand_abbreviation_in_command(L"gc somebranch", wcslen(L"gc"), &result);
|
||||
if (! expanded) err(L"gc not expanded");
|
||||
if (result != L"git checkout somebranch") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str());
|
||||
|
||||
expanded = reader_expand_abbreviation_in_command(L"echo hi ; gc somebranch", wcslen(L"echo hi ; gc "), &result);
|
||||
expanded = reader_expand_abbreviation_in_command(L"echo hi ; gc somebranch", wcslen(L"echo hi ; g"), &result);
|
||||
if (! expanded) err(L"gc not expanded on line %ld", (long)__LINE__);
|
||||
if (result != L"echo hi ; git checkout somebranch") err(L"gc incorrectly expanded on line %ld", (long)__LINE__);
|
||||
|
||||
expanded = reader_expand_abbreviation_in_command(L"echo (echo (echo (echo (gc ", wcslen(L"echo (echo (echo (echo (gc "), &result);
|
||||
expanded = reader_expand_abbreviation_in_command(L"echo (echo (echo (echo (gc ", wcslen(L"echo (echo (echo (echo (gc"), &result);
|
||||
if (! expanded) err(L"gc not expanded on line %ld", (long)__LINE__);
|
||||
if (result != L"echo (echo (git checkout ") err(L"gc incorrectly expanded on line %ld", (long)__LINE__);
|
||||
if (result != L"echo (echo (echo (echo (git checkout ") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str());
|
||||
|
||||
/* if commands should be expanded */
|
||||
expanded = reader_expand_abbreviation_in_command(L"if gc", wcslen(L"if gc"), &result);
|
||||
if (! expanded) err(L"gc not expanded on line %ld", (long)__LINE__);
|
||||
if (result != L"if git checkout") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str());
|
||||
|
||||
/* others should not be */
|
||||
expanded = reader_expand_abbreviation_in_command(L"of gc", wcslen(L"of gc"), &result);
|
||||
if (expanded) err(L"gc incorrectly expanded on line %ld", (long)__LINE__);
|
||||
|
||||
env_pop();
|
||||
}
|
||||
|
|
|
@ -1106,6 +1106,9 @@ static void tokenize(const wchar_t * const buff, std::vector<int> &color, const
|
|||
if (! is_cmd && use_function)
|
||||
is_cmd = function_exists_no_autoload(cmd, vars);
|
||||
|
||||
if (! is_cmd)
|
||||
is_cmd = expand_abbreviation(cmd, NULL);
|
||||
|
||||
/*
|
||||
Moving on to expensive tests
|
||||
*/
|
||||
|
|
|
@ -541,7 +541,6 @@ void parse_util_set_argv(const wchar_t * const *argv, const wcstring_list_t &nam
|
|||
{
|
||||
const wchar_t * const *arg;
|
||||
size_t i;
|
||||
|
||||
for (i=0, arg=argv; i < named_arguments.size(); i++)
|
||||
{
|
||||
env_set(named_arguments.at(i).c_str(), *arg, ENV_LOCAL);
|
||||
|
@ -549,10 +548,7 @@ void parse_util_set_argv(const wchar_t * const *argv, const wcstring_list_t &nam
|
|||
if (*arg)
|
||||
arg++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wchar_t *parse_util_unescape_wildcards(const wchar_t *str)
|
||||
|
|
69
reader.cpp
69
reader.cpp
|
@ -97,8 +97,8 @@ commence.
|
|||
#include "iothread.h"
|
||||
#include "intern.h"
|
||||
#include "path.h"
|
||||
|
||||
#include "parse_util.h"
|
||||
#include "parser_keywords.h"
|
||||
|
||||
/**
|
||||
Maximum length of prefix string when printing completion
|
||||
|
@ -249,8 +249,8 @@ public:
|
|||
/** Do what we need to do whenever our command line changes */
|
||||
void command_line_changed(void);
|
||||
|
||||
/** Expand abbreviations at the current cursor position. Returns true if the command line changed. */
|
||||
bool expand_abbreviation_as_necessary(void);
|
||||
/** Expand abbreviations at the current cursor position. */
|
||||
bool expand_abbreviation_as_necessary();
|
||||
|
||||
/** The current position of the cursor in buff. */
|
||||
size_t buff_pos;
|
||||
|
@ -647,17 +647,12 @@ void reader_data_t::command_line_changed()
|
|||
/* Expand abbreviations at the given cursor position. Does NOT inspect 'data'. */
|
||||
bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t cursor_pos, wcstring *output)
|
||||
{
|
||||
/* Can't have the cursor at the beginning */
|
||||
if (cursor_pos == 0)
|
||||
return false;
|
||||
|
||||
/* See if we are at "command position". Get the surrounding command substitution, and get the extent of the first token. */
|
||||
const wchar_t * const buff = cmdline.c_str();
|
||||
const wchar_t *cmdsub_begin = NULL, *cmdsub_end = NULL;
|
||||
parse_util_cmdsubst_extent(buff, cursor_pos, &cmdsub_begin, &cmdsub_end);
|
||||
assert(cmdsub_begin != NULL && cmdsub_begin >= buff);
|
||||
assert(cmdsub_end != NULL && cmdsub_end >= cmdsub_begin);
|
||||
fprintf(stderr, "cmdsub of '%ls' at %lu is '%ls'\n", cmdline.c_str(), cursor_pos, wcstring(cmdsub_begin, cmdsub_end).c_str());
|
||||
|
||||
/* Determine the offset of this command substitution */
|
||||
const size_t subcmd_offset = cmdsub_begin - buff;
|
||||
|
@ -667,8 +662,9 @@ bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t curso
|
|||
|
||||
/* Get the token before the cursor */
|
||||
const wchar_t *subcmd_tok_begin = NULL, *subcmd_tok_end = NULL;
|
||||
size_t subcmd_cursor_pos = cursor_pos + subcmd_offset;
|
||||
parse_util_token_extent(subcmd_cstr, subcmd_cursor_pos, NULL, NULL, &subcmd_tok_begin, &subcmd_tok_end);
|
||||
assert(cursor_pos >= subcmd_offset);
|
||||
size_t subcmd_cursor_pos = cursor_pos - subcmd_offset;
|
||||
parse_util_token_extent(subcmd_cstr, subcmd_cursor_pos, &subcmd_tok_begin, &subcmd_tok_end, NULL, NULL);
|
||||
|
||||
/* Compute the offset of the token before the cursor within the subcmd */
|
||||
assert(subcmd_tok_begin >= subcmd_cstr);
|
||||
|
@ -700,12 +696,29 @@ bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t curso
|
|||
}
|
||||
else
|
||||
{
|
||||
/* Command. */
|
||||
had_cmd = true;
|
||||
if (tok_pos == subcmd_tok_begin_offset)
|
||||
const wcstring potential_cmd = tok_last(&tok);
|
||||
if (parser_keywords_is_subcommand(potential_cmd))
|
||||
{
|
||||
/* This is the token we care about! */
|
||||
previous_token_is_cmd = true;
|
||||
if (potential_cmd == L"command" || potential_cmd == L"builtin")
|
||||
{
|
||||
/* 'command' and 'builtin' defeat abbreviation expansion. Skip this command. */
|
||||
had_cmd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other subcommand. Pretend it doesn't exist so that we can expand the following command */
|
||||
had_cmd = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's a normal command */
|
||||
had_cmd = true;
|
||||
if (tok_pos == subcmd_tok_begin_offset)
|
||||
{
|
||||
/* This is the token we care about! */
|
||||
previous_token_is_cmd = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -763,12 +776,13 @@ bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t curso
|
|||
return result;
|
||||
}
|
||||
|
||||
/* Expand abbreviations */
|
||||
bool reader_data_t::expand_abbreviation_as_necessary(void)
|
||||
/* Expand abbreviations. This may change the command line but does NOT repaint it. This is to allow the caller to coalesce repaints. */
|
||||
bool reader_data_t::expand_abbreviation_as_necessary()
|
||||
{
|
||||
bool result = false;
|
||||
if (this->expand_abbreviations)
|
||||
{
|
||||
/* Try expanding abbreviations */
|
||||
wcstring new_cmdline;
|
||||
if (reader_expand_abbreviation_in_command(this->command_line, this->buff_pos, &new_cmdline))
|
||||
{
|
||||
|
@ -776,11 +790,8 @@ bool reader_data_t::expand_abbreviation_as_necessary(void)
|
|||
size_t new_buff_pos = this->buff_pos + new_cmdline.size() - this->command_line.size();
|
||||
|
||||
this->command_line.swap(new_cmdline);
|
||||
data->command_line_changed();
|
||||
data->buff_pos = new_buff_pos;
|
||||
reader_super_highlight_me_plenty(data->buff_pos);
|
||||
reader_repaint();
|
||||
|
||||
data->command_line_changed();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
@ -3418,12 +3429,14 @@ const wchar_t *reader_readline(void)
|
|||
|
||||
/* See if this command is valid */
|
||||
int command_test_result = data->test_func(data->command_line.c_str());
|
||||
if (command_test_result == 0)
|
||||
if (command_test_result == 0 || command_test_result == PARSER_TEST_INCOMPLETE)
|
||||
{
|
||||
/* This command is valid, but an abbreviation may make it invalid. If so, we will have to test again. */
|
||||
bool abbreviation_expanded = data->expand_abbreviation_as_necessary();
|
||||
if (abbreviation_expanded)
|
||||
{
|
||||
/* It's our reponsibility to rehighlight and repaint. But everything we do below triggers a repaint. */
|
||||
reader_super_highlight_me_plenty(data->buff_pos);
|
||||
command_test_result = data->test_func(data->command_line.c_str());
|
||||
}
|
||||
}
|
||||
|
@ -3764,9 +3777,14 @@ const wchar_t *reader_readline(void)
|
|||
/* Other, if a normal character, we add it to the command */
|
||||
default:
|
||||
{
|
||||
|
||||
if ((!wchar_private(c)) && (((c>31) || (c==L'\n'))&& (c != 127)))
|
||||
{
|
||||
/* Expand abbreviations on space */
|
||||
if (c == L' ')
|
||||
{
|
||||
data->expand_abbreviation_as_necessary();
|
||||
}
|
||||
|
||||
/* Regular character */
|
||||
insert_char(c);
|
||||
}
|
||||
|
@ -3800,10 +3818,7 @@ const wchar_t *reader_readline(void)
|
|||
}
|
||||
|
||||
writestr(L"\n");
|
||||
/*
|
||||
if( comp )
|
||||
halloc_free( comp );
|
||||
*/
|
||||
|
||||
if (!reader_exit_forced())
|
||||
{
|
||||
if (tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
||||
|
|
Loading…
Reference in a new issue