Permalink
Browse files

forward-word should accept a word of an autosuggestion

  • Loading branch information...
1 parent 983bc5c commit eec6db0a2312e923f74402bb2e714f4bb331d9bd @ridiculousfish ridiculousfish committed Dec 11, 2012
Showing with 136 additions and 105 deletions.
  1. +4 −3 autoload.h
  2. +1 −1 builtin.cpp
  3. +29 −98 reader.cpp
  4. +5 −3 screen.cpp
  5. +79 −0 tokenizer.cpp
  6. +18 −0 tokenizer.h
View
@@ -34,9 +34,10 @@ struct autoload_function_t : public lru_node_t
bool is_internalized; /** Whether this function came from a builtin "internalized" script */
};
-struct builtin_script_t {
- const wchar_t *name;
- const char *def;
+struct builtin_script_t
+{
+ const wchar_t *name;
+ const char *def;
};
struct builtin_script_t;
View
@@ -461,7 +461,7 @@ static void builtin_bind_function_names()
/**
Add specified key binding.
*/
-static int builtin_bind_add(wchar_t *seq, wchar_t *cmd, int terminfo)
+static int builtin_bind_add(const wchar_t *seq, const wchar_t *cmd, int terminfo)
{
if (terminfo)
View
@@ -1283,13 +1283,29 @@ static void update_autosuggestion(void)
#endif
}
-static void accept_autosuggestion(void)
+/* Accept any autosuggestion by replacing the command line with it. If full is true, take the whole thing; if it's false, then take only the first "word" */
+static void accept_autosuggestion(bool full)
{
- /* Accept any autosuggestion by replacing the command line with it. */
if (! data->autosuggestion.empty())
{
/* Accept the autosuggestion */
- data->command_line = data->autosuggestion;
+ if (full)
+ {
+ /* Just take the whole thing */
+ data->command_line = data->autosuggestion;
+ }
+ else
+ {
+ /* Accept characters up to a word separator */
+ move_word_state_machine_t state;
+ for (size_t idx = data->command_line.size(); idx < data->autosuggestion.size(); idx++)
+ {
+ wchar_t wc = data->autosuggestion.at(idx);
+ if (! state.consume_char(wc))
+ break;
+ data->command_line.push_back(wc);
+ }
+ }
data->buff_pos = data->command_line.size();
data->command_line_changed();
reader_super_highlight_me_plenty(data->buff_pos);
@@ -2026,98 +2042,6 @@ static void handle_token_history(int forward, int reset)
}
}
-/* Our state machine that implements "one word" movement or erasure. */
-class move_word_state_machine_t
-{
- enum
- {
- s_whitespace,
- s_separator,
- s_slash,
- s_nonseparators_except_slash,
- s_end
- } state;
-
-public:
-
- move_word_state_machine_t() : state(s_whitespace)
- {
- }
-
- bool consume_char(wchar_t c)
- {
- //printf("state %d, consume '%lc'\n", state, c);
- bool consumed = false;
- /* Always treat separators as first. All this does is ensure that we treat ^ as a string character instead of as stderr redirection, which I hypothesize is usually what is desired. */
- bool was_first = true;
- while (state != s_end && ! consumed)
- {
- switch (state)
- {
- case s_whitespace:
- if (iswspace(c))
- {
- /* Consumed whitespace */
- consumed = true;
- }
- else if (tok_is_string_character(c, was_first))
- {
- /* String path */
- state = s_slash;
- }
- else
- {
- /* Separator path */
- state = s_separator;
- }
- break;
-
- case s_separator:
- if (! iswspace(c) && ! tok_is_string_character(c, was_first))
- {
- /* Consumed separator */
- consumed = true;
- }
- else
- {
- state = s_end;
- }
- break;
-
- case s_slash:
- if (c == L'/')
- {
- /* Consumed slash */
- consumed = true;
- }
- else
- {
- state = s_nonseparators_except_slash;
- }
- break;
-
- case s_nonseparators_except_slash:
- if (c != L'/' && tok_is_string_character(c, was_first))
- {
- /* Consumed string character except slash */
- consumed = true;
- }
- else
- {
- state = s_end;
- }
- break;
-
- /* We won't get here, but keep the compiler happy */
- case s_end:
- default:
- break;
- }
- }
- return consumed;
- }
-};
-
/**
Move buffer position one word or erase one word. This function
updates both the internal buffer and the screen. It is used by
@@ -3338,7 +3262,7 @@ const wchar_t *reader_readline()
}
else
{
- accept_autosuggestion();
+ accept_autosuggestion(true);
}
break;
}
@@ -3367,7 +3291,14 @@ const wchar_t *reader_readline()
/* move one word right*/
case R_FORWARD_WORD:
{
- move_word(MOVE_DIR_RIGHT, false /* do not erase */, false);
+ if (data->buff_pos < data->command_length())
+ {
+ move_word(MOVE_DIR_RIGHT, false /* do not erase */, false);
+ }
+ else
+ {
+ accept_autosuggestion(false /* accept only one word */);
+ }
break;
}
@@ -3440,7 +3371,7 @@ const wchar_t *reader_readline()
case R_ACCEPT_AUTOSUGGESTION:
{
- accept_autosuggestion();
+ accept_autosuggestion(true);
break;
}
View
@@ -566,9 +566,10 @@ static void s_move(screen_t *s, data_buffer_t *b, int new_x, int new_y)
{
if (s->actual.cursor.x == new_x && s->actual.cursor.y == new_y)
return;
-
+
// If we are at the end of our window, then either the cursor stuck to the edge or it didn't. We don't know! We can fix it up though.
- if (s->actual.cursor.x == common_get_width()) {
+ if (s->actual.cursor.x == common_get_width())
+ {
// Either issue a cr to go back to the beginning of this line, or a nl to go to the beginning of the next one, depending on what we think is more efficient
if (new_y <= s->actual.cursor.y)
{
@@ -887,7 +888,8 @@ static void s_update(screen_t *scr, const wchar_t *left_prompt, const wchar_t *r
}
/* If we're soft wrapped, and if we're going to change the first character of the next line, don't skip over the last two characters so that we maintain soft-wrapping */
- if (o_line.is_soft_wrapped && i + 1 < scr->desired.line_count()) {
+ if (o_line.is_soft_wrapped && i + 1 < scr->desired.line_count())
+ {
bool first_character_of_next_line_will_change = true;
if (i + 1 < scr->actual.line_count())
{
View
@@ -669,6 +669,85 @@ void tok_set_pos(tokenizer_t *tok, int pos)
}
+
+move_word_state_machine_t::move_word_state_machine_t() : state(s_whitespace)
+{
+}
+
+bool move_word_state_machine_t::consume_char(wchar_t c)
+{
+ //printf("state %d, consume '%lc'\n", state, c);
+ bool consumed = false;
+ /* Always treat separators as first. All this does is ensure that we treat ^ as a string character instead of as stderr redirection, which I hypothesize is usually what is desired. */
+ bool was_first = true;
+ while (state != s_end && ! consumed)
+ {
+ switch (state)
+ {
+ case s_whitespace:
+ if (iswspace(c))
+ {
+ /* Consumed whitespace */
+ consumed = true;
+ }
+ else if (tok_is_string_character(c, was_first))
+ {
+ /* String path */
+ state = s_slash;
+ }
+ else
+ {
+ /* Separator path */
+ state = s_separator;
+ }
+ break;
+
+ case s_separator:
+ if (! iswspace(c) && ! tok_is_string_character(c, was_first))
+ {
+ /* Consumed separator */
+ consumed = true;
+ }
+ else
+ {
+ state = s_end;
+ }
+ break;
+
+ case s_slash:
+ if (c == L'/')
+ {
+ /* Consumed slash */
+ consumed = true;
+ }
+ else
+ {
+ state = s_nonseparators_except_slash;
+ }
+ break;
+
+ case s_nonseparators_except_slash:
+ if (c != L'/' && tok_is_string_character(c, was_first))
+ {
+ /* Consumed string character except slash */
+ consumed = true;
+ }
+ else
+ {
+ state = s_end;
+ }
+ break;
+
+ /* We won't get here, but keep the compiler happy */
+ case s_end:
+ default:
+ break;
+ }
+ }
+ return consumed;
+}
+
+
#ifdef TOKENIZER_TEST
/**
View
@@ -184,4 +184,22 @@ const wchar_t *tok_get_desc(int type);
int tok_get_error(tokenizer_t *tok);
+/* Our state machine that implements "one word" movement or erasure. */
+class move_word_state_machine_t
+{
+ enum
+ {
+ s_whitespace,
+ s_separator,
+ s_slash,
+ s_nonseparators_except_slash,
+ s_end
+ } state;
+
+public:
+ move_word_state_machine_t();
+ bool consume_char(wchar_t c);
+};
+
+
#endif

0 comments on commit eec6db0

Please sign in to comment.