aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/edit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r--src/nvim/edit.c113
1 files changed, 88 insertions, 25 deletions
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index c04190eaba..50c28dbaad 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -184,6 +184,16 @@ static expand_T compl_xp;
static int compl_opt_refresh_always = FALSE;
+static int pum_selected_item = -1;
+
+/// state for pum_ext_select_item.
+struct {
+ bool active;
+ int item;
+ bool insert;
+ bool finish;
+} pum_want;
+
typedef struct insert_state {
VimState state;
cmdarg_T *ca;
@@ -560,7 +570,7 @@ static int insert_check(VimState *state)
if (curwin->w_wcol < s->mincol - curbuf->b_p_ts
&& curwin->w_wrow == curwin->w_winrow
- + curwin->w_height - 1 - p_so
+ + curwin->w_grid.Rows - 1 - p_so
&& (curwin->w_cursor.lnum != curwin->w_topline
|| curwin->w_topfill > 0)) {
if (curwin->w_topfill > 0) {
@@ -976,10 +986,25 @@ static int insert_handle_key(InsertState *s)
case K_EVENT: // some event
multiqueue_process_events(main_loop.events);
- break;
+ goto check_pum;
case K_COMMAND: // some command
do_cmdline(NULL, getcmdkeycmd, NULL, 0);
+
+check_pum:
+ // TODO(bfredl): Not entirely sure this indirection is necessary
+ // but doing like this ensures using nvim_select_popupmenu_item is
+ // equivalent to selecting the item with a typed key.
+ if (pum_want.active) {
+ if (pum_visible()) {
+ insert_do_complete(s);
+ if (pum_want.finish) {
+ // accept the item and stop completion
+ ins_compl_prep(Ctrl_Y);
+ }
+ }
+ pum_want.active = false;
+ }
break;
case K_HOME: // <Home>
@@ -1494,40 +1519,41 @@ void edit_putchar(int c, int highlight)
{
int attr;
- if (ScreenLines != NULL) {
- update_topline(); /* just in case w_topline isn't valid */
+ if (curwin->w_grid.chars != NULL || default_grid.chars != NULL) {
+ update_topline(); // just in case w_topline isn't valid
validate_cursor();
if (highlight) {
attr = HL_ATTR(HLF_8);
} else {
attr = 0;
}
- pc_row = curwin->w_winrow + curwin->w_wrow;
- pc_col = curwin->w_wincol;
+ pc_row = curwin->w_wrow;
+ pc_col = 0;
pc_status = PC_STATUS_UNSET;
if (curwin->w_p_rl) {
- pc_col += curwin->w_width - 1 - curwin->w_wcol;
+ pc_col += curwin->w_grid.Columns - 1 - curwin->w_wcol;
if (has_mbyte) {
- int fix_col = mb_fix_col(pc_col, pc_row);
+ int fix_col = grid_fix_col(&curwin->w_grid, pc_col, pc_row);
if (fix_col != pc_col) {
- screen_putchar(' ', pc_row, fix_col, attr);
- --curwin->w_wcol;
+ grid_putchar(&curwin->w_grid, ' ', pc_row, fix_col, attr);
+ curwin->w_wcol--;
pc_status = PC_STATUS_RIGHT;
}
}
} else {
pc_col += curwin->w_wcol;
- if (mb_lefthalve(pc_row, pc_col))
+ if (grid_lefthalve(&curwin->w_grid, pc_row, pc_col)) {
pc_status = PC_STATUS_LEFT;
+ }
}
/* save the character to be able to put it back */
if (pc_status == PC_STATUS_UNSET) {
- screen_getbytes(pc_row, pc_col, pc_bytes, &pc_attr);
+ grid_getbytes(&curwin->w_grid, pc_row, pc_col, pc_bytes, &pc_attr);
pc_status = PC_STATUS_SET;
}
- screen_putchar(c, pc_row, pc_col, attr);
+ grid_putchar(&curwin->w_grid, c, pc_row, pc_col, attr);
}
}
@@ -1541,9 +1567,10 @@ void edit_unputchar(void)
curwin->w_wcol++;
}
if (pc_status == PC_STATUS_RIGHT || pc_status == PC_STATUS_LEFT) {
- redrawWinline(curwin, curwin->w_cursor.lnum, false);
+ redrawWinline(curwin, curwin->w_cursor.lnum);
} else {
- screen_puts(pc_bytes, pc_row - msg_scrolled, pc_col, pc_attr);
+ grid_puts(&curwin->w_grid, pc_bytes, pc_row - msg_scrolled, pc_col,
+ pc_attr);
}
}
}
@@ -1566,8 +1593,8 @@ void display_dollar(colnr_T col)
char_u *p = get_cursor_line_ptr();
curwin->w_cursor.col -= utf_head_off(p, p + col);
curs_columns(false); // Recompute w_wrow and w_wcol
- if (curwin->w_wcol < curwin->w_width) {
- edit_putchar('$', FALSE);
+ if (curwin->w_wcol < curwin->w_grid.Columns) {
+ edit_putchar('$', false);
dollar_vcol = curwin->w_virtcol;
}
curwin->w_cursor.col = save_col;
@@ -1581,7 +1608,7 @@ static void undisplay_dollar(void)
{
if (dollar_vcol >= 0) {
dollar_vcol = -1;
- redrawWinline(curwin, curwin->w_cursor.lnum, false);
+ redrawWinline(curwin, curwin->w_cursor.lnum);
}
}
@@ -2664,6 +2691,7 @@ void ins_compl_show_pum(void)
// Use the cursor to get all wrapping and other settings right.
col = curwin->w_cursor.col;
curwin->w_cursor.col = compl_col;
+ pum_selected_item = cur;
pum_display(compl_match_array, compl_match_arraysize, cur, array_changed);
curwin->w_cursor.col = col;
}
@@ -3518,6 +3546,7 @@ expand_by_function (
win_T *curwin_save;
buf_T *curbuf_save;
typval_T rettv;
+ const int save_State = State;
funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu;
if (*funcname == NUL)
@@ -3563,6 +3592,9 @@ expand_by_function (
ins_compl_add_dict(matchdict);
theend:
+ // Restore State, it might have been changed.
+ State = save_State;
+
if (matchdict != NULL) {
tv_dict_unref(matchdict);
}
@@ -4340,6 +4372,17 @@ ins_compl_next (
return num_matches;
}
+void pum_ext_select_item(int item, bool insert, bool finish)
+{
+ if (!pum_visible() || item < -1 || item >= compl_match_arraysize) {
+ return;
+ }
+ pum_want.active = true;
+ pum_want.item = item;
+ pum_want.insert = insert;
+ pum_want.finish = finish;
+}
+
// Call this while finding completions, to check whether the user has hit a key
// that should change the currently displayed completion, or exit completion
// mode. Also, when compl_pending is not zero, show a completion as soon as
@@ -4400,6 +4443,9 @@ void ins_compl_check_keys(int frequency, int in_compl_func)
*/
static int ins_compl_key2dir(int c)
{
+ if (c == K_EVENT || c == K_COMMAND) {
+ return pum_want.item < pum_selected_item ? BACKWARD : FORWARD;
+ }
if (c == Ctrl_P || c == Ctrl_L
|| c == K_PAGEUP || c == K_KPAGEUP
|| c == K_S_UP || c == K_UP) {
@@ -4427,6 +4473,11 @@ static int ins_compl_key2count(int c)
{
int h;
+ if (c == K_EVENT || c == K_COMMAND) {
+ int offset = pum_want.item - pum_selected_item;
+ return abs(offset);
+ }
+
if (ins_compl_pum_key(c) && c != K_UP && c != K_DOWN) {
h = pum_get_height();
if (h > 3)
@@ -4453,6 +4504,9 @@ static bool ins_compl_use_match(int c)
case K_KPAGEUP:
case K_S_UP:
return false;
+ case K_EVENT:
+ case K_COMMAND:
+ return pum_want.active && pum_want.insert;
}
return true;
}
@@ -4674,6 +4728,7 @@ static int ins_complete(int c, bool enable_pum)
pos_T pos;
win_T *curwin_save;
buf_T *curbuf_save;
+ const int save_State = State;
/* Call 'completefunc' or 'omnifunc' and get pattern length as a
* string */
@@ -4691,7 +4746,9 @@ static int ins_complete(int c, bool enable_pum)
pos = curwin->w_cursor;
curwin_save = curwin;
curbuf_save = curbuf;
- col = call_func_retnr(funcname, 2, args, FALSE);
+ col = call_func_retnr(funcname, 2, args, false);
+
+ State = save_State;
if (curwin_save != curwin || curbuf_save != curbuf) {
EMSG(_(e_complwin));
return FAIL;
@@ -5825,7 +5882,7 @@ static void check_auto_format(
/*
* Find out textwidth to be used for formatting:
* if 'textwidth' option is set, use it
- * else if 'wrapmargin' option is set, use curwin->w_width - 'wrapmargin'
+ * else if 'wrapmargin' option is set, use curwin->w_grid.Columns-'wrapmargin'
* if invalid value, use 0.
* Set default to window width (maximum 79) for "gq" operator.
*/
@@ -5840,9 +5897,10 @@ comp_textwidth (
if (textwidth == 0 && curbuf->b_p_wm) {
/* The width is the window width minus 'wrapmargin' minus all the
* things that add to the margin. */
- textwidth = curwin->w_width - curbuf->b_p_wm;
- if (cmdwin_type != 0)
+ textwidth = curwin->w_grid.Columns - curbuf->b_p_wm;
+ if (cmdwin_type != 0) {
textwidth -= 1;
+ }
textwidth -= curwin->w_p_fdc;
if (signcolumn_on(curwin)) {
@@ -5855,9 +5913,10 @@ comp_textwidth (
if (textwidth < 0)
textwidth = 0;
if (ff && textwidth == 0) {
- textwidth = curwin->w_width - 1;
- if (textwidth > 79)
+ textwidth = curwin->w_grid.Columns - 1;
+ if (textwidth > 79) {
textwidth = 79;
+ }
}
return textwidth;
}
@@ -5921,7 +5980,7 @@ static void check_spell_redraw(void)
linenr_T lnum = spell_redraw_lnum;
spell_redraw_lnum = 0;
- redrawWinline(curwin, lnum, false);
+ redrawWinline(curwin, lnum);
}
}
@@ -8663,6 +8722,7 @@ static colnr_T get_nolist_virtcol(void)
static char_u *do_insert_char_pre(int c)
{
char buf[MB_MAXBYTES + 1];
+ const int save_State = State;
// Return quickly when there is nothing to do.
if (!has_event(EVENT_INSERTCHARPRE)) {
@@ -8687,6 +8747,9 @@ static char_u *do_insert_char_pre(int c)
set_vim_var_string(VV_CHAR, NULL, -1);
textlock--;
+ // Restore the State, it may have been changed.
+ State = save_State;
+
return res;
}