diff options
Diffstat (limited to 'src/nvim/arglist.c')
-rw-r--r-- | src/nvim/arglist.c | 199 |
1 files changed, 104 insertions, 95 deletions
diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c index 0be83f0c05..02e3a99aab 100644 --- a/src/nvim/arglist.c +++ b/src/nvim/arglist.c @@ -79,13 +79,14 @@ void alist_expand(int *fnum_list, int fnum_len) { char *save_p_su = p_su; + char **old_arg_files = xmalloc(sizeof(*old_arg_files) * GARGCOUNT); + // Don't use 'suffixes' here. This should work like the shell did the // expansion. Also, the vimrc file isn't read yet, thus the user // can't set the options. p_su = empty_option; - char **old_arg_files = xmalloc(sizeof(*old_arg_files) * GARGCOUNT); for (int i = 0; i < GARGCOUNT; i++) { - old_arg_files[i] = vim_strsave(GARGLIST[i].ae_fname); + old_arg_files[i] = xstrdup(GARGLIST[i].ae_fname); } int old_arg_count = GARGCOUNT; char **new_arg_files; @@ -157,7 +158,7 @@ void alist_add(alist_T *al, char *fname, int set_fnum) #ifdef BACKSLASH_IN_FILENAME slash_adjust(fname); #endif - AARGLIST(al)[al->al_ga.ga_len].ae_fname = (char_u *)fname; + AARGLIST(al)[al->al_ga.ga_len].ae_fname = fname; if (set_fnum > 0) { AARGLIST(al)[al->al_ga.ga_len].ae_fnum = buflist_add(fname, BLN_LISTED | (set_fnum == 2 ? BLN_CURBUF : 0)); @@ -202,7 +203,7 @@ static char *do_one_arg(char *str) for (p = str; *str; str++) { // When the backslash is used for escaping the special meaning of a // character we need to keep it until wildcard expansion. - if (rem_backslash((char_u *)str)) { + if (rem_backslash(str)) { *p++ = *str++; *p++ = *str; } else { @@ -226,7 +227,7 @@ static char *do_one_arg(char *str) /// growarray "gap". static void get_arglist(garray_T *gap, char *str, int escaped) { - ga_init(gap, (int)sizeof(char_u *), 20); + ga_init(gap, (int)sizeof(char *), 20); while (*str != NUL) { GA_APPEND(char *, gap, str); @@ -244,12 +245,12 @@ static void get_arglist(garray_T *gap, char *str, int escaped) /// "fnames[fcountp]". When "wig" is true, removes files matching 'wildignore'. /// /// @return FAIL or OK. -int get_arglist_exp(char_u *str, int *fcountp, char ***fnamesp, bool wig) +int get_arglist_exp(char *str, int *fcountp, char ***fnamesp, bool wig) { garray_T ga; int i; - get_arglist(&ga, (char *)str, true); + get_arglist(&ga, str, true); if (wig) { i = expand_wildcards(ga.ga_len, ga.ga_data, @@ -297,7 +298,7 @@ static void alist_add_list(int count, char **files, int after, bool will_edit) } for (int i = 0; i < count; i++) { const int flags = BLN_LISTED | (will_edit ? BLN_CURBUF : 0); - ARGLIST[after + i].ae_fname = (char_u *)files[i]; + ARGLIST[after + i].ae_fname = files[i]; ARGLIST[after + i].ae_fnum = buflist_add(files[i], flags); } ALIST(curwin)->al_ga.ga_len += count; @@ -308,6 +309,50 @@ static void alist_add_list(int count, char **files, int after, bool will_edit) } } +/// Delete the file names in "alist_ga" from the argument list. +static void arglist_del_files(garray_T *alist_ga) +{ + regmatch_T regmatch; + + // Delete the items: use each item as a regexp and find a match in the + // argument list. + regmatch.rm_ic = p_fic; // ignore case when 'fileignorecase' is set + for (int i = 0; i < alist_ga->ga_len && !got_int; i++) { + char *p = ((char **)alist_ga->ga_data)[i]; + p = file_pat_to_reg_pat(p, NULL, NULL, false); + if (p == NULL) { + break; + } + regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0); + if (regmatch.regprog == NULL) { + xfree(p); + break; + } + + bool didone = false; + for (int match = 0; match < ARGCOUNT; match++) { + if (vim_regexec(®match, alist_name(&ARGLIST[match]), (colnr_T)0)) { + didone = true; + xfree(ARGLIST[match].ae_fname); + memmove(ARGLIST + match, ARGLIST + match + 1, + (size_t)(ARGCOUNT - match - 1) * sizeof(aentry_T)); + ALIST(curwin)->al_ga.ga_len--; + if (curwin->w_arg_idx > match) { + curwin->w_arg_idx--; + } + match--; + } + } + + vim_regfree(regmatch.regprog); + xfree(p); + if (!didone) { + semsg(_(e_nomatch2), ((char **)alist_ga->ga_data)[i]); + } + } + ga_clear(alist_ga); +} + /// @param str /// @param what /// AL_SET: Redefine the argument list to 'str'. @@ -324,8 +369,6 @@ static int do_arglist(char *str, int what, int after, bool will_edit) garray_T new_ga; int exp_count; char **exp_files; - char *p; - int match; int arg_escaped = true; // Set default argument for ":argadd" command. @@ -341,46 +384,7 @@ static int do_arglist(char *str, int what, int after, bool will_edit) get_arglist(&new_ga, str, arg_escaped); if (what == AL_DEL) { - regmatch_T regmatch; - bool didone; - - // Delete the items: use each item as a regexp and find a match in the - // argument list. - regmatch.rm_ic = p_fic; // ignore case when 'fileignorecase' is set - for (int i = 0; i < new_ga.ga_len && !got_int; i++) { - p = ((char **)new_ga.ga_data)[i]; - p = file_pat_to_reg_pat(p, NULL, NULL, false); - if (p == NULL) { - break; - } - regmatch.regprog = vim_regcomp(p, p_magic ? RE_MAGIC : 0); - if (regmatch.regprog == NULL) { - xfree(p); - break; - } - - didone = false; - for (match = 0; match < ARGCOUNT; match++) { - if (vim_regexec(®match, alist_name(&ARGLIST[match]), (colnr_T)0)) { - didone = true; - xfree(ARGLIST[match].ae_fname); - memmove(ARGLIST + match, ARGLIST + match + 1, - (size_t)(ARGCOUNT - match - 1) * sizeof(aentry_T)); - ALIST(curwin)->al_ga.ga_len--; - if (curwin->w_arg_idx > match) { - curwin->w_arg_idx--; - } - match--; - } - } - - vim_regfree(regmatch.regprog); - xfree(p); - if (!didone) { - semsg(_(e_nomatch2), ((char_u **)new_ga.ga_data)[i]); - } - } - ga_clear(&new_ga); + arglist_del_files(&new_ga); } else { int i = expand_wildcards(new_ga.ga_len, new_ga.ga_data, &exp_count, &exp_files, @@ -471,28 +475,31 @@ void ex_args(exarg_T *eap) ex_next(eap); } else if (eap->cmdidx == CMD_args) { // ":args": list arguments. - if (ARGCOUNT > 0) { - char **items = xmalloc(sizeof(char_u *) * (size_t)ARGCOUNT); - // Overwrite the command, for a short list there is no scrolling - // required and no wait_return(). - gotocmdline(true); - for (int i = 0; i < ARGCOUNT; i++) { - items[i] = alist_name(&ARGLIST[i]); - } - list_in_columns(items, ARGCOUNT, curwin->w_arg_idx); - xfree(items); + if (ARGCOUNT <= 0) { + return; } + + char **items = xmalloc(sizeof(char *) * (size_t)ARGCOUNT); + + // Overwrite the command, for a short list there is no scrolling + // required and no wait_return(). + gotocmdline(true); + + for (int i = 0; i < ARGCOUNT; i++) { + items[i] = alist_name(&ARGLIST[i]); + } + list_in_columns(items, ARGCOUNT, curwin->w_arg_idx); + xfree(items); } else if (eap->cmdidx == CMD_arglocal) { garray_T *gap = &curwin->w_alist->al_ga; // ":argslocal": make a local copy of the global argument list. ga_grow(gap, GARGCOUNT); + for (int i = 0; i < GARGCOUNT; i++) { if (GARGLIST[i].ae_fname != NULL) { - AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname = - vim_strsave(GARGLIST[i].ae_fname); - AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum = - GARGLIST[i].ae_fnum; + AARGLIST(curwin->w_alist)[gap->ga_len].ae_fname = xstrdup(GARGLIST[i].ae_fname); + AARGLIST(curwin->w_alist)[gap->ga_len].ae_fnum = GARGLIST[i].ae_fnum; gap->ga_len++; } } @@ -626,7 +633,7 @@ void ex_argdedupe(exarg_T *eap FUNC_ATTR_UNUSED) { for (int i = 0; i < ARGCOUNT; i++) { for (int j = i + 1; j < ARGCOUNT; j++) { - if (FNAMECMP(ARGLIST[i].ae_fname, ARGLIST[j].ae_fname) == 0) { + if (path_fnamecmp(ARGLIST[i].ae_fname, ARGLIST[j].ae_fname) == 0) { xfree(ARGLIST[j].ae_fname); memmove(ARGLIST + j, ARGLIST + j + 1, (size_t)(ARGCOUNT - j - 1) * sizeof(aentry_T)); @@ -742,7 +749,7 @@ char *alist_name(aentry_T *aep) // Use the name from the associated buffer if it exists. bp = buflist_findnr(aep->ae_fnum); if (bp == NULL || bp->b_fname == NULL) { - return (char *)aep->ae_fname; + return aep->ae_fname; } return bp->b_fname; } @@ -1074,7 +1081,7 @@ char *arg_all(void) } /// "argc([window id])" function -void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr) +void f_argc(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { if (argvars[0].v_type == VAR_UNKNOWN) { // use the current window @@ -1095,13 +1102,13 @@ void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr) } /// "argidx()" function -void f_argidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) +void f_argidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = curwin->w_arg_idx; } /// "arglistid()" function -void f_arglistid(typval_T *argvars, typval_T *rettv, FunPtr fptr) +void f_arglistid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = -1; win_T *wp = find_tabwin(&argvars[0], &argvars[1]); @@ -1123,36 +1130,38 @@ static void get_arglist_as_rettv(aentry_T *arglist, int argcount, typval_T *rett } /// "argv(nr)" function -void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) +void f_argv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { aentry_T *arglist = NULL; int argcount = -1; - if (argvars[0].v_type != VAR_UNKNOWN) { - if (argvars[1].v_type == VAR_UNKNOWN) { - arglist = ARGLIST; - argcount = ARGCOUNT; - } else if (argvars[1].v_type == VAR_NUMBER - && tv_get_number(&argvars[1]) == -1) { - arglist = GARGLIST; - argcount = GARGCOUNT; - } else { - win_T *wp = find_win_by_nr_or_id(&argvars[1]); - if (wp != NULL) { - // Use the argument list of the specified window - arglist = WARGLIST(wp); - argcount = WARGCOUNT(wp); - } - } - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - int idx = (int)tv_get_number_chk(&argvars[0], NULL); - if (arglist != NULL && idx >= 0 && idx < argcount) { - rettv->vval.v_string = xstrdup((const char *)alist_name(&arglist[idx])); - } else if (idx == -1) { - get_arglist_as_rettv(arglist, argcount, rettv); - } - } else { + if (argvars[0].v_type == VAR_UNKNOWN) { get_arglist_as_rettv(ARGLIST, ARGCOUNT, rettv); + return; + } + + if (argvars[1].v_type == VAR_UNKNOWN) { + arglist = ARGLIST; + argcount = ARGCOUNT; + } else if (argvars[1].v_type == VAR_NUMBER + && tv_get_number(&argvars[1]) == -1) { + arglist = GARGLIST; + argcount = GARGCOUNT; + } else { + win_T *wp = find_win_by_nr_or_id(&argvars[1]); + if (wp != NULL) { + // Use the argument list of the specified window + arglist = WARGLIST(wp); + argcount = WARGCOUNT(wp); + } + } + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + int idx = (int)tv_get_number_chk(&argvars[0], NULL); + if (arglist != NULL && idx >= 0 && idx < argcount) { + rettv->vval.v_string = xstrdup((const char *)alist_name(&arglist[idx])); + } else if (idx == -1) { + get_arglist_as_rettv(arglist, argcount, rettv); } } |