mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.2.1587: loop for handling keys for the command line is too long (#19868)
Problem: Loop for handling keys for the command line is too long.
Solution: Move wild menu handling to separate functions. (Yegappan
Lakshmanan, closes vim/vim#6856)
eadee486c7
This commit is contained in:
parent
741ef87876
commit
61ff37952a
@ -10,6 +10,7 @@
|
|||||||
#include "nvim/charset.h"
|
#include "nvim/charset.h"
|
||||||
#include "nvim/cmdexpand.h"
|
#include "nvim/cmdexpand.h"
|
||||||
#include "nvim/cmdhist.h"
|
#include "nvim/cmdhist.h"
|
||||||
|
#include "nvim/drawscreen.h"
|
||||||
#include "nvim/eval.h"
|
#include "nvim/eval.h"
|
||||||
#include "nvim/eval/funcs.h"
|
#include "nvim/eval/funcs.h"
|
||||||
#include "nvim/eval/userfunc.h"
|
#include "nvim/eval/userfunc.h"
|
||||||
@ -40,6 +41,7 @@
|
|||||||
#include "nvim/ui.h"
|
#include "nvim/ui.h"
|
||||||
#include "nvim/usercmd.h"
|
#include "nvim/usercmd.h"
|
||||||
#include "nvim/vim.h"
|
#include "nvim/vim.h"
|
||||||
|
#include "nvim/window.h"
|
||||||
|
|
||||||
/// Type used by ExpandGeneric()
|
/// Type used by ExpandGeneric()
|
||||||
typedef char *(*CompleteListItemGetter)(expand_T *, int);
|
typedef char *(*CompleteListItemGetter)(expand_T *, int);
|
||||||
@ -53,15 +55,13 @@ typedef void *(*user_expand_func_T)(const char_u *, int, typval_T *);
|
|||||||
|
|
||||||
static int cmd_showtail; ///< Only show path tail in lists ?
|
static int cmd_showtail; ///< Only show path tail in lists ?
|
||||||
|
|
||||||
// TODO(zeertzjq): make these four variables static in cmdexpand.c
|
|
||||||
|
|
||||||
/// "compl_match_array" points the currently displayed list of entries in the
|
/// "compl_match_array" points the currently displayed list of entries in the
|
||||||
/// popup menu. It is NULL when there is no popup menu.
|
/// popup menu. It is NULL when there is no popup menu.
|
||||||
pumitem_T *compl_match_array = NULL;
|
pumitem_T *compl_match_array = NULL; // TODO(zeertzjq): make this static in cmdexpand.c
|
||||||
int compl_match_arraysize;
|
static int compl_match_arraysize;
|
||||||
/// First column in cmdline of the matched item for completion.
|
/// First column in cmdline of the matched item for completion.
|
||||||
int compl_startcol;
|
static int compl_startcol;
|
||||||
int compl_selected;
|
static int compl_selected;
|
||||||
|
|
||||||
static int sort_func_compare(const void *s1, const void *s2)
|
static int sort_func_compare(const void *s1, const void *s2)
|
||||||
{
|
{
|
||||||
@ -2509,6 +2509,227 @@ void globpath(char *path, char_u *file, garray_T *ga, int expand_options)
|
|||||||
xfree(buf);
|
xfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Translate some keys pressed when 'wildmenu' is used.
|
||||||
|
int wildmenu_translate_key(CmdlineInfo *cclp, int key, expand_T *xp, int did_wild_list)
|
||||||
|
{
|
||||||
|
int c = key;
|
||||||
|
|
||||||
|
if (did_wild_list && p_wmnu) {
|
||||||
|
if (c == K_LEFT) {
|
||||||
|
c = Ctrl_P;
|
||||||
|
} else if (c == K_RIGHT) {
|
||||||
|
c = Ctrl_N;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Hitting CR after "emenu Name.": complete submenu
|
||||||
|
if (xp->xp_context == EXPAND_MENUNAMES && p_wmnu
|
||||||
|
&& cclp->cmdpos > 1
|
||||||
|
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.'
|
||||||
|
&& cclp->cmdbuff[cclp->cmdpos - 2] != '\\'
|
||||||
|
&& (c == '\n' || c == '\r' || c == K_KENTER)) {
|
||||||
|
c = K_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Delete characters on the command line, from "from" to the current position.
|
||||||
|
static void cmdline_del(CmdlineInfo *cclp, int from)
|
||||||
|
{
|
||||||
|
assert(cclp->cmdpos <= cclp->cmdlen);
|
||||||
|
memmove(cclp->cmdbuff + from, cclp->cmdbuff + cclp->cmdpos,
|
||||||
|
(size_t)cclp->cmdlen - (size_t)cclp->cmdpos + 1);
|
||||||
|
cclp->cmdlen -= cclp->cmdpos - from;
|
||||||
|
cclp->cmdpos = from;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle a key pressed when wild menu is displayed
|
||||||
|
int wildmenu_process_key(CmdlineInfo *cclp, int key, expand_T *xp)
|
||||||
|
{
|
||||||
|
int c = key;
|
||||||
|
|
||||||
|
if (!p_wmnu) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special translations for 'wildmenu'
|
||||||
|
if (xp->xp_context == EXPAND_MENUNAMES) {
|
||||||
|
// Hitting <Down> after "emenu Name.": complete submenu
|
||||||
|
if (c == K_DOWN && cclp->cmdpos > 0
|
||||||
|
&& cclp->cmdbuff[cclp->cmdpos - 1] == '.') {
|
||||||
|
c = (int)p_wc;
|
||||||
|
KeyTyped = true; // in case the key was mapped
|
||||||
|
} else if (c == K_UP) {
|
||||||
|
// Hitting <Up>: Remove one submenu name in front of the
|
||||||
|
// cursor
|
||||||
|
int found = false;
|
||||||
|
|
||||||
|
int j = (int)((char_u *)xp->xp_pattern - cclp->cmdbuff);
|
||||||
|
int i = 0;
|
||||||
|
while (--j > 0) {
|
||||||
|
// check for start of menu name
|
||||||
|
if (cclp->cmdbuff[j] == ' '
|
||||||
|
&& cclp->cmdbuff[j - 1] != '\\') {
|
||||||
|
i = j + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for start of submenu name
|
||||||
|
if (cclp->cmdbuff[j] == '.'
|
||||||
|
&& cclp->cmdbuff[j - 1] != '\\') {
|
||||||
|
if (found) {
|
||||||
|
i = j + 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
cmdline_del(cclp, i);
|
||||||
|
}
|
||||||
|
c = (int)p_wc;
|
||||||
|
KeyTyped = true; // in case the key was mapped
|
||||||
|
xp->xp_context = EXPAND_NOTHING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xp->xp_context == EXPAND_FILES
|
||||||
|
|| xp->xp_context == EXPAND_DIRECTORIES
|
||||||
|
|| xp->xp_context == EXPAND_SHELLCMD) {
|
||||||
|
char_u upseg[5];
|
||||||
|
|
||||||
|
upseg[0] = PATHSEP;
|
||||||
|
upseg[1] = '.';
|
||||||
|
upseg[2] = '.';
|
||||||
|
upseg[3] = PATHSEP;
|
||||||
|
upseg[4] = NUL;
|
||||||
|
|
||||||
|
if (c == K_DOWN
|
||||||
|
&& cclp->cmdpos > 0
|
||||||
|
&& cclp->cmdbuff[cclp->cmdpos - 1] == PATHSEP
|
||||||
|
&& (cclp->cmdpos < 3
|
||||||
|
|| cclp->cmdbuff[cclp->cmdpos - 2] != '.'
|
||||||
|
|| cclp->cmdbuff[cclp->cmdpos - 3] != '.')) {
|
||||||
|
// go down a directory
|
||||||
|
c = (int)p_wc;
|
||||||
|
KeyTyped = true; // in case the key was mapped
|
||||||
|
} else if (STRNCMP(xp->xp_pattern, upseg + 1, 3) == 0
|
||||||
|
&& c == K_DOWN) {
|
||||||
|
// If in a direct ancestor, strip off one ../ to go down
|
||||||
|
int found = false;
|
||||||
|
|
||||||
|
int j = cclp->cmdpos;
|
||||||
|
int i = (int)((char_u *)xp->xp_pattern - cclp->cmdbuff);
|
||||||
|
while (--j > i) {
|
||||||
|
j -= utf_head_off(cclp->cmdbuff, cclp->cmdbuff + j);
|
||||||
|
if (vim_ispathsep(cclp->cmdbuff[j])) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found
|
||||||
|
&& cclp->cmdbuff[j - 1] == '.'
|
||||||
|
&& cclp->cmdbuff[j - 2] == '.'
|
||||||
|
&& (vim_ispathsep(cclp->cmdbuff[j - 3]) || j == i + 2)) {
|
||||||
|
cmdline_del(cclp, j - 2);
|
||||||
|
c = (int)p_wc;
|
||||||
|
KeyTyped = true; // in case the key was mapped
|
||||||
|
}
|
||||||
|
} else if (c == K_UP) {
|
||||||
|
// go up a directory
|
||||||
|
int found = false;
|
||||||
|
|
||||||
|
int j = cclp->cmdpos - 1;
|
||||||
|
int i = (int)((char_u *)xp->xp_pattern - cclp->cmdbuff);
|
||||||
|
while (--j > i) {
|
||||||
|
j -= utf_head_off(cclp->cmdbuff, cclp->cmdbuff + j);
|
||||||
|
if (vim_ispathsep(cclp->cmdbuff[j])
|
||||||
|
#ifdef BACKSLASH_IN_FILENAME
|
||||||
|
&& vim_strchr((const char_u *)" *?[{`$%#", cclp->cmdbuff[j + 1])
|
||||||
|
== NULL
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
|
if (found) {
|
||||||
|
i = j + 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
j = i;
|
||||||
|
} else if (STRNCMP(cclp->cmdbuff + j, upseg, 4) == 0) {
|
||||||
|
j += 4;
|
||||||
|
} else if (STRNCMP(cclp->cmdbuff + j, upseg + 1, 3) == 0
|
||||||
|
&& j == i) {
|
||||||
|
j += 3;
|
||||||
|
} else {
|
||||||
|
j = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j > 0) {
|
||||||
|
// TODO(tarruda): this is only for DOS/Unix systems - need to put in
|
||||||
|
// machine-specific stuff here and in upseg init
|
||||||
|
cmdline_del(cclp, j);
|
||||||
|
put_on_cmdline(upseg + 1, 3, false);
|
||||||
|
} else if (cclp->cmdpos > i) {
|
||||||
|
cmdline_del(cclp, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now complete in the new directory. Set KeyTyped in case the
|
||||||
|
// Up key came from a mapping.
|
||||||
|
c = (int)p_wc;
|
||||||
|
KeyTyped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Free expanded names when finished walking through the matches
|
||||||
|
void wildmenu_cleanup(CmdlineInfo *cclp)
|
||||||
|
{
|
||||||
|
if (!p_wmnu || wild_menu_showing == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool skt = KeyTyped;
|
||||||
|
int old_RedrawingDisabled = RedrawingDisabled;
|
||||||
|
|
||||||
|
if (cclp->input_fn) {
|
||||||
|
RedrawingDisabled = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wild_menu_showing == WM_SCROLLED) {
|
||||||
|
// Entered command line, move it up
|
||||||
|
cmdline_row--;
|
||||||
|
redrawcmd();
|
||||||
|
wild_menu_showing = 0;
|
||||||
|
} else if (save_p_ls != -1) {
|
||||||
|
// restore 'laststatus' and 'winminheight'
|
||||||
|
p_ls = save_p_ls;
|
||||||
|
p_wmh = save_p_wmh;
|
||||||
|
last_status(false);
|
||||||
|
update_screen(VALID); // redraw the screen NOW
|
||||||
|
redrawcmd();
|
||||||
|
save_p_ls = -1;
|
||||||
|
wild_menu_showing = 0;
|
||||||
|
// don't redraw statusline if WM_LIST is showing
|
||||||
|
} else if (wild_menu_showing != WM_LIST) {
|
||||||
|
win_redraw_last_status(topframe);
|
||||||
|
wild_menu_showing = 0; // must be before redraw_statuslines #8385
|
||||||
|
redraw_statuslines();
|
||||||
|
} else {
|
||||||
|
wild_menu_showing = 0;
|
||||||
|
}
|
||||||
|
KeyTyped = skt;
|
||||||
|
if (cclp->input_fn) {
|
||||||
|
RedrawingDisabled = old_RedrawingDisabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// "getcompletion()" function
|
/// "getcompletion()" function
|
||||||
void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define NVIM_CMDEXPAND_H
|
#define NVIM_CMDEXPAND_H
|
||||||
|
|
||||||
#include "nvim/eval/typval.h"
|
#include "nvim/eval/typval.h"
|
||||||
|
#include "nvim/ex_getln.h"
|
||||||
#include "nvim/garray.h"
|
#include "nvim/garray.h"
|
||||||
#include "nvim/types.h"
|
#include "nvim/types.h"
|
||||||
|
|
||||||
|
@ -170,12 +170,7 @@ static Array cmdline_block = ARRAY_DICT_INIT;
|
|||||||
/// user interrupting highlight function to not interrupt command-line.
|
/// user interrupting highlight function to not interrupt command-line.
|
||||||
static bool getln_interrupted_highlight = false;
|
static bool getln_interrupted_highlight = false;
|
||||||
|
|
||||||
// TODO(zeertzjq): make these four variables static in cmdexpand.c
|
extern pumitem_T *compl_match_array; // TODO(zeertzjq): make this static in cmdexpand.c
|
||||||
|
|
||||||
extern pumitem_T *compl_match_array;
|
|
||||||
extern int compl_match_arraysize;
|
|
||||||
extern int compl_startcol;
|
|
||||||
extern int compl_selected;
|
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "ex_getln.c.generated.h"
|
# include "ex_getln.c.generated.h"
|
||||||
@ -1028,14 +1023,8 @@ static int command_line_execute(VimState *state, int key)
|
|||||||
s->c = Ctrl_P;
|
s->c = Ctrl_P;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special translations for 'wildmenu'
|
s->c = wildmenu_translate_key(&ccline, s->c, &s->xpc, s->did_wild_list);
|
||||||
if (s->did_wild_list && p_wmnu) {
|
|
||||||
if (s->c == K_LEFT) {
|
|
||||||
s->c = Ctrl_P;
|
|
||||||
} else if (s->c == K_RIGHT) {
|
|
||||||
s->c = Ctrl_N;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (compl_match_array || s->did_wild_list) {
|
if (compl_match_array || s->did_wild_list) {
|
||||||
if (s->c == Ctrl_E) {
|
if (s->c == Ctrl_E) {
|
||||||
s->res = nextwild(&s->xpc, WILD_CANCEL, WILD_NO_BEEP,
|
s->res = nextwild(&s->xpc, WILD_CANCEL, WILD_NO_BEEP,
|
||||||
@ -1047,15 +1036,6 @@ static int command_line_execute(VimState *state, int key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hitting CR after "emenu Name.": complete submenu
|
|
||||||
if (s->xpc.xp_context == EXPAND_MENUNAMES && p_wmnu
|
|
||||||
&& ccline.cmdpos > 1
|
|
||||||
&& ccline.cmdbuff[ccline.cmdpos - 1] == '.'
|
|
||||||
&& ccline.cmdbuff[ccline.cmdpos - 2] != '\\'
|
|
||||||
&& (s->c == '\n' || s->c == '\r' || s->c == K_KENTER)) {
|
|
||||||
s->c = K_DOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
// free expanded names when finished walking through matches
|
// free expanded names when finished walking through matches
|
||||||
if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
|
if (!(s->c == p_wc && KeyTyped) && s->c != p_wcm && s->c != Ctrl_Z
|
||||||
&& s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
|
&& s->c != Ctrl_N && s->c != Ctrl_P && s->c != Ctrl_A
|
||||||
@ -1072,175 +1052,10 @@ static int command_line_execute(VimState *state, int key)
|
|||||||
s->xpc.xp_context = EXPAND_NOTHING;
|
s->xpc.xp_context = EXPAND_NOTHING;
|
||||||
}
|
}
|
||||||
s->wim_index = 0;
|
s->wim_index = 0;
|
||||||
if (p_wmnu && wild_menu_showing != 0) {
|
wildmenu_cleanup(&ccline);
|
||||||
const bool skt = KeyTyped;
|
|
||||||
int old_RedrawingDisabled = RedrawingDisabled;
|
|
||||||
|
|
||||||
if (ccline.input_fn) {
|
|
||||||
RedrawingDisabled = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wild_menu_showing == WM_SCROLLED) {
|
|
||||||
// Entered command line, move it up
|
|
||||||
cmdline_row--;
|
|
||||||
redrawcmd();
|
|
||||||
wild_menu_showing = 0;
|
|
||||||
} else if (save_p_ls != -1) {
|
|
||||||
// restore 'laststatus' and 'winminheight'
|
|
||||||
p_ls = save_p_ls;
|
|
||||||
p_wmh = save_p_wmh;
|
|
||||||
last_status(false);
|
|
||||||
update_screen(VALID); // redraw the screen NOW
|
|
||||||
redrawcmd();
|
|
||||||
save_p_ls = -1;
|
|
||||||
wild_menu_showing = 0;
|
|
||||||
// don't redraw statusline if WM_LIST is showing
|
|
||||||
} else if (wild_menu_showing != WM_LIST) {
|
|
||||||
win_redraw_last_status(topframe);
|
|
||||||
wild_menu_showing = 0; // must be before redraw_statuslines #8385
|
|
||||||
redraw_statuslines();
|
|
||||||
} else {
|
|
||||||
wild_menu_showing = 0;
|
|
||||||
}
|
|
||||||
KeyTyped = skt;
|
|
||||||
if (ccline.input_fn) {
|
|
||||||
RedrawingDisabled = old_RedrawingDisabled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special translations for 'wildmenu'
|
s->c = wildmenu_process_key(&ccline, s->c, &s->xpc);
|
||||||
if (s->xpc.xp_context == EXPAND_MENUNAMES && p_wmnu) {
|
|
||||||
// Hitting <Down> after "emenu Name.": complete submenu
|
|
||||||
if (s->c == K_DOWN && ccline.cmdpos > 0
|
|
||||||
&& ccline.cmdbuff[ccline.cmdpos - 1] == '.') {
|
|
||||||
s->c = (int)p_wc;
|
|
||||||
KeyTyped = true; // in case the key was mapped
|
|
||||||
} else if (s->c == K_UP) {
|
|
||||||
// Hitting <Up>: Remove one submenu name in front of the
|
|
||||||
// cursor
|
|
||||||
int found = false;
|
|
||||||
|
|
||||||
int j = (int)((char_u *)s->xpc.xp_pattern - ccline.cmdbuff);
|
|
||||||
int i = 0;
|
|
||||||
while (--j > 0) {
|
|
||||||
// check for start of menu name
|
|
||||||
if (ccline.cmdbuff[j] == ' '
|
|
||||||
&& ccline.cmdbuff[j - 1] != '\\') {
|
|
||||||
i = j + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for start of submenu name
|
|
||||||
if (ccline.cmdbuff[j] == '.'
|
|
||||||
&& ccline.cmdbuff[j - 1] != '\\') {
|
|
||||||
if (found) {
|
|
||||||
i = j + 1;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (i > 0) {
|
|
||||||
cmdline_del(i);
|
|
||||||
}
|
|
||||||
s->c = (int)p_wc;
|
|
||||||
KeyTyped = true; // in case the key was mapped
|
|
||||||
s->xpc.xp_context = EXPAND_NOTHING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((s->xpc.xp_context == EXPAND_FILES
|
|
||||||
|| s->xpc.xp_context == EXPAND_DIRECTORIES
|
|
||||||
|| s->xpc.xp_context == EXPAND_SHELLCMD) && p_wmnu) {
|
|
||||||
char_u upseg[5];
|
|
||||||
|
|
||||||
upseg[0] = PATHSEP;
|
|
||||||
upseg[1] = '.';
|
|
||||||
upseg[2] = '.';
|
|
||||||
upseg[3] = PATHSEP;
|
|
||||||
upseg[4] = NUL;
|
|
||||||
|
|
||||||
if (s->c == K_DOWN
|
|
||||||
&& ccline.cmdpos > 0
|
|
||||||
&& ccline.cmdbuff[ccline.cmdpos - 1] == PATHSEP
|
|
||||||
&& (ccline.cmdpos < 3
|
|
||||||
|| ccline.cmdbuff[ccline.cmdpos - 2] != '.'
|
|
||||||
|| ccline.cmdbuff[ccline.cmdpos - 3] != '.')) {
|
|
||||||
// go down a directory
|
|
||||||
s->c = (int)p_wc;
|
|
||||||
KeyTyped = true; // in case the key was mapped
|
|
||||||
} else if (STRNCMP(s->xpc.xp_pattern, upseg + 1, 3) == 0
|
|
||||||
&& s->c == K_DOWN) {
|
|
||||||
// If in a direct ancestor, strip off one ../ to go down
|
|
||||||
int found = false;
|
|
||||||
|
|
||||||
int j = ccline.cmdpos;
|
|
||||||
int i = (int)((char_u *)s->xpc.xp_pattern - ccline.cmdbuff);
|
|
||||||
while (--j > i) {
|
|
||||||
j -= utf_head_off(ccline.cmdbuff, ccline.cmdbuff + j);
|
|
||||||
if (vim_ispathsep(ccline.cmdbuff[j])) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found
|
|
||||||
&& ccline.cmdbuff[j - 1] == '.'
|
|
||||||
&& ccline.cmdbuff[j - 2] == '.'
|
|
||||||
&& (vim_ispathsep(ccline.cmdbuff[j - 3]) || j == i + 2)) {
|
|
||||||
cmdline_del(j - 2);
|
|
||||||
s->c = (int)p_wc;
|
|
||||||
KeyTyped = true; // in case the key was mapped
|
|
||||||
}
|
|
||||||
} else if (s->c == K_UP) {
|
|
||||||
// go up a directory
|
|
||||||
int found = false;
|
|
||||||
|
|
||||||
int j = ccline.cmdpos - 1;
|
|
||||||
int i = (int)((char_u *)s->xpc.xp_pattern - ccline.cmdbuff);
|
|
||||||
while (--j > i) {
|
|
||||||
j -= utf_head_off(ccline.cmdbuff, ccline.cmdbuff + j);
|
|
||||||
if (vim_ispathsep(ccline.cmdbuff[j])
|
|
||||||
#ifdef BACKSLASH_IN_FILENAME
|
|
||||||
&& vim_strchr((const char_u *)" *?[{`$%#", ccline.cmdbuff[j + 1])
|
|
||||||
== NULL
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
if (found) {
|
|
||||||
i = j + 1;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
j = i;
|
|
||||||
} else if (STRNCMP(ccline.cmdbuff + j, upseg, 4) == 0) {
|
|
||||||
j += 4;
|
|
||||||
} else if (STRNCMP(ccline.cmdbuff + j, upseg + 1, 3) == 0
|
|
||||||
&& j == i) {
|
|
||||||
j += 3;
|
|
||||||
} else {
|
|
||||||
j = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (j > 0) {
|
|
||||||
// TODO(tarruda): this is only for DOS/Unix systems - need to put in
|
|
||||||
// machine-specific stuff here and in upseg init
|
|
||||||
cmdline_del(j);
|
|
||||||
put_on_cmdline(upseg + 1, 3, false);
|
|
||||||
} else if (ccline.cmdpos > i) {
|
|
||||||
cmdline_del(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now complete in the new directory. Set KeyTyped in case the
|
|
||||||
// Up key came from a mapping.
|
|
||||||
s->c = (int)p_wc;
|
|
||||||
KeyTyped = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// CTRL-\ CTRL-N goes to Normal mode, CTRL-\ e prompts for an expression.
|
// CTRL-\ CTRL-N goes to Normal mode, CTRL-\ e prompts for an expression.
|
||||||
if (s->c == Ctrl_BSL) {
|
if (s->c == Ctrl_BSL) {
|
||||||
@ -3749,16 +3564,6 @@ void cmdline_paste_str(char_u *s, int literally)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Delete characters on the command line, from "from" to the current position.
|
|
||||||
static void cmdline_del(int from)
|
|
||||||
{
|
|
||||||
assert(ccline.cmdpos <= ccline.cmdlen);
|
|
||||||
memmove(ccline.cmdbuff + from, ccline.cmdbuff + ccline.cmdpos,
|
|
||||||
(size_t)ccline.cmdlen - (size_t)ccline.cmdpos + 1);
|
|
||||||
ccline.cmdlen -= ccline.cmdpos - from;
|
|
||||||
ccline.cmdpos = from;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is called when the screen size changes and with incremental
|
// This function is called when the screen size changes and with incremental
|
||||||
// search and in other situations where the command line may have been
|
// search and in other situations where the command line may have been
|
||||||
// overwritten.
|
// overwritten.
|
||||||
|
Loading…
Reference in New Issue
Block a user