# HG changeset patch # User Bram Moolenaar # Date 1564325105 -7200 # Node ID 77c3f6428b6ced41e91f4e286d31e83f924f5a02 # Parent 8ff04f492f46faab10776a2de58a5c8906c36b45 patch 8.1.1769: 'shellslash' is also used for completion commit https://github.com/vim/vim/commit/ac3150d385e6e3f3fe76642aac3cda954d30583f Author: Bram Moolenaar Date: Sun Jul 28 16:36:39 2019 +0200 patch 8.1.1769: 'shellslash' is also used for completion Problem: 'shellslash' is also used for completion. Solution: Add the 'completeslash' option. (Yasuhiro Matsumoto, closes https://github.com/vim/vim/issues/3612) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1874,6 +1874,21 @@ A jump table for the options with a shor This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. + *'completeslash'* *'csl'* +'completeslash' 'csl' string (default: "") + local to buffer + {not in Vi} {only for MS-Windows} + When this option is set it overrules 'shellslash' for completion: + - When this option is set to "slash", a forward slash is used for path + completion in insert mode. This is useful when editing HTML tag, or + Makefile with 'noshellslash' on Windows. + - When this option is set to "backslash", backslash is used. This is + useful when editing a batch file with 'shellslash' set on Windows. + - When this option is empty, same character is used as for + 'shellslash'. + For Insert mode completion the buffer-local value is used. For + command line completion the global value is used. + *'completeopt'* *'cot'* 'completeopt' 'cot' string (default: "menu,preview") global @@ -6521,7 +6536,8 @@ A jump table for the options with a shor 'shellslash' only works when a backslash can be used as a path separator. To test if this is so use: > if exists('+shellslash') -< +< Also see 'completeslash'. + *'shelltemp'* *'stmp'* *'noshelltemp'* *'nostmp'* 'shelltemp' 'stmp' boolean (Vi default off, Vim default on) global diff --git a/src/ex_getln.c b/src/ex_getln.c --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -5095,6 +5095,26 @@ ExpandFromContext( ret = expand_wildcards_eval(&pat, num_file, file, flags); if (free_pat) vim_free(pat); +#ifdef BACKSLASH_IN_FILENAME + if (p_csl[0] != NUL) + { + int i; + + for (i = 0; i < *num_file; ++i) + { + char_u *ptr = (*file)[i]; + + while (*ptr != NUL) + { + if (p_csl[0] == 's' && *ptr == '\\') + *ptr = '/'; + else if (p_csl[0] == 'b' && *ptr == '/') + *ptr = '\\'; + ptr += (*mb_ptr2len)(ptr); + } + } + } +#endif return ret; } diff --git a/src/insexpand.c b/src/insexpand.c --- a/src/insexpand.c +++ b/src/insexpand.c @@ -2669,6 +2669,26 @@ ins_compl_get_exp(pos_T *ini) // May change home directory back to "~". tilde_replace(compl_pattern, num_matches, matches); +#ifdef BACKSLASH_IN_FILENAME + if (curbuf->b_p_csl[0] != NUL) + { + int i; + + for (i = 0; i < num_matches; ++i) + { + char_u *ptr = matches[i]; + + while (*ptr != NUL) + { + if (curbuf->b_p_csl[0] == 's' && *ptr == '\\') + *ptr = '/'; + else if (curbuf->b_p_csl[0] == 'b' && *ptr == '/') + *ptr = '\\'; + ptr += (*mb_ptr2len)(ptr); + } + } + } +#endif ins_compl_add_matches(num_matches, matches, p_fic || p_wic); } break; diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -88,6 +88,7 @@ # define PV_DICT OPT_BOTH(OPT_BUF(BV_DICT)) # define PV_TSR OPT_BOTH(OPT_BUF(BV_TSR)) #endif +#define PV_CSL OPT_BUF(BV_CSL) #ifdef FEAT_COMPL_FUNC # define PV_CFU OPT_BUF(BV_CFU) #endif @@ -892,6 +893,15 @@ static struct vimoption options[] = {(char_u *)0L, (char_u *)0L} #endif SCTX_INIT}, + {"completeslash", "csl", P_STRING|P_VI_DEF|P_VIM, +#if defined(FEAT_INS_EXPAND) && defined(BACKSLASH_IN_FILENAME) + (char_u *)&p_csl, PV_CSL, + {(char_u *)"", (char_u *)0L} +#else + (char_u *)NULL, PV_NONE, + {(char_u *)0L, (char_u *)0L} +#endif + SCTX_INIT}, {"confirm", "cf", P_BOOL|P_VI_DEF, #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG) (char_u *)&p_confirm, PV_NONE, @@ -3238,6 +3248,9 @@ static char *(p_fcl_values[]) = {"all", #endif #ifdef FEAT_INS_EXPAND static char *(p_cot_values[]) = {"menu", "menuone", "longest", "preview", "noinsert", "noselect", NULL}; +# ifdef BACKSLASH_IN_FILENAME +static char *(p_csl_values[]) = {"slash", "backslash", NULL}; +# endif #endif #ifdef FEAT_SIGNS static char *(p_scl_values[]) = {"yes", "no", "auto", "number", NULL}; @@ -7409,7 +7422,7 @@ did_set_string_option( } } - /* 'completeopt' */ + // 'completeopt' else if (varp == &p_cot) { if (check_opt_strings(p_cot, p_cot_values, TRUE) != OK) @@ -7417,7 +7430,16 @@ did_set_string_option( else completeopt_was_set(); } -#endif /* FEAT_INS_EXPAND */ + +# ifdef BACKSLASH_IN_FILENAME + // 'completeslash' + else if (varp == &curbuf->b_p_csl) + { + if (check_opt_strings(p_csl, p_csl_values, FALSE) != OK) + errmsg = e_invarg; + } +# endif +#endif // FEAT_INS_EXPAND #ifdef FEAT_SIGNS // 'signcolumn' @@ -11110,7 +11132,6 @@ get_varp(struct vimoption *p) #endif case PV_MENC: return *curbuf->b_p_menc != NUL ? (char_u *)&(curbuf->b_p_menc) : p->var; - #ifdef FEAT_ARABIC case PV_ARAB: return (char_u *)&(curwin->w_p_arab); #endif @@ -11197,6 +11218,9 @@ get_varp(struct vimoption *p) #endif #ifdef FEAT_INS_EXPAND case PV_CPT: return (char_u *)&(curbuf->b_p_cpt); +# ifdef BACKSLASH_IN_FILENAME + case PV_CSL: return (char_u *)&(curbuf->b_p_csl); +# endif #endif #ifdef FEAT_COMPL_FUNC case PV_CFU: return (char_u *)&(curbuf->b_p_cfu); @@ -11591,6 +11615,9 @@ buf_copy_options(buf_T *buf, int flags) buf->b_p_swf = cmdmod.noswapfile ? FALSE : p_swf; #ifdef FEAT_INS_EXPAND buf->b_p_cpt = vim_strsave(p_cpt); +# ifdef BACKSLASH_IN_FILENAME + buf->b_p_csl = vim_strsave(p_csl); +# endif #endif #ifdef FEAT_COMPL_FUNC buf->b_p_cfu = vim_strsave(p_cfu); diff --git a/src/option.h b/src/option.h --- a/src/option.h +++ b/src/option.h @@ -412,6 +412,9 @@ EXTERN int p_confirm; // 'confirm' EXTERN int p_cp; // 'compatible' #ifdef FEAT_INS_EXPAND EXTERN char_u *p_cot; // 'completeopt' +# ifdef BACKSLASH_IN_FILENAME +EXTERN char_u *p_csl; // 'completeslash' +# endif EXTERN long p_ph; // 'pumheight' EXTERN long p_pw; // 'pumwidth' #endif @@ -997,6 +1000,9 @@ enum , BV_DICT , BV_TSR #endif +#ifdef BACKSLASH_IN_FILENAME + , BV_CSL +#endif #ifdef FEAT_COMPL_FUNC , BV_CFU #endif diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1198,6 +1198,7 @@ typedef struct hashitem_S // Initial size for a hashtable. Our items are relatively small and growing // is expensive, thus use 16 as a start. Must be a power of 2. +// This allows for storing 10 items (2/3 of 16) before a resize is needed. #define HT_INIT_SIZE 16 typedef struct hashtable_S @@ -2395,6 +2396,9 @@ struct file_buffer #ifdef FEAT_INS_EXPAND char_u *b_p_cpt; // 'complete' #endif +#ifdef BACKSLASH_IN_FILENAME + char_u *b_p_csl; // 'completeslash' +#endif #ifdef FEAT_COMPL_FUNC char_u *b_p_cfu; // 'completefunc' char_u *b_p_ofu; // 'omnifunc' diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim --- a/src/testdir/test_ins_complete.vim +++ b/src/testdir/test_ins_complete.vim @@ -331,3 +331,50 @@ func Test_compl_in_cmdwin() delcom GetInput set wildmenu& wildchar& endfunc + +" Test for insert path completion with completeslash option +func Test_ins_completeslash() + if !has('win32') + return + endif + + call mkdir('Xdir') + + let orig_shellslash = &shellslash + set cpt& + + new + + set noshellslash + + set completeslash= + exe "normal oXd\\" + call assert_equal('Xdir\', getline('.')) + + set completeslash=backslash + exe "normal oXd\\" + call assert_equal('Xdir\', getline('.')) + + set completeslash=slash + exe "normal oXd\\" + call assert_equal('Xdir/', getline('.')) + + set shellslash + + set completeslash= + exe "normal oXd\\" + call assert_equal('Xdir/', getline('.')) + + set completeslash=backslash + exe "normal oXd\\" + call assert_equal('Xdir\', getline('.')) + + set completeslash=slash + exe "normal oXd\\" + call assert_equal('Xdir/', getline('.')) + %bw! + call delete('Xdir', 'rf') + + let &shellslash = orig_shellslash +endfunc + diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -778,6 +778,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1769, +/**/ 1768, /**/ 1767,