version 1.224, 2021/06/10 07:50:04 |
version 1.225, 2021/06/10 07:56:47 |
|
|
*new_key = KEYC_BSPACE; |
*new_key = KEYC_BSPACE; |
return (1); |
return (1); |
case 'b': |
case 'b': |
case 'B': |
|
*new_key = 'b'|KEYC_META; |
*new_key = 'b'|KEYC_META; |
return (1); |
return (1); |
|
case 'B': |
|
*new_key = 'B'|KEYC_VI; |
|
return (1); |
case 'd': |
case 'd': |
*new_key = '\025'; |
*new_key = '\025'; |
return (1); |
return (1); |
case 'e': |
case 'e': |
|
*new_key = 'e'|KEYC_VI; |
|
return (1); |
case 'E': |
case 'E': |
|
*new_key = 'E'|KEYC_VI; |
|
return (1); |
case 'w': |
case 'w': |
|
*new_key = 'w'|KEYC_VI; |
|
return (1); |
case 'W': |
case 'W': |
*new_key = 'f'|KEYC_META; |
*new_key = 'W'|KEYC_VI; |
return (1); |
return (1); |
case 'p': |
case 'p': |
*new_key = '\031'; /* C-y */ |
*new_key = '\031'; /* C-y */ |
|
|
return (1); |
return (1); |
} |
} |
|
|
|
/* Prompt forward to the next beginning of a word. */ |
|
static void |
|
status_prompt_forward_word(struct client *c, size_t size, int vi, |
|
const char *separators) |
|
{ |
|
size_t idx = c->prompt_index; |
|
int word_is_separators; |
|
|
|
/* In emacs mode, skip until the first non-whitespace character. */ |
|
if (!vi) |
|
while (idx != size && |
|
status_prompt_space(&c->prompt_buffer[idx])) |
|
idx++; |
|
|
|
/* Can't move forward if we're already at the end. */ |
|
if (idx == size) { |
|
c->prompt_index = idx; |
|
return; |
|
} |
|
|
|
/* Determine the current character class (separators or not). */ |
|
word_is_separators = status_prompt_in_list(separators, |
|
&c->prompt_buffer[idx]) && |
|
!status_prompt_space(&c->prompt_buffer[idx]); |
|
|
|
/* Skip ahead until the first space or opposite character class. */ |
|
do { |
|
idx++; |
|
if (status_prompt_space(&c->prompt_buffer[idx])) { |
|
/* In vi mode, go to the start of the next word. */ |
|
if (vi) |
|
while (idx != size && |
|
status_prompt_space(&c->prompt_buffer[idx])) |
|
idx++; |
|
break; |
|
} |
|
} while (idx != size && word_is_separators == status_prompt_in_list( |
|
separators, &c->prompt_buffer[idx])); |
|
|
|
c->prompt_index = idx; |
|
} |
|
|
|
/* Prompt forward to the next end of a word. */ |
|
static void |
|
status_prompt_end_word(struct client *c, size_t size, const char *separators) |
|
{ |
|
size_t idx = c->prompt_index; |
|
int word_is_separators; |
|
|
|
/* Can't move forward if we're already at the end. */ |
|
if (idx == size) |
|
return; |
|
|
|
/* Find the next word. */ |
|
do { |
|
idx++; |
|
if (idx == size) { |
|
c->prompt_index = idx; |
|
return; |
|
} |
|
} while (status_prompt_space(&c->prompt_buffer[idx])); |
|
|
|
/* Determine the character class (separators or not). */ |
|
word_is_separators = status_prompt_in_list(separators, |
|
&c->prompt_buffer[idx]); |
|
|
|
/* Skip ahead until the next space or opposite character class. */ |
|
do { |
|
idx++; |
|
if (idx == size) |
|
break; |
|
} while (!status_prompt_space(&c->prompt_buffer[idx]) && |
|
word_is_separators == status_prompt_in_list(separators, |
|
&c->prompt_buffer[idx])); |
|
|
|
/* Back up to the previous character to stop at the end of the word. */ |
|
c->prompt_index = idx - 1; |
|
} |
|
|
|
/* Prompt backward to the previous beginning of a word. */ |
|
static void |
|
status_prompt_backward_word(struct client *c, const char *separators) |
|
{ |
|
size_t idx = c->prompt_index; |
|
int word_is_separators; |
|
|
|
/* Find non-whitespace. */ |
|
while (idx != 0) { |
|
--idx; |
|
if (!status_prompt_space(&c->prompt_buffer[idx])) |
|
break; |
|
} |
|
word_is_separators = status_prompt_in_list(separators, |
|
&c->prompt_buffer[idx]); |
|
|
|
/* Find the character before the beginning of the word. */ |
|
while (idx != 0) { |
|
--idx; |
|
if (status_prompt_space(&c->prompt_buffer[idx]) || |
|
word_is_separators != status_prompt_in_list(separators, |
|
&c->prompt_buffer[idx])) { |
|
/* Go back to the word. */ |
|
idx++; |
|
break; |
|
} |
|
} |
|
c->prompt_index = idx; |
|
} |
|
|
/* Handle keys in prompt. */ |
/* Handle keys in prompt. */ |
int |
int |
status_prompt_key(struct client *c, key_code key) |
status_prompt_key(struct client *c, key_code key) |
{ |
{ |
struct options *oo = c->session->options; |
struct options *oo = c->session->options; |
char *s, *cp, prefix = '='; |
char *s, *cp, prefix = '='; |
const char *histstr, *ws = NULL, *keystring; |
const char *histstr, *separators = NULL, *keystring; |
size_t size, idx; |
size_t size, idx; |
struct utf8_data tmp; |
struct utf8_data tmp; |
int keys; |
int keys, word_is_separators; |
|
|
if (c->prompt_flags & PROMPT_KEY) { |
if (c->prompt_flags & PROMPT_KEY) { |
keystring = key_string_lookup_key(key, 0); |
keystring = key_string_lookup_key(key, 0); |
|
|
} |
} |
break; |
break; |
case '\027': /* C-w */ |
case '\027': /* C-w */ |
ws = options_get_string(oo, "word-separators"); |
separators = options_get_string(oo, "word-separators"); |
idx = c->prompt_index; |
idx = c->prompt_index; |
|
|
/* Find a non-separator. */ |
/* Find non-whitespace. */ |
while (idx != 0) { |
while (idx != 0) { |
idx--; |
idx--; |
if (!status_prompt_in_list(ws, &c->prompt_buffer[idx])) |
if (!status_prompt_space(&c->prompt_buffer[idx])) |
break; |
break; |
} |
} |
|
word_is_separators = status_prompt_in_list(separators, |
|
&c->prompt_buffer[idx]); |
|
|
/* Find the separator at the beginning of the word. */ |
/* Find the character before the beginning of the word. */ |
while (idx != 0) { |
while (idx != 0) { |
idx--; |
idx--; |
if (status_prompt_in_list(ws, &c->prompt_buffer[idx])) { |
if (status_prompt_space(&c->prompt_buffer[idx]) || |
|
word_is_separators != status_prompt_in_list( |
|
separators, &c->prompt_buffer[idx])) { |
/* Go back to the word. */ |
/* Go back to the word. */ |
idx++; |
idx++; |
break; |
break; |
|
|
c->prompt_index = idx; |
c->prompt_index = idx; |
|
|
goto changed; |
goto changed; |
case 'f'|KEYC_META: |
|
case KEYC_RIGHT|KEYC_CTRL: |
case KEYC_RIGHT|KEYC_CTRL: |
ws = options_get_string(oo, "word-separators"); |
case 'f'|KEYC_META: |
|
separators = options_get_string(oo, "word-separators"); |
/* Find a word. */ |
status_prompt_forward_word(c, size, 0, separators); |
while (c->prompt_index != size) { |
|
idx = ++c->prompt_index; |
|
if (!status_prompt_in_list(ws, &c->prompt_buffer[idx])) |
|
break; |
|
} |
|
|
|
/* Find the separator at the end of the word. */ |
|
while (c->prompt_index != size) { |
|
idx = ++c->prompt_index; |
|
if (status_prompt_in_list(ws, &c->prompt_buffer[idx])) |
|
break; |
|
} |
|
|
|
/* Back up to the end-of-word like vi. */ |
|
if (options_get_number(oo, "status-keys") == MODEKEY_VI && |
|
c->prompt_index != 0) |
|
c->prompt_index--; |
|
|
|
goto changed; |
goto changed; |
case 'b'|KEYC_META: |
case 'E'|KEYC_VI: |
|
status_prompt_end_word(c, size, ""); |
|
goto changed; |
|
case 'e'|KEYC_VI: |
|
separators = options_get_string(oo, "word-separators"); |
|
status_prompt_end_word(c, size, separators); |
|
goto changed; |
|
case 'W'|KEYC_VI: |
|
status_prompt_forward_word(c, size, 1, ""); |
|
goto changed; |
|
case 'w'|KEYC_VI: |
|
separators = options_get_string(oo, "word-separators"); |
|
status_prompt_forward_word(c, size, 1, separators); |
|
goto changed; |
|
case 'B'|KEYC_VI: |
|
status_prompt_backward_word(c, ""); |
|
goto changed; |
case KEYC_LEFT|KEYC_CTRL: |
case KEYC_LEFT|KEYC_CTRL: |
ws = options_get_string(oo, "word-separators"); |
case 'b'|KEYC_META: |
|
separators = options_get_string(oo, "word-separators"); |
/* Find a non-separator. */ |
status_prompt_backward_word(c, separators); |
while (c->prompt_index != 0) { |
|
idx = --c->prompt_index; |
|
if (!status_prompt_in_list(ws, &c->prompt_buffer[idx])) |
|
break; |
|
} |
|
|
|
/* Find the separator at the beginning of the word. */ |
|
while (c->prompt_index != 0) { |
|
idx = --c->prompt_index; |
|
if (status_prompt_in_list(ws, &c->prompt_buffer[idx])) { |
|
/* Go back to the word. */ |
|
c->prompt_index++; |
|
break; |
|
} |
|
} |
|
goto changed; |
goto changed; |
case KEYC_UP: |
case KEYC_UP: |
case '\020': /* C-p */ |
case '\020': /* C-p */ |
|
|
return (0); |
return (0); |
if (key <= 0x7f) |
if (key <= 0x7f) |
utf8_set(&tmp, key); |
utf8_set(&tmp, key); |
else |
else if (KEYC_IS_UNICODE(key)) |
utf8_to_data(key, &tmp); |
utf8_to_data(key, &tmp); |
|
else |
|
return (0); |
|
|
c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2, |
c->prompt_buffer = xreallocarray(c->prompt_buffer, size + 2, |
sizeof *c->prompt_buffer); |
sizeof *c->prompt_buffer); |