mirror of
https://github.com/neovim/neovim.git
synced 2025-10-06 01:46:29 +00:00
vim-patch:8.1.0027: difficult to make a plugin that feeds a line to a job
Problem: Difficult to make a plugin that feeds a line to a job.
Solution: Add the nitial code for the "prompt" buftype.
f273245f64
This commit is contained in:
@@ -763,6 +763,8 @@ static void free_buffer(buf_T *buf)
|
||||
unref_var_dict(buf->b_vars);
|
||||
aubuflocal_remove(buf);
|
||||
tv_dict_unref(buf->additional_data);
|
||||
xfree(buf->b_prompt_text);
|
||||
callback_free(&buf->b_prompt_callback);
|
||||
clear_fmark(&buf->b_last_cursor);
|
||||
clear_fmark(&buf->b_last_insert);
|
||||
clear_fmark(&buf->b_last_change);
|
||||
@@ -1876,6 +1878,9 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
buf->b_prompt_callback.type = kCallbackNone;
|
||||
buf->b_prompt_text = NULL;
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
@@ -4824,6 +4829,12 @@ do_arg_all(
|
||||
xfree(opened);
|
||||
}
|
||||
|
||||
// Return TRUE if "buf" is a prompt buffer.
|
||||
int bt_prompt(buf_T *buf)
|
||||
{
|
||||
return buf != NULL && buf->b_p_bt[0] == 'p';
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a window for a number of buffers.
|
||||
*/
|
||||
@@ -5218,14 +5229,18 @@ bool bt_nofile(const buf_T *const buf)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
return buf != NULL && ((buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f')
|
||||
|| buf->b_p_bt[0] == 'a' || buf->terminal);
|
||||
|| buf->b_p_bt[0] == 'a'
|
||||
|| buf->terminal
|
||||
|| buf->b_p_bt[0] == 'p');
|
||||
}
|
||||
|
||||
// Return true if "buf" is a "nowrite", "nofile" or "terminal" buffer.
|
||||
bool bt_dontwrite(const buf_T *const buf)
|
||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
return buf != NULL && (buf->b_p_bt[0] == 'n' || buf->terminal);
|
||||
return buf != NULL && (buf->b_p_bt[0] == 'n'
|
||||
|| buf->terminal
|
||||
|| buf->b_p_bt[0] == 'p');
|
||||
}
|
||||
|
||||
bool bt_dontwrite_msg(const buf_T *const buf)
|
||||
|
@@ -791,6 +791,9 @@ struct file_buffer {
|
||||
// are not used! Use the B_SPELL macro to
|
||||
// access b_spell without #ifdef.
|
||||
|
||||
char_u *b_prompt_text; // set by prompt_setprompt()
|
||||
Callback b_prompt_callback; // set by prompt_setcallback()
|
||||
|
||||
synblock_T b_s; // Info related to syntax highlighting. w_s
|
||||
// normally points to this, but some windows
|
||||
// may use a different synblock_T.
|
||||
|
@@ -2432,6 +2432,10 @@ void nv_diffgetput(bool put, size_t count)
|
||||
exarg_T ea;
|
||||
char buf[30];
|
||||
|
||||
if (bt_prompt(curbuf)) {
|
||||
vim_beep(BO_OPER);
|
||||
return;
|
||||
}
|
||||
if (count == 0) {
|
||||
ea.arg = (char_u *)"";
|
||||
} else {
|
||||
|
@@ -574,6 +574,12 @@ static int insert_check(VimState *state)
|
||||
foldCheckClose();
|
||||
}
|
||||
|
||||
int cmdchar_todo = s->cmdchar;
|
||||
if (bt_prompt(curbuf)) {
|
||||
init_prompt(cmdchar_todo);
|
||||
cmdchar_todo = NUL;
|
||||
}
|
||||
|
||||
// If we inserted a character at the last position of the last line in the
|
||||
// window, scroll the window one line up. This avoids an extra redraw. This
|
||||
// is detected when the cursor column is smaller after inserting something.
|
||||
@@ -1143,6 +1149,14 @@ check_pum:
|
||||
cmdwin_result = CAR;
|
||||
return 0;
|
||||
}
|
||||
if (bt_prompt(curbuf)) {
|
||||
invoke_prompt_callback();
|
||||
if (curbuf != buf) {
|
||||
// buffer changed, get out of Insert mode
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!ins_eol(s->c) && !p_im) {
|
||||
return 0; // out of memory
|
||||
}
|
||||
@@ -1569,6 +1583,50 @@ void edit_putchar(int c, int highlight)
|
||||
}
|
||||
}
|
||||
|
||||
// Return the effective prompt for the current buffer.
|
||||
char_u *prompt_text(void)
|
||||
{
|
||||
if (curbuf->b_prompt_text == NULL) {
|
||||
return (char_u *)"% ";
|
||||
}
|
||||
return curbuf->b_prompt_text;
|
||||
}
|
||||
|
||||
// Prepare for prompt mode: Make sure the last line has the prompt text.
|
||||
// Move the cursor to this line.
|
||||
static void init_prompt(int cmdchar_todo)
|
||||
{
|
||||
char_u *prompt = prompt_text();
|
||||
char_u *text;
|
||||
|
||||
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
|
||||
text = get_cursor_line_ptr();
|
||||
if (STRNCMP(text, prompt, STRLEN(prompt)) != 0) {
|
||||
// prompt is missing, insert it or append a line with it
|
||||
if (*text == NUL) {
|
||||
ml_replace(curbuf->b_ml.ml_line_count, prompt, true);
|
||||
} else {
|
||||
ml_append(curbuf->b_ml.ml_line_count, prompt, 0, false);
|
||||
}
|
||||
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
|
||||
coladvance((colnr_T)MAXCOL);
|
||||
changed_bytes(curbuf->b_ml.ml_line_count, 0);
|
||||
}
|
||||
if (cmdchar_todo == 'A') {
|
||||
coladvance((colnr_T)MAXCOL);
|
||||
}
|
||||
if (cmdchar_todo == 'I' || curwin->w_cursor.col <= (int)STRLEN(prompt)) {
|
||||
curwin->w_cursor.col = STRLEN(prompt);
|
||||
}
|
||||
}
|
||||
|
||||
// Return TRUE if the cursor is in the editable position of the prompt line.
|
||||
int prompt_curpos_editable(void)
|
||||
{
|
||||
return curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count
|
||||
&& curwin->w_cursor.col >= (int)STRLEN(prompt_text());
|
||||
}
|
||||
|
||||
/*
|
||||
* Undo the previous edit_putchar().
|
||||
*/
|
||||
|
@@ -13687,3 +13687,34 @@ void ex_checkhealth(exarg_T *eap)
|
||||
|
||||
xfree(buf);
|
||||
}
|
||||
|
||||
void invoke_prompt_callback(void)
|
||||
{
|
||||
typval_T rettv;
|
||||
typval_T argv[2];
|
||||
char_u *text;
|
||||
char_u *prompt;
|
||||
linenr_T lnum = curbuf->b_ml.ml_line_count;
|
||||
|
||||
// Add a new line for the prompt before invoking the callback, so that
|
||||
// text can always be inserted above the last line.
|
||||
ml_append(lnum, (char_u *)"", 0, false);
|
||||
curwin->w_cursor.lnum = lnum + 1;
|
||||
curwin->w_cursor.col = 0;
|
||||
|
||||
if (curbuf->b_prompt_callback.type == kCallbackNone) {
|
||||
return;
|
||||
}
|
||||
text = ml_get(lnum);
|
||||
prompt = prompt_text();
|
||||
if (STRLEN(text) >= STRLEN(prompt)) {
|
||||
text += STRLEN(prompt);
|
||||
}
|
||||
argv[0].v_type = VAR_STRING;
|
||||
argv[0].vval.v_string = vim_strsave(text);
|
||||
argv[1].v_type = VAR_UNKNOWN;
|
||||
|
||||
callback_call(&curbuf->b_prompt_callback, 1, argv, &rettv);
|
||||
tv_clear(&argv[0]);
|
||||
tv_clear(&rettv);
|
||||
}
|
||||
|
@@ -243,6 +243,8 @@ return {
|
||||
pow={args=2},
|
||||
prevnonblank={args=1},
|
||||
printf={args=varargs(1)},
|
||||
prompt_setcallback={args={2, 2}},
|
||||
prompt_setprompt={args={2, 2}},
|
||||
pum_getpos={},
|
||||
pumvisible={},
|
||||
py3eval={args=1},
|
||||
|
@@ -6076,6 +6076,51 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
}
|
||||
}
|
||||
|
||||
// "prompt_setcallback({buffer}, {callback})" function
|
||||
static void f_prompt_setcallback(typval_T *argvars,
|
||||
typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
buf_T *buf;
|
||||
Callback prompt_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(&prompt_callback, &argvars[1])) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
callback_free(&buf->b_prompt_callback);
|
||||
buf->b_prompt_callback = prompt_callback;
|
||||
}
|
||||
|
||||
// "prompt_setprompt({buffer}, {text})" function
|
||||
static void f_prompt_setprompt(typval_T *argvars,
|
||||
typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
buf_T *buf;
|
||||
const char_u *text;
|
||||
|
||||
if (check_secure()) {
|
||||
return;
|
||||
}
|
||||
buf = tv_get_buf(&argvars[0], false);
|
||||
if (buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
text = (const char_u *)tv_get_string(&argvars[1]);
|
||||
xfree(buf->b_prompt_text);
|
||||
buf->b_prompt_text = vim_strsave(text);
|
||||
}
|
||||
|
||||
// "pum_getpos()" function
|
||||
static void f_pum_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
|
@@ -3642,7 +3642,9 @@ static void nv_help(cmdarg_T *cap)
|
||||
*/
|
||||
static void nv_addsub(cmdarg_T *cap)
|
||||
{
|
||||
if (!VIsual_active && cap->oap->op_type == OP_NOP) {
|
||||
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||
clearopbeep(cap->oap);
|
||||
} else if (!VIsual_active && cap->oap->op_type == OP_NOP) {
|
||||
prep_redo_cmd(cap);
|
||||
cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
|
||||
op_addsub(cap->oap, cap->count1, cap->arg);
|
||||
@@ -5239,6 +5241,13 @@ static void nv_down(cmdarg_T *cap)
|
||||
// In the cmdline window a <CR> executes the command.
|
||||
if (cmdwin_type != 0 && cap->cmdchar == CAR) {
|
||||
cmdwin_result = CAR;
|
||||
} else if (bt_prompt(curbuf) && cap->cmdchar == CAR
|
||||
&& curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) {
|
||||
// In a prompt buffer a <CR> in the last line invokes the callback.
|
||||
invoke_prompt_callback();
|
||||
if (restart_edit == 0) {
|
||||
restart_edit = 'a';
|
||||
}
|
||||
} else {
|
||||
cap->oap->motion_type = kMTLineWise;
|
||||
if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == false) {
|
||||
@@ -5831,6 +5840,10 @@ static void nv_undo(cmdarg_T *cap)
|
||||
static void nv_kundo(cmdarg_T *cap)
|
||||
{
|
||||
if (!checkclearopq(cap->oap)) {
|
||||
if (bt_prompt(curbuf)) {
|
||||
clearopbeep(cap->oap);
|
||||
return;
|
||||
}
|
||||
u_undo((int)cap->count1);
|
||||
curwin->w_set_curswant = true;
|
||||
}
|
||||
@@ -5844,8 +5857,13 @@ static void nv_replace(cmdarg_T *cap)
|
||||
char_u *ptr;
|
||||
int had_ctrl_v;
|
||||
|
||||
if (checkclearop(cap->oap))
|
||||
if (checkclearop(cap->oap)) {
|
||||
return;
|
||||
}
|
||||
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||
clearopbeep(cap->oap);
|
||||
return;
|
||||
}
|
||||
|
||||
/* get another character */
|
||||
if (cap->nchar == Ctrl_V) {
|
||||
@@ -6182,7 +6200,11 @@ static void v_visop(cmdarg_T *cap)
|
||||
*/
|
||||
static void nv_subst(cmdarg_T *cap)
|
||||
{
|
||||
if (VIsual_active) { /* "vs" and "vS" are the same as "vc" */
|
||||
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||
clearopbeep(cap->oap);
|
||||
return;
|
||||
}
|
||||
if (VIsual_active) { // "vs" and "vS" are the same as "vc"
|
||||
if (cap->cmdchar == 'S') {
|
||||
VIsual_mode_orig = VIsual_mode;
|
||||
VIsual_mode = 'V';
|
||||
@@ -7120,10 +7142,15 @@ static void nv_tilde(cmdarg_T *cap)
|
||||
{
|
||||
if (!p_to
|
||||
&& !VIsual_active
|
||||
&& cap->oap->op_type != OP_TILDE)
|
||||
&& cap->oap->op_type != OP_TILDE) {
|
||||
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||
clearopbeep(cap->oap);
|
||||
return;
|
||||
}
|
||||
n_swapchar(cap);
|
||||
else
|
||||
} else {
|
||||
nv_operator(cap);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -7136,6 +7163,12 @@ static void nv_operator(cmdarg_T *cap)
|
||||
|
||||
op_type = get_op_type(cap->cmdchar, cap->nchar);
|
||||
|
||||
if (bt_prompt(curbuf) && op_is_change(op_type)
|
||||
&& !prompt_curpos_editable()) {
|
||||
clearopbeep(cap->oap);
|
||||
return;
|
||||
}
|
||||
|
||||
if (op_type == cap->oap->op_type) /* double operator works on lines */
|
||||
nv_lineop(cap);
|
||||
else if (!checkclearop(cap->oap)) {
|
||||
@@ -7796,8 +7829,11 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
|
||||
clearop(cap->oap);
|
||||
assert(cap->opcount >= 0);
|
||||
nv_diffgetput(true, (size_t)cap->opcount);
|
||||
} else
|
||||
} else {
|
||||
clearopbeep(cap->oap);
|
||||
}
|
||||
} else if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||
clearopbeep(cap->oap);
|
||||
} else {
|
||||
if (fix_indent) {
|
||||
dir = (cap->cmdchar == ']' && cap->nchar == 'p')
|
||||
@@ -7809,8 +7845,9 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
|
||||
? BACKWARD : FORWARD;
|
||||
}
|
||||
prep_redo_cmd(cap);
|
||||
if (cap->cmdchar == 'g')
|
||||
if (cap->cmdchar == 'g') {
|
||||
flags |= PUT_CURSEND;
|
||||
}
|
||||
|
||||
if (VIsual_active) {
|
||||
/* Putting in Visual mode: The put text replaces the selected
|
||||
@@ -7916,10 +7953,14 @@ static void nv_open(cmdarg_T *cap)
|
||||
clearop(cap->oap);
|
||||
assert(cap->opcount >= 0);
|
||||
nv_diffgetput(false, (size_t)cap->opcount);
|
||||
} else if (VIsual_active) /* switch start and end of visual */
|
||||
} else if (VIsual_active) {
|
||||
// switch start and end of visual/
|
||||
v_swap_corners(cap->cmdchar);
|
||||
else
|
||||
} else if (bt_prompt(curbuf)) {
|
||||
clearopbeep(cap->oap);
|
||||
} else {
|
||||
n_opencmd(cap);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate start/end virtual columns for operating in block mode.
|
||||
|
@@ -89,6 +89,10 @@ struct block_def {
|
||||
# include "ops.c.generated.h"
|
||||
#endif
|
||||
|
||||
// Flags for third item in "opchars".
|
||||
#define OPF_LINES 1 // operator always works on lines
|
||||
#define OPF_CHANGE 2 // operator changes text
|
||||
|
||||
/*
|
||||
* The names of operators.
|
||||
* IMPORTANT: Index must correspond with defines in vim.h!!!
|
||||
@@ -96,36 +100,36 @@ struct block_def {
|
||||
*/
|
||||
static char opchars[][3] =
|
||||
{
|
||||
{ NUL, NUL, false }, // OP_NOP
|
||||
{ 'd', NUL, false }, // OP_DELETE
|
||||
{ 'y', NUL, false }, // OP_YANK
|
||||
{ 'c', NUL, false }, // OP_CHANGE
|
||||
{ '<', NUL, true }, // OP_LSHIFT
|
||||
{ '>', NUL, true }, // OP_RSHIFT
|
||||
{ '!', NUL, true }, // OP_FILTER
|
||||
{ 'g', '~', false }, // OP_TILDE
|
||||
{ '=', NUL, true }, // OP_INDENT
|
||||
{ 'g', 'q', true }, // OP_FORMAT
|
||||
{ ':', NUL, true }, // OP_COLON
|
||||
{ 'g', 'U', false }, // OP_UPPER
|
||||
{ 'g', 'u', false }, // OP_LOWER
|
||||
{ 'J', NUL, true }, // DO_JOIN
|
||||
{ 'g', 'J', true }, // DO_JOIN_NS
|
||||
{ 'g', '?', false }, // OP_ROT13
|
||||
{ 'r', NUL, false }, // OP_REPLACE
|
||||
{ 'I', NUL, false }, // OP_INSERT
|
||||
{ 'A', NUL, false }, // OP_APPEND
|
||||
{ 'z', 'f', true }, // OP_FOLD
|
||||
{ 'z', 'o', true }, // OP_FOLDOPEN
|
||||
{ 'z', 'O', true }, // OP_FOLDOPENREC
|
||||
{ 'z', 'c', true }, // OP_FOLDCLOSE
|
||||
{ 'z', 'C', true }, // OP_FOLDCLOSEREC
|
||||
{ 'z', 'd', true }, // OP_FOLDDEL
|
||||
{ 'z', 'D', true }, // OP_FOLDDELREC
|
||||
{ 'g', 'w', true }, // OP_FORMAT2
|
||||
{ 'g', '@', false }, // OP_FUNCTION
|
||||
{ Ctrl_A, NUL, false }, // OP_NR_ADD
|
||||
{ Ctrl_X, NUL, false }, // OP_NR_SUB
|
||||
{ NUL, NUL, 0 }, // OP_NOP
|
||||
{ 'd', NUL, OPF_CHANGE }, // OP_DELETE
|
||||
{ 'y', NUL, 0 }, // OP_YANK
|
||||
{ 'c', NUL, OPF_CHANGE }, // OP_CHANGE
|
||||
{ '<', NUL, OPF_LINES | OPF_CHANGE }, // OP_LSHIFT
|
||||
{ '>', NUL, OPF_LINES | OPF_CHANGE }, // OP_RSHIFT
|
||||
{ '!', NUL, OPF_LINES | OPF_CHANGE }, // OP_FILTER
|
||||
{ 'g', '~', OPF_CHANGE }, // OP_TILDE
|
||||
{ '=', NUL, OPF_LINES | OPF_CHANGE }, // OP_INDENT
|
||||
{ 'g', 'q', OPF_LINES | OPF_CHANGE }, // OP_FORMAT
|
||||
{ ':', NUL, OPF_LINES }, // OP_COLON
|
||||
{ 'g', 'U', OPF_CHANGE }, // OP_UPPER
|
||||
{ 'g', 'u', OPF_CHANGE }, // OP_LOWER
|
||||
{ 'J', NUL, OPF_LINES | OPF_CHANGE }, // DO_JOIN
|
||||
{ 'g', 'J', OPF_LINES | OPF_CHANGE }, // DO_JOIN_NS
|
||||
{ 'g', '?', OPF_CHANGE }, // OP_ROT13
|
||||
{ 'r', NUL, OPF_CHANGE }, // OP_REPLACE
|
||||
{ 'I', NUL, OPF_CHANGE }, // OP_INSERT
|
||||
{ 'A', NUL, OPF_CHANGE }, // OP_APPEND
|
||||
{ 'z', 'f', OPF_LINES }, // OP_FOLD
|
||||
{ 'z', 'o', OPF_LINES }, // OP_FOLDOPEN
|
||||
{ 'z', 'O', OPF_LINES }, // OP_FOLDOPENREC
|
||||
{ 'z', 'c', OPF_LINES }, // OP_FOLDCLOSE
|
||||
{ 'z', 'C', OPF_LINES }, // OP_FOLDCLOSEREC
|
||||
{ 'z', 'd', OPF_LINES }, // OP_FOLDDEL
|
||||
{ 'z', 'D', OPF_LINES }, // OP_FOLDDELREC
|
||||
{ 'g', 'w', OPF_LINES | OPF_CHANGE }, // OP_FORMAT2
|
||||
{ 'g', '@', OPF_CHANGE }, // OP_FUNCTION
|
||||
{ Ctrl_A, NUL, OPF_CHANGE }, // OP_NR_ADD
|
||||
{ Ctrl_X, NUL, OPF_CHANGE }, // OP_NR_SUB
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -169,7 +173,13 @@ int get_op_type(int char1, int char2)
|
||||
*/
|
||||
int op_on_lines(int op)
|
||||
{
|
||||
return opchars[op][2];
|
||||
return opchars[op][2] & OPF_LINES;
|
||||
}
|
||||
|
||||
// Return TRUE if operator "op" changes text.
|
||||
int op_is_change(int op)
|
||||
{
|
||||
return opchars[op][2] & OPF_CHANGE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -299,7 +299,8 @@ static char *(p_scbopt_values[]) = { "ver", "hor", "jump", NULL };
|
||||
static char *(p_debug_values[]) = { "msg", "throw", "beep", NULL };
|
||||
static char *(p_ead_values[]) = { "both", "ver", "hor", NULL };
|
||||
static char *(p_buftype_values[]) = { "nofile", "nowrite", "quickfix",
|
||||
"help", "acwrite", "terminal", NULL };
|
||||
"help", "acwrite", "terminal",
|
||||
"prompt", NULL };
|
||||
|
||||
static char *(p_bufhidden_values[]) = { "hide", "unload", "delete",
|
||||
"wipe", NULL };
|
||||
|
Reference in New Issue
Block a user