diff --git a/src/cmdexpand.c b/src/cmdexpand.c index ffefada749..449636f736 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -47,30 +47,38 @@ static char_u *cmdline_orig = NULL; static int cmdline_fuzzy_completion_supported(expand_T *xp) { - return (vim_strchr(p_wop, WOP_FUZZY) != NULL - && xp->xp_context != EXPAND_BOOL_SETTINGS - && xp->xp_context != EXPAND_COLORS - && xp->xp_context != EXPAND_COMPILER - && xp->xp_context != EXPAND_DIRECTORIES - && xp->xp_context != EXPAND_DIRS_IN_CDPATH - && xp->xp_context != EXPAND_FILES - && xp->xp_context != EXPAND_FILES_IN_PATH - && xp->xp_context != EXPAND_FILETYPE - && xp->xp_context != EXPAND_FILETYPECMD - && xp->xp_context != EXPAND_FINDFUNC - && xp->xp_context != EXPAND_HELP - && xp->xp_context != EXPAND_KEYMAP - && xp->xp_context != EXPAND_OLD_SETTING - && xp->xp_context != EXPAND_STRING_SETTING - && xp->xp_context != EXPAND_SETTING_SUBTRACT - && xp->xp_context != EXPAND_OWNSYNTAX - && xp->xp_context != EXPAND_PACKADD - && xp->xp_context != EXPAND_RUNTIME - && xp->xp_context != EXPAND_SHELLCMD - && xp->xp_context != EXPAND_SHELLCMDLINE - && xp->xp_context != EXPAND_TAGS - && xp->xp_context != EXPAND_TAGS_LISTFILES - && xp->xp_context != EXPAND_USER_LIST); + switch (xp->xp_context) + { + case EXPAND_BOOL_SETTINGS: + case EXPAND_COLORS: + case EXPAND_COMPILER: + case EXPAND_DIRECTORIES: + case EXPAND_DIRS_IN_CDPATH: + case EXPAND_FILES: + case EXPAND_FILES_IN_PATH: + case EXPAND_FILETYPE: + case EXPAND_FILETYPECMD: + case EXPAND_FINDFUNC: + case EXPAND_HELP: + case EXPAND_KEYMAP: + case EXPAND_OLD_SETTING: + case EXPAND_STRING_SETTING: + case EXPAND_SETTING_SUBTRACT: + case EXPAND_OWNSYNTAX: + case EXPAND_PACKADD: + case EXPAND_RUNTIME: + case EXPAND_SHELLCMD: + case EXPAND_SHELLCMDLINE: + case EXPAND_TAGS: + case EXPAND_TAGS_LISTFILES: + case EXPAND_USER_LIST: + return FALSE; + + default: + break; + } + + return vim_strchr(p_wop, WOP_FUZZY) != NULL; } /* @@ -3710,28 +3718,16 @@ ExpandGenericExt( */ static void expand_shellcmd_onedir( - char_u *buf, - char_u *s, - size_t l, char_u *pat, + size_t pathlen, // length of the path portion of pat. char_u ***matches, int *numMatches, int flags, hashtab_T *ht, garray_T *gap) { - int ret; - hash_T hash; - hashitem_T *hi; - - vim_strncpy(buf, s, l); - add_pathsep(buf); - l = STRLEN(buf); - vim_strncpy(buf + l, pat, MAXPATHL - 1 - l); - // Expand matches in one directory of $PATH. - ret = expand_wildcards(1, &buf, numMatches, matches, flags); - if (ret != OK) + if (expand_wildcards(1, &pat, numMatches, matches, flags) != OK) return; if (ga_grow(gap, *numMatches) == FAIL) @@ -3742,17 +3738,22 @@ expand_shellcmd_onedir( for (int i = 0; i < *numMatches; ++i) { - char_u *name = (*matches)[i]; + char_u *name = (*matches)[i]; + size_t namelen = STRLEN(name); - if (STRLEN(name) > l) + if (namelen > pathlen) { + hash_T hash; + hashitem_T *hi; + // Check if this name was already found. - hash = hash_hash(name + l); - hi = hash_lookup(ht, name + l, hash); + hash = hash_hash(name + pathlen); + hi = hash_lookup(ht, name + pathlen, hash); if (HASHITEM_EMPTY(hi)) { // Remove the path that was prepended. - STRMOVE(name, name + l); + mch_memmove(name, name + pathlen, + (size_t)(namelen - pathlen) + 1); // +1 for NUL ((char_u **)gap->ga_data)[gap->ga_len++] = name; hash_add_item(ht, hi, name, hash); name = NULL; @@ -3775,12 +3776,11 @@ expand_shellcmd( int flagsarg) // EW_ flags { char_u *pat; - int i; + size_t patlen; char_u *path = NULL; int mustfree = FALSE; garray_T ga; char_u *buf; - size_t l; char_u *s, *e; int flags = flagsarg; int did_curdir = FALSE; @@ -3791,16 +3791,31 @@ expand_shellcmd( return FAIL; // for ":set path=" and ":set tags=" halve backslashes for escaped space - pat = vim_strsave(filepat); + patlen = STRLEN(filepat); + pat = vim_strnsave(filepat, patlen); if (pat == NULL) { vim_free(buf); return FAIL; } - for (i = 0; pat[i]; ++i) - if (pat[i] == '\\' && pat[i + 1] == ' ') - STRMOVE(pat + i, pat + i + 1); + // Replace "\ " with " ". + e = pat + patlen; + for (s = pat; *s != NUL; ++s) + { + char_u *p; + + if (*s != '\\') + continue; + + p = s + 1; + if (*p == ' ') + { + mch_memmove(s, p, (size_t)(e - p) + 1); // +1 for NUL + --e; + } + } + patlen = (size_t)(e - pat); flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; @@ -3823,37 +3838,62 @@ expand_shellcmd( hash_init(&found_ht); for (s = path; ; s = e) { -#if defined(MSWIN) - e = vim_strchr(s, ';'); -#else - e = vim_strchr(s, ':'); -#endif - if (e == NULL) - e = s + STRLEN(s); + size_t pathlen; // length of the path portion of buf + // (including trailing slash). + size_t seplen; if (*s == NUL) { if (did_curdir) break; + // Find directories in the current directory, path is empty. did_curdir = TRUE; flags |= EW_DIR; - } - else if (STRNCMP(s, ".", (int)(e - s)) == 0) - { - did_curdir = TRUE; - flags |= EW_DIR; + + e = s; + pathlen = 0; + seplen = 0; } else - // Do not match directories inside a $PATH item. - flags &= ~EW_DIR; + { +#if defined(MSWIN) + e = vim_strchr(s, ';'); +#else + e = vim_strchr(s, ':'); +#endif + if (e == NULL) + e = s + STRLEN(s); - l = e - s; - if (l > MAXPATHL - 5) - break; + pathlen = (size_t)(e - s); + if (STRNCMP(s, ".", pathlen) == 0) + { + did_curdir = TRUE; + flags |= EW_DIR; + } + else + // Do not match directories inside a $PATH item. + flags &= ~EW_DIR; - expand_shellcmd_onedir(buf, s, l, pat, matches, numMatches, flags, - &found_ht, &ga); + seplen = !after_pathsep(s, e) ? STRLEN_LITERAL(PATHSEPSTR) : 0; + } + + if (pathlen + seplen + patlen + 1 <= MAXPATHL) + { + if (pathlen > 0) + { + vim_strncpy(buf, s, pathlen); + if (seplen > 0) + { + STRCPY(buf + pathlen, PATHSEPSTR); + pathlen += seplen; + } + } + STRCPY(buf + pathlen, pat); + + expand_shellcmd_onedir(buf, pathlen, matches, numMatches, flags, + &found_ht, &ga); + } if (*e != NUL) ++e; @@ -4086,7 +4126,9 @@ globpath( { expand_T xpc; char_u *buf; - size_t buflen; + size_t pathlen; // length of the path portion of buf + // (including trailing slash) + size_t seplen; size_t filelen; buf = alloc(MAXPATHL); @@ -4098,29 +4140,35 @@ globpath( filelen = STRLEN(file); +#if defined(MSWIN) + // Using the platform's path separator (\) makes vim incorrectly + // treat it as an escape character, use '/' instead. + #define TMP_PATHSEPSTR "/" +#else + #define TMP_PATHSEPSTR PATHSEPSTR +#endif + // Loop over all entries in {path}. while (*path != NUL) { // Copy one item of the path to buf[] and concatenate the file name. - buflen = (size_t)copy_option_part(&path, buf, MAXPATHL, ","); - if (buflen + filelen + 2 < MAXPATHL) + pathlen = (size_t)copy_option_part(&path, buf, MAXPATHL, ","); + seplen = (*buf != NUL && !after_pathsep(buf, buf + pathlen)) + ? STRLEN_LITERAL(TMP_PATHSEPSTR) + : 0; + + if (pathlen + seplen + filelen + 1 <= MAXPATHL) { int num_p; char_u **p; - if (*buf != NUL && !after_pathsep(buf, buf + buflen)) + if (seplen > 0) { -#if defined(MSWIN) - // Using the platform's path separator (\) makes vim incorrectly - // treat it as an escape character, use '/' instead. - STRCPY(buf + buflen, "/"); - ++buflen; -#else - STRCPY(buf + buflen, PATHSEPSTR); - buflen += STRLEN_LITERAL(PATHSEPSTR); -#endif + STRCPY(buf + pathlen, TMP_PATHSEPSTR); + pathlen += seplen; } - STRCPY(buf + buflen, file); + STRCPY(buf + pathlen, file); + if (ExpandFromContext(&xpc, buf, &p, &num_p, WILD_SILENT|expand_options) != FAIL && num_p > 0) { @@ -4142,6 +4190,7 @@ globpath( vim_free(buf); } +#undef TMP_PATHSEPSTR /* * Translate some keys pressed when 'wildmenu' is used. @@ -4485,19 +4534,20 @@ f_getcompletion(typval_T *argvars, typval_T *rettv) } else { - xpc.xp_pattern = pat; + char_u *pattern_start; + + xpc.xp_pattern = pattern_start = pat; xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); xpc.xp_line = pat; xpc.xp_context = cmdcomplete_str_to_type(type); - if (xpc.xp_context == EXPAND_NOTHING) + switch (xpc.xp_context) { + case EXPAND_NOTHING: semsg(_(e_invalid_argument_str), type); return; - } - if (xpc.xp_context == EXPAND_USER_DEFINED) - { + case EXPAND_USER_DEFINED: // Must be "custom,funcname" pattern if (STRNCMP(type, "custom,", 7) != 0) { @@ -4506,10 +4556,9 @@ f_getcompletion(typval_T *argvars, typval_T *rettv) } xpc.xp_arg = type + 7; - } + break; - if (xpc.xp_context == EXPAND_USER_LIST) - { + case EXPAND_USER_LIST: // Must be "customlist,funcname" pattern if (STRNCMP(type, "customlist,", 11) != 0) { @@ -4518,48 +4567,55 @@ f_getcompletion(typval_T *argvars, typval_T *rettv) } xpc.xp_arg = type + 11; - } + break; # if defined(FEAT_MENU) - if (xpc.xp_context == EXPAND_MENUS) - { + case EXPAND_MENUS: set_context_in_menu_cmd(&xpc, (char_u *)"menu", xpc.xp_pattern, FALSE); - xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); - } + xpc.xp_pattern_len -= (int)(xpc.xp_pattern - pattern_start); + break; # endif + # ifdef FEAT_CSCOPE - if (xpc.xp_context == EXPAND_CSCOPE) - { + case EXPAND_CSCOPE: set_context_in_cscope_cmd(&xpc, xpc.xp_pattern, CMD_cscope); - xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); - } + xpc.xp_pattern_len -= (int)(xpc.xp_pattern - pattern_start); + break; # endif + # ifdef FEAT_SIGNS - if (xpc.xp_context == EXPAND_SIGN) - { + case EXPAND_SIGN: set_context_in_sign_cmd(&xpc, xpc.xp_pattern); - xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); - } + xpc.xp_pattern_len -= (int)(xpc.xp_pattern - pattern_start); + break; # endif - if (xpc.xp_context == EXPAND_RUNTIME) - { + + case EXPAND_RUNTIME: set_context_in_runtime_cmd(&xpc, xpc.xp_pattern); - xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); - } - if (xpc.xp_context == EXPAND_SHELLCMDLINE) + xpc.xp_pattern_len -= (int)(xpc.xp_pattern - pattern_start); + break; + + case EXPAND_SHELLCMDLINE: { int context = EXPAND_SHELLCMDLINE; set_context_for_wildcard_arg(NULL, xpc.xp_pattern, FALSE, &xpc, - &context); - xpc.xp_pattern_len = (int)STRLEN(xpc.xp_pattern); + &context); + xpc.xp_pattern_len -= (int)(xpc.xp_pattern - pattern_start); + break; } - if (xpc.xp_context == EXPAND_FILETYPECMD) + + case EXPAND_FILETYPECMD: filetype_expand_what = EXP_FILETYPECMD_ALL; + break; + + default: + break; + } } if (cmdline_fuzzy_completion_supported(&xpc)) // when fuzzy matching, don't modify the search string - pat = vim_strsave(xpc.xp_pattern); + pat = vim_strnsave(xpc.xp_pattern, xpc.xp_pattern_len); else pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); @@ -4665,7 +4721,7 @@ copy_substring_from_pos(pos_T *start, pos_T *end, char_u **match, int is_single_line = start->lnum == end->lnum; segment_len = is_single_line ? (end->col - start->col) - : (int)STRLEN(start_ptr); + : (int)(ml_get_len(start->lnum) - start->col); if (ga_grow(&ga, segment_len + 2) != OK) return FAIL; diff --git a/src/po/vim.pot b/src/po/vim.pot index 8c0848cebd..55da0b7127 100644 --- a/src/po/vim.pot +++ b/src/po/vim.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-07-16 19:53+0200\n" +"POT-Creation-Date: 2025-07-16 20:09+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -340,11 +340,11 @@ msgstr "" msgid "Switched to clipboard method '%s'." msgstr "" -#: ../cmdexpand.c:1352 +#: ../cmdexpand.c:1360 msgid "tagname" msgstr "" -#: ../cmdexpand.c:1355 +#: ../cmdexpand.c:1363 msgid " kind file\n" msgstr "" @@ -4257,327 +4257,327 @@ msgstr "" msgid "%s (%s, compiled %s)" msgstr "" -#: ../version.c:4044 +#: ../version.c:4046 msgid "" "\n" "MS-Windows ARM64 GUI/console version" msgstr "" -#: ../version.c:4046 +#: ../version.c:4048 msgid "" "\n" "MS-Windows 64-bit GUI/console version" msgstr "" -#: ../version.c:4049 +#: ../version.c:4051 msgid "" "\n" "MS-Windows 32-bit GUI/console version" msgstr "" -#: ../version.c:4054 +#: ../version.c:4056 msgid "" "\n" "MS-Windows ARM64 GUI version" msgstr "" -#: ../version.c:4056 +#: ../version.c:4058 msgid "" "\n" "MS-Windows 64-bit GUI version" msgstr "" -#: ../version.c:4059 +#: ../version.c:4061 msgid "" "\n" "MS-Windows 32-bit GUI version" msgstr "" -#: ../version.c:4063 +#: ../version.c:4065 msgid " with OLE support" msgstr "" -#: ../version.c:4068 -msgid "" -"\n" -"MS-Windows ARM64 console version" -msgstr "" - #: ../version.c:4070 msgid "" "\n" +"MS-Windows ARM64 console version" +msgstr "" + +#: ../version.c:4072 +msgid "" +"\n" "MS-Windows 64-bit console version" msgstr "" -#: ../version.c:4073 +#: ../version.c:4075 msgid "" "\n" "MS-Windows 32-bit console version" msgstr "" -#: ../version.c:4079 +#: ../version.c:4081 msgid "" "\n" "macOS version" msgstr "" -#: ../version.c:4081 +#: ../version.c:4083 msgid "" "\n" "macOS version w/o darwin feat." msgstr "" -#: ../version.c:4091 +#: ../version.c:4093 msgid "" "\n" "OpenVMS version" msgstr "" -#: ../version.c:4106 +#: ../version.c:4108 msgid "" "\n" "Included patches: " msgstr "" -#: ../version.c:4131 +#: ../version.c:4133 msgid "" "\n" "Extra patches: " msgstr "" -#: ../version.c:4143 ../version.c:4454 +#: ../version.c:4145 ../version.c:4456 msgid "Modified by " msgstr "" -#: ../version.c:4150 +#: ../version.c:4152 msgid "" "\n" "Compiled " msgstr "" -#: ../version.c:4153 +#: ../version.c:4155 msgid "by " msgstr "" -#: ../version.c:4165 -msgid "" -"\n" -"Huge version " -msgstr "" - #: ../version.c:4167 msgid "" "\n" -"Normal version " +"Huge version " msgstr "" #: ../version.c:4169 msgid "" "\n" +"Normal version " +msgstr "" + +#: ../version.c:4171 +msgid "" +"\n" "Tiny version " msgstr "" -#: ../version.c:4172 +#: ../version.c:4174 msgid "without GUI." msgstr "" -#: ../version.c:4175 +#: ../version.c:4177 msgid "with GTK3 GUI." msgstr "" -#: ../version.c:4177 +#: ../version.c:4179 msgid "with GTK2-GNOME GUI." msgstr "" -#: ../version.c:4179 +#: ../version.c:4181 msgid "with GTK2 GUI." msgstr "" -#: ../version.c:4182 +#: ../version.c:4184 msgid "with X11-Motif GUI." msgstr "" -#: ../version.c:4184 +#: ../version.c:4186 msgid "with Haiku GUI." msgstr "" -#: ../version.c:4186 +#: ../version.c:4188 msgid "with Photon GUI." msgstr "" -#: ../version.c:4188 +#: ../version.c:4190 msgid "with GUI." msgstr "" -#: ../version.c:4190 +#: ../version.c:4192 msgid " Features included (+) or not (-):\n" msgstr "" -#: ../version.c:4197 +#: ../version.c:4199 msgid " system vimrc file: \"" msgstr "" -#: ../version.c:4202 +#: ../version.c:4204 msgid " user vimrc file: \"" msgstr "" -#: ../version.c:4207 +#: ../version.c:4209 msgid " 2nd user vimrc file: \"" msgstr "" -#: ../version.c:4212 ../version.c:4219 ../version.c:4223 +#: ../version.c:4214 ../version.c:4221 ../version.c:4225 msgid " 3rd user vimrc file: \"" msgstr "" -#: ../version.c:4215 +#: ../version.c:4217 msgid " 4th user vimrc file: \"" msgstr "" -#: ../version.c:4228 +#: ../version.c:4230 msgid " user exrc file: \"" msgstr "" -#: ../version.c:4233 +#: ../version.c:4235 msgid " 2nd user exrc file: \"" msgstr "" -#: ../version.c:4239 +#: ../version.c:4241 msgid " system gvimrc file: \"" msgstr "" -#: ../version.c:4243 +#: ../version.c:4245 msgid " user gvimrc file: \"" msgstr "" -#: ../version.c:4247 +#: ../version.c:4249 msgid "2nd user gvimrc file: \"" msgstr "" -#: ../version.c:4252 +#: ../version.c:4254 msgid "3rd user gvimrc file: \"" msgstr "" -#: ../version.c:4257 +#: ../version.c:4259 msgid " defaults file: \"" msgstr "" -#: ../version.c:4262 +#: ../version.c:4264 msgid " system menu file: \"" msgstr "" -#: ../version.c:4270 +#: ../version.c:4272 msgid " fall-back for $VIM: \"" msgstr "" -#: ../version.c:4276 +#: ../version.c:4278 msgid " f-b for $VIMRUNTIME: \"" msgstr "" -#: ../version.c:4280 +#: ../version.c:4282 msgid "Compilation: " msgstr "" -#: ../version.c:4286 +#: ../version.c:4288 msgid "Compiler: " msgstr "" -#: ../version.c:4291 +#: ../version.c:4293 msgid "Linking: " msgstr "" -#: ../version.c:4296 +#: ../version.c:4298 msgid " DEBUG BUILD" msgstr "" -#: ../version.c:4332 +#: ../version.c:4334 msgid "VIM - Vi IMproved" msgstr "" -#: ../version.c:4334 +#: ../version.c:4336 msgid "version " msgstr "" -#: ../version.c:4335 +#: ../version.c:4337 msgid "by Bram Moolenaar et al." msgstr "" -#: ../version.c:4339 +#: ../version.c:4341 msgid "Vim is open source and freely distributable" msgstr "" -#: ../version.c:4341 +#: ../version.c:4343 msgid "Help poor children in Uganda!" msgstr "" -#: ../version.c:4342 +#: ../version.c:4344 msgid "type :help iccf for information " msgstr "" -#: ../version.c:4344 +#: ../version.c:4346 msgid "type :q to exit " msgstr "" -#: ../version.c:4345 +#: ../version.c:4347 msgid "type :help or for on-line help" msgstr "" -#: ../version.c:4346 +#: ../version.c:4348 msgid "type :help version9 for version info" msgstr "" -#: ../version.c:4349 +#: ../version.c:4351 msgid "Running in Vi compatible mode" msgstr "" -#: ../version.c:4350 +#: ../version.c:4352 msgid "type :set nocp for Vim defaults" msgstr "" -#: ../version.c:4351 +#: ../version.c:4353 msgid "type :help cp-default for info on this" msgstr "" -#: ../version.c:4366 +#: ../version.c:4368 msgid "menu Help->Orphans for information " msgstr "" -#: ../version.c:4368 +#: ../version.c:4370 msgid "Running modeless, typed text is inserted" msgstr "" -#: ../version.c:4369 +#: ../version.c:4371 msgid "menu Edit->Global Settings->Toggle Insert Mode " msgstr "" -#: ../version.c:4370 +#: ../version.c:4372 msgid " for two modes " msgstr "" -#: ../version.c:4374 +#: ../version.c:4376 msgid "menu Edit->Global Settings->Toggle Vi Compatible" msgstr "" -#: ../version.c:4375 +#: ../version.c:4377 msgid " for Vim defaults " msgstr "" -#: ../version.c:4416 +#: ../version.c:4418 msgid "Sponsor Vim development!" msgstr "" -#: ../version.c:4417 +#: ../version.c:4419 msgid "Become a registered Vim user!" msgstr "" -#: ../version.c:4420 +#: ../version.c:4422 msgid "type :help sponsor for information " msgstr "" -#: ../version.c:4421 +#: ../version.c:4423 msgid "type :help register for information " msgstr "" -#: ../version.c:4423 +#: ../version.c:4425 msgid "menu Help->Sponsor/Register for information " msgstr "" diff --git a/src/version.c b/src/version.c index 31263512a1..4120e910fa 100644 --- a/src/version.c +++ b/src/version.c @@ -719,6 +719,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1556, /**/ 1555, /**/