diff options
Diffstat (limited to 'src/nvim/edit.c')
-rw-r--r-- | src/nvim/edit.c | 113 |
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; } |