vim-patch:8.1.0069: cannot handle pressing CTRL-C in a prompt buffer

Problem:    Cannot handle pressing CTRL-C in a prompt buffer.
Solution:   Add prompt_setinterrupt().
0e5979a6d4
This commit is contained in:
erw7 2019-05-23 06:38:02 +09:00
parent 783aecd501
commit fe395ae210
6 changed files with 77 additions and 10 deletions

View File

@ -2281,8 +2281,9 @@ pow({x}, {y}) Float {x} to the power of {y}
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
printf({fmt}, {expr1}...) String format text
prompt_addtext({buf}, {expr}) none add text to a prompt buffer
prompt_setprompt({buf}, {text}) none set prompt text
prompt_setcallback({buf}, {expr}) none set prompt callback function
prompt_setinterrupt({buf}, {text}) none set prompt interrupt function
prompt_setprompt({buf}, {text}) none set prompt text
pum_getpos() Dict position and size of pum if visible
pumvisible() Number whether popup menu is visible
pyeval({expr}) any evaluate |Python| expression
@ -6544,17 +6545,11 @@ printf({fmt}, {expr1} ...) *printf()*
of "%" items. If there are not sufficient or too many
arguments an error is given. Up to 18 arguments can be used.
prompt_setprompt({buf}, {text}) *prompt_setprompt()*
Set prompt for buffer {buf} to {text}. You most likely want
{text} to end in a space.
The result is only visible if {buf} has 'buftype' set to
"prompt". Example: >
call prompt_setprompt(bufnr(''), 'command: ')
prompt_setcallback({buf}, {expr}) *prompt_setcallback()*
Set prompt callback for buffer {buf} to {expr}. This has only
Set prompt callback for buffer {buf} to {expr}. When {expr}
is an empty string the callback is removed. This has only
effect if {buf} has 'buftype' set to "prompt".
The callback is invoked when pressing Enter. The current
buffer will always be the prompt buffer. A new line for a
prompt is added before invoking the callback, thus the prompt
@ -6579,6 +6574,22 @@ prompt_setcallback({buf}, {expr}) *prompt_setcallback()*
endif
endfunc
prompt_setinterrupt({buf}, {expr}) *prompt_setinterrupt()*
Set a callback for buffer {buf} to {expr}. When {expr} is an
empty string the callback is removed. This has only effect if
{buf} has 'buftype' set to "prompt".
This callback will be invoked when pressing CTRL-C in Insert
mode. Without setting a callback Vim will exit Insert mode,
as in any buffer.
prompt_setprompt({buf}, {text}) *prompt_setprompt()*
Set prompt for buffer {buf} to {text}. You most likely want
{text} to end in a space.
The result is only visible if {buf} has 'buftype' set to
"prompt". Example: >
call prompt_setprompt(bufnr(''), 'command: ')
pum_getpos() *pum_getpos()*
If the popup menu (see |ins-completion-menu|) is not visible,
returns an empty |Dictionary|, otherwise, returns a
@ -6591,6 +6602,7 @@ pum_getpos() *pum_getpos()*
scrollbar |TRUE| if visible
The values are the same as in |v:event| during |CompleteChanged|.
pumvisible() *pumvisible()*
Returns non-zero when the popup menu is visible, zero
otherwise. See |ins-completion-menu|.

View File

@ -765,6 +765,7 @@ static void free_buffer(buf_T *buf)
tv_dict_unref(buf->additional_data);
xfree(buf->b_prompt_text);
callback_free(&buf->b_prompt_callback);
callback_free(&buf->b_prompt_interrupt);
clear_fmark(&buf->b_last_cursor);
clear_fmark(&buf->b_last_insert);
clear_fmark(&buf->b_last_change);
@ -1879,6 +1880,7 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
}
buf->b_prompt_callback.type = kCallbackNone;
buf->b_prompt_interrupt.type = kCallbackNone;
buf->b_prompt_text = NULL;
return buf;

View File

@ -823,6 +823,16 @@ static int insert_handle_key(InsertState *s)
s->nomove = true;
return 0; // exit insert mode
}
if (s->c == Ctrl_C && bt_prompt(curbuf)) {
if (invoke_prompt_interrupt()) {
if (!bt_prompt(curbuf)) {
// buffer changed to a non-prompt buffer, get out of
// Insert mode
return 0;
}
break;
}
}
// when 'insertmode' set, and not halfway through a mapping, don't leave
// Insert mode

View File

@ -13718,3 +13718,20 @@ void invoke_prompt_callback(void)
tv_clear(&argv[0]);
tv_clear(&rettv);
}
// Return true When the interrupt callback was invoked.
bool invoke_prompt_interrupt(void)
{
typval_T rettv;
typval_T argv[1];
if (curbuf->b_prompt_interrupt.type == kCallbackNone) {
return false;
}
argv[0].v_type = VAR_UNKNOWN;
got_int = false; // don't skip executing commands
callback_call(&curbuf->b_prompt_interrupt, 0, argv, &rettv);
tv_clear(&rettv);
return true;
}

View File

@ -244,6 +244,7 @@ return {
prevnonblank={args=1},
printf={args=varargs(1)},
prompt_setcallback={args={2, 2}},
prompt_setinterrupt={args={2, 2}},
prompt_setprompt={args={2, 2}},
pum_getpos={},
pumvisible={},

View File

@ -6101,6 +6101,31 @@ static void f_prompt_setcallback(typval_T *argvars,
buf->b_prompt_callback = prompt_callback;
}
// "prompt_setinterrupt({buffer}, {callback})" function
static void f_prompt_setinterrupt(typval_T *argvars,
typval_T *rettv, FunPtr fptr)
{
buf_T *buf;
Callback interrupt_callback = { .type = kCallbackNone };
if (check_secure()) {
return;
}
buf = tv_get_buf(&argvars[0], false);
if (buf == NULL) {
return;
}
if (argvars[1].v_type != VAR_STRING || *argvars[1].vval.v_string != NUL) {
if (!callback_from_typval(&interrupt_callback, &argvars[1])) {
return;
}
}
callback_free(&buf->b_prompt_interrupt);
buf->b_prompt_interrupt= interrupt_callback;
}
// "prompt_setprompt({buffer}, {text})" function
static void f_prompt_setprompt(typval_T *argvars,
typval_T *rettv, FunPtr fptr)