mirror of
https://github.com/neovim/neovim.git
synced 2025-09-30 23:18:33 +00:00
Allow using internal popupmenu or ext_popupmenu for wildmenu
Deprecate ext_wildmenu. ext_popupmenu already contains more state (anchor position), and will allow further expansion (info about items).
This commit is contained in:
@@ -34,6 +34,7 @@ typedef struct {
|
||||
|
||||
// Position of legacy cursor, used both for drawing and visible user cursor.
|
||||
Integer client_row, client_col;
|
||||
bool wildmenu_active;
|
||||
} UIData;
|
||||
|
||||
static PMap(uint64_t) *connected_uis = NULL;
|
||||
@@ -146,6 +147,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
|
||||
data->buffer = (Array)ARRAY_DICT_INIT;
|
||||
data->hl_id = 0;
|
||||
data->client_col = -1;
|
||||
data->wildmenu_active = false;
|
||||
ui->data = data;
|
||||
|
||||
pmap_put(uint64_t)(connected_uis, channel_id, ui);
|
||||
@@ -586,6 +588,7 @@ static Array translate_firstarg(UI *ui, Array args)
|
||||
|
||||
static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
|
||||
{
|
||||
UIData *data = ui->data;
|
||||
if (!ui->ui_ext[kUILinegrid]) {
|
||||
// the representation of highlights in cmdline changed, translate back
|
||||
// never consumes args
|
||||
@@ -611,6 +614,39 @@ static void remote_ui_event(UI *ui, char *name, Array args, bool *args_consumed)
|
||||
}
|
||||
}
|
||||
|
||||
// Back-compat: translate popupmenu_xx to legacy wildmenu_xx.
|
||||
if (ui->ui_ext[kUIWildmenu]) {
|
||||
if (strequal(name, "popupmenu_show")) {
|
||||
data->wildmenu_active = (args.items[4].data.integer == -1)
|
||||
|| !ui->ui_ext[kUIPopupmenu];
|
||||
if (data->wildmenu_active) {
|
||||
Array new_args = ARRAY_DICT_INIT;
|
||||
Array items = args.items[0].data.array;
|
||||
Array new_items = ARRAY_DICT_INIT;
|
||||
for (size_t i = 0; i < items.size; i++) {
|
||||
ADD(new_items, copy_object(items.items[i].data.array.items[0]));
|
||||
}
|
||||
ADD(new_args, ARRAY_OBJ(new_items));
|
||||
push_call(ui, "wildmenu_show", new_args);
|
||||
if (args.items[1].data.integer != -1) {
|
||||
Array new_args2 = ARRAY_DICT_INIT;
|
||||
ADD(new_args2, args.items[1]);
|
||||
push_call(ui, "wildmenu_select", new_args);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (strequal(name, "popupmenu_select")) {
|
||||
if (data->wildmenu_active) {
|
||||
name = "wildmenu_select";
|
||||
}
|
||||
} else if (strequal(name, "popupmenu_hide")) {
|
||||
if (data->wildmenu_active) {
|
||||
name = "wildmenu_hide";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Array my_args = ARRAY_DICT_INIT;
|
||||
// Objects are currently single-reference
|
||||
// make a copy, but only if necessary
|
||||
|
@@ -143,11 +143,11 @@ void cmdline_block_hide(void)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
|
||||
void wildmenu_show(Array items)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
|
||||
void wildmenu_select(Integer selected)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
|
||||
void wildmenu_hide(void)
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_ONLY;
|
||||
FUNC_API_SINCE(3) FUNC_API_REMOTE_IMPL FUNC_API_BRIDGE_IMPL;
|
||||
|
||||
void msg_show(String kind, Array content, Boolean replace_last)
|
||||
FUNC_API_SINCE(6) FUNC_API_REMOTE_ONLY;
|
||||
|
@@ -2656,7 +2656,7 @@ void ins_compl_show_pum(void)
|
||||
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);
|
||||
pum_display(compl_match_array, compl_match_arraysize, cur, array_changed, 0);
|
||||
curwin->w_cursor.col = col;
|
||||
|
||||
if (!has_event(EVENT_MENUPOPUPCHANGED)) {
|
||||
|
@@ -3235,7 +3235,7 @@ const char * set_one_cmd_context(
|
||||
case CMD_tjump:
|
||||
case CMD_stjump:
|
||||
case CMD_ptjump:
|
||||
if (*p_wop != NUL) {
|
||||
if (wop_flags & WOP_TAGFILE) {
|
||||
xp->xp_context = EXPAND_TAGS_LISTFILES;
|
||||
} else {
|
||||
xp->xp_context = EXPAND_TAGS;
|
||||
|
@@ -214,6 +214,15 @@ static int hislen = 0; /* actual length of history tables */
|
||||
/// user interrupting highlight function to not interrupt command-line.
|
||||
static bool getln_interrupted_highlight = false;
|
||||
|
||||
// "compl_match_array" points the currently displayed list of entries in the
|
||||
// popup menu. It is NULL when there is no popup menu.
|
||||
static pumitem_T *compl_match_array = NULL;
|
||||
static int compl_match_arraysize;
|
||||
// First column in cmdline of the matched item for completion.
|
||||
static int compl_startcol;
|
||||
static int compl_selected;
|
||||
|
||||
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ex_getln.c.generated.h"
|
||||
@@ -600,6 +609,13 @@ static int command_line_execute(VimState *state, int key)
|
||||
} else if (s->c == K_RIGHT) {
|
||||
s->c = Ctrl_N;
|
||||
}
|
||||
if (compl_match_array) {
|
||||
if (s->c == K_UP) {
|
||||
s->c = Ctrl_P;
|
||||
} else if (s->c == K_DOWN) {
|
||||
s->c = Ctrl_N;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hitting CR after "emenu Name.": complete submenu
|
||||
@@ -615,8 +631,10 @@ static int command_line_execute(VimState *state, int key)
|
||||
if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm
|
||||
&& s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
|
||||
&& s->c != Ctrl_L) {
|
||||
if (ui_has(kUIWildmenu)) {
|
||||
ui_call_wildmenu_hide();
|
||||
if (compl_match_array) {
|
||||
pum_undisplay(true);
|
||||
xfree(compl_match_array);
|
||||
compl_match_array = NULL;
|
||||
}
|
||||
if (s->xpc.xp_numfiles != -1) {
|
||||
(void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE);
|
||||
@@ -3746,13 +3764,12 @@ ExpandOne (
|
||||
else
|
||||
findex = -1;
|
||||
}
|
||||
if (p_wmnu) {
|
||||
if (ui_has(kUIWildmenu)) {
|
||||
ui_call_wildmenu_select(findex);
|
||||
} else {
|
||||
win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files,
|
||||
findex, cmd_showtail);
|
||||
}
|
||||
if (compl_match_array) {
|
||||
compl_selected = findex;
|
||||
cmdline_pum_display(false);
|
||||
} else if (p_wmnu) {
|
||||
win_redr_status_matches(xp, xp->xp_numfiles, xp->xp_files,
|
||||
findex, cmd_showtail);
|
||||
}
|
||||
if (findex == -1) {
|
||||
return vim_strsave(orig_save);
|
||||
@@ -4069,6 +4086,12 @@ void tilde_replace(char_u *orig_pat, int num_files, char_u **files)
|
||||
}
|
||||
}
|
||||
|
||||
void cmdline_pum_display(bool changed_array)
|
||||
{
|
||||
pum_display(compl_match_array, compl_match_arraysize, compl_selected,
|
||||
changed_array, compl_startcol);
|
||||
}
|
||||
|
||||
/*
|
||||
* Show all matches for completion on the command line.
|
||||
* Returns EXPAND_NOTHING when the character that triggered expansion should
|
||||
@@ -4102,12 +4125,28 @@ static int showmatches(expand_T *xp, int wildmenu)
|
||||
showtail = cmd_showtail;
|
||||
}
|
||||
|
||||
if (ui_has(kUIWildmenu)) {
|
||||
Array args = ARRAY_DICT_INIT;
|
||||
bool compl_use_pum = (ui_has(kUICmdline)
|
||||
? ui_has(kUIPopupmenu)
|
||||
: wildmenu && (wop_flags & WOP_PUM))
|
||||
|| ui_has(kUIWildmenu);
|
||||
|
||||
if (compl_use_pum) {
|
||||
compl_match_arraysize = num_files;
|
||||
compl_match_array = xcalloc(compl_match_arraysize, sizeof(pumitem_T));
|
||||
for (i = 0; i < num_files; i++) {
|
||||
ADD(args, STRING_OBJ(cstr_to_string((char *)files_found[i])));
|
||||
compl_match_array[i].pum_text = L_SHOWFILE(i);
|
||||
}
|
||||
ui_call_wildmenu_show(args);
|
||||
ssize_t offset = showtail ? sm_gettail(xp->xp_pattern)-xp->xp_pattern : 0;
|
||||
if (ui_has(kUICmdline)) {
|
||||
compl_startcol = ccline.cmdpos - strnlen((char *)xp->xp_pattern+offset,
|
||||
xp->xp_pattern_len-offset);
|
||||
} else {
|
||||
compl_startcol = ccline.cmdspos
|
||||
- mb_string2cells_len(xp->xp_pattern+offset,
|
||||
xp->xp_pattern_len-offset);
|
||||
}
|
||||
compl_selected = -1;
|
||||
cmdline_pum_display(true);
|
||||
return EXPAND_OK;
|
||||
}
|
||||
|
||||
|
@@ -555,6 +555,24 @@ size_t mb_string2cells(const char_u *str)
|
||||
return clen;
|
||||
}
|
||||
|
||||
/// Get the number of cells occupied by string `str` with maximum length `size`
|
||||
///
|
||||
/// @param str The source string, may not be NULL, must be a NUL-terminated
|
||||
/// string.
|
||||
/// @param size maximum length of string. It will terminate on earlier NUL.
|
||||
/// @return The number of cells occupied by string `str`
|
||||
size_t mb_string2cells_len(const char_u *str, size_t size)
|
||||
{
|
||||
size_t clen = 0;
|
||||
|
||||
for (const char_u *p = str; *p != NUL && p < str+size;
|
||||
p += utf_ptr2len_len(p, size+(p-str))) {
|
||||
clen += utf_ptr2cells(p);
|
||||
}
|
||||
|
||||
return clen;
|
||||
}
|
||||
|
||||
/// Convert a UTF-8 byte sequence to a wide character
|
||||
///
|
||||
/// If the sequence is illegal or truncated by a NUL then the first byte is
|
||||
|
@@ -284,7 +284,6 @@ static char *(p_ambw_values[]) = { "single", "double", NULL };
|
||||
static char *(p_bg_values[]) = { "light", "dark", NULL };
|
||||
static char *(p_nf_values[]) = { "bin", "octal", "hex", "alpha", NULL };
|
||||
static char *(p_ff_values[]) = { FF_UNIX, FF_DOS, FF_MAC, NULL };
|
||||
static char *(p_wop_values[]) = { "tagfile", NULL };
|
||||
static char *(p_wak_values[]) = { "yes", "menu", "no", NULL };
|
||||
static char *(p_mousem_values[]) = { "extend", "popup", "popup_setpos",
|
||||
"mac", NULL };
|
||||
@@ -2608,11 +2607,11 @@ ambw_end:
|
||||
else if (varp == &p_wim) {
|
||||
if (check_opt_wim() == FAIL)
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
/* 'wildoptions' */
|
||||
else if (varp == &p_wop) {
|
||||
if (check_opt_strings(p_wop, p_wop_values, TRUE) != OK)
|
||||
// 'wildoptions'
|
||||
} else if (varp == &p_wop) {
|
||||
if (opt_strings_flags(p_wop, p_wop_values, &wop_flags, true) != OK) {
|
||||
errmsg = e_invarg;
|
||||
}
|
||||
}
|
||||
/* 'winaltkeys' */
|
||||
else if (varp == &p_wak) {
|
||||
|
@@ -659,6 +659,12 @@ extern char_u *p_vfile; /* 'verbosefile' */
|
||||
#endif
|
||||
EXTERN int p_warn; // 'warn'
|
||||
EXTERN char_u *p_wop; // 'wildoptions'
|
||||
EXTERN unsigned wop_flags;
|
||||
# ifdef IN_OPTION_C
|
||||
static char *(p_wop_values[]) = { "tagfile", "pum", NULL };
|
||||
#endif
|
||||
#define WOP_TAGFILE 0x01
|
||||
#define WOP_PUM 0x02
|
||||
EXTERN long p_window; // 'window'
|
||||
EXTERN char_u *p_wak; // 'winaltkeys'
|
||||
EXTERN char_u *p_wig; // 'wildignore'
|
||||
|
@@ -2699,7 +2699,7 @@ return {
|
||||
},
|
||||
{
|
||||
full_name='wildoptions', abbreviation='wop',
|
||||
type='string', scope={'global'},
|
||||
type='string', list='onecomma', scope={'global'},
|
||||
vi_def=true,
|
||||
varname='p_wop',
|
||||
defaults={if_true={vi=""}}
|
||||
|
@@ -66,7 +66,9 @@ static bool pum_invalid = false; // the screen was just cleared
|
||||
/// @param array_changed if true, array contains different items since last call
|
||||
/// if false, a new item is selected, but the array
|
||||
/// is the same
|
||||
void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
|
||||
/// @param cmd_startcol only for cmdline mode: column of completed match
|
||||
void pum_display(pumitem_T *array, int size, int selected, bool array_changed,
|
||||
int cmd_startcol)
|
||||
{
|
||||
int w;
|
||||
int def_width;
|
||||
@@ -84,7 +86,8 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
|
||||
if (!pum_is_visible) {
|
||||
// To keep the code simple, we only allow changing the
|
||||
// draw mode when the popup menu is not being displayed
|
||||
pum_external = ui_has(kUIPopupmenu);
|
||||
pum_external = ui_has(kUIPopupmenu)
|
||||
|| (State == CMDLINE && ui_has(kUIWildmenu));
|
||||
}
|
||||
|
||||
do {
|
||||
@@ -96,19 +99,26 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed)
|
||||
above_row = 0;
|
||||
below_row = cmdline_row;
|
||||
|
||||
// anchor position: the start of the completed word
|
||||
row = curwin->w_wrow;
|
||||
if (curwin->w_p_rl) {
|
||||
col = curwin->w_width - curwin->w_wcol - 1;
|
||||
// wildoptions=pum
|
||||
if (State == CMDLINE) {
|
||||
row = ui_has(kUICmdline) ? 0 : cmdline_row;
|
||||
col = cmd_startcol;
|
||||
pum_anchor_grid = ui_has(kUICmdline) ? -1 : DEFAULT_GRID_HANDLE;
|
||||
} else {
|
||||
col = curwin->w_wcol;
|
||||
}
|
||||
// anchor position: the start of the completed word
|
||||
row = curwin->w_wrow;
|
||||
if (curwin->w_p_rl) {
|
||||
col = curwin->w_width - curwin->w_wcol - 1;
|
||||
} else {
|
||||
col = curwin->w_wcol;
|
||||
}
|
||||
|
||||
pum_anchor_grid = (int)curwin->w_grid.handle;
|
||||
if (!ui_has(kUIMultigrid)) {
|
||||
pum_anchor_grid = (int)default_grid.handle;
|
||||
row += curwin->w_winrow;
|
||||
col += curwin->w_wincol;
|
||||
pum_anchor_grid = (int)curwin->w_grid.handle;
|
||||
if (!ui_has(kUIMultigrid)) {
|
||||
pum_anchor_grid = (int)default_grid.handle;
|
||||
row += curwin->w_winrow;
|
||||
col += curwin->w_wincol;
|
||||
}
|
||||
}
|
||||
|
||||
if (pum_external) {
|
||||
|
@@ -7151,8 +7151,12 @@ void screen_resize(int width, int height)
|
||||
if (curwin->w_p_scb)
|
||||
do_check_scrollbind(TRUE);
|
||||
if (State & CMDLINE) {
|
||||
redraw_popupmenu = false;
|
||||
update_screen(NOT_VALID);
|
||||
redrawcmdline();
|
||||
if (pum_drawn()) {
|
||||
cmdline_pum_display(false);
|
||||
}
|
||||
} else {
|
||||
update_topline();
|
||||
if (pum_drawn()) {
|
||||
|
Reference in New Issue
Block a user