diff --git a/input.cpp b/input.cpp index d08f9d600..f3d752a90 100644 --- a/input.cpp +++ b/input.cpp @@ -114,6 +114,7 @@ static const wchar_t * const name_arr[] = L"history-token-search-forward", L"self-insert", L"transpose-chars", + L"transpose-words", L"null", L"eof", L"vi-arg-digit", @@ -199,6 +200,7 @@ static const wchar_t code_arr[] = R_HISTORY_TOKEN_SEARCH_FORWARD, R_SELF_INSERT, R_TRANSPOSE_CHARS, + R_TRANSPOSE_WORDS, R_NULL, R_EOF, R_VI_ARG_DIGIT, diff --git a/input.h b/input.h index a5df1a8b3..465d50473 100644 --- a/input.h +++ b/input.h @@ -43,6 +43,7 @@ enum R_HISTORY_TOKEN_SEARCH_FORWARD, R_SELF_INSERT, R_TRANSPOSE_CHARS, + R_TRANSPOSE_WORDS, R_VI_ARG_DIGIT, R_VI_DELETE_TO, R_EXECUTE, diff --git a/reader.cpp b/reader.cpp index 6184c75ea..da4a6e003 100644 --- a/reader.cpp +++ b/reader.cpp @@ -3553,6 +3553,46 @@ const wchar_t *reader_readline(void) break; } + case R_TRANSPOSE_WORDS: + { + size_t orig_pos = data->buff_pos; + size_t len = data->command_length(); + const wchar_t *buff = data->command_line.c_str(); + const wchar_t *tok_begin, *tok_end, *prev_begin, *prev_end; + + /* If we are not in a token, look for one ahead */ + while (data->buff_pos != len && !iswalnum(buff[data->buff_pos])) + data->buff_pos++; + + parse_util_token_extent(buff, data->buff_pos, &tok_begin, &tok_end, &prev_begin, &prev_end); + + /* In case we didn't find a token at or after the cursor... */ + if (tok_begin == &buff[len]) + { + /* ...retry beginning from the previous token */ + size_t pos = prev_end - &buff[0]; + parse_util_token_extent(buff, pos, &tok_begin, &tok_end, &prev_begin, &prev_end); + } + + /* Make sure we have two tokens */ + if (prev_begin < prev_end && tok_begin < tok_end && tok_begin > prev_begin) + { + wcstring prev(prev_begin, prev_end - prev_begin); + wcstring sep(prev_end, tok_begin - prev_end); + wcstring tok(tok_begin, tok_end - tok_begin); + wcstring trail(tok_end, &buff[len] - tok_end); + + /* Compose new command line with swapped tokens */ + wcstring new_buff(buff, prev_begin - buff); + new_buff.append(tok); + new_buff.append(sep); + new_buff.append(prev); + new_buff.append(trail); + set_command_line_and_position(new_buff, orig_pos); + } + break; + } + /* Other, if a normal character, we add it to the command */ default: { diff --git a/share/functions/fish_default_key_bindings.fish b/share/functions/fish_default_key_bindings.fish index a01579bab..fe3dc5d37 100644 --- a/share/functions/fish_default_key_bindings.fish +++ b/share/functions/fish_default_key_bindings.fish @@ -68,6 +68,7 @@ function fish_default_key_bindings -d "Default (Emacs-like) key bindings for fis bind \cf forward-char bind \cb backward-char bind \ct transpose-chars + bind \et transpose-words bind \e\x7f backward-kill-word bind \eb backward-word bind \ef forward-word