mirror of
https://github.com/neovim/neovim.git
synced 2026-07-09 10:59:38 +00:00
refactor(path): path_skip_sep() #40524
Problem: Redundant code. Solution: Add path_skip_sep() and use it. Dropping MB_PTR_ADV is safe: the loops only advance while `*p` is a one-byte separator (`/`, `\`, `:`). MB_PTR_ADV was needed in legacy Vim because it supported non-UTF-8 (DBCS) *internal* encodings.
This commit is contained in:
@@ -340,6 +340,7 @@ UI
|
||||
|
||||
VIMSCRIPT
|
||||
|
||||
• `fnamemodify(':h')` preserves logical roots for more path formats.
|
||||
• |v:exitreason| is set before |QuitPre|.
|
||||
• |v:startreason| indicates whether Nvim started normally or by |:restart|.
|
||||
• |v:starttime| is the process start time (nanoseconds since UNIX epoch).
|
||||
@@ -369,7 +370,6 @@ These existing features changed their behavior.
|
||||
• Markdown inline highlighting now conceals the backslash in backslash escapes.
|
||||
• Markdown inline backslash escapes and hard line breaks no longer use the
|
||||
`@string.escape` capture.
|
||||
• `fnamemodify(':h')` preserves logical roots for more path formats.
|
||||
|
||||
==============================================================================
|
||||
REMOVED FEATURES *news-removed*
|
||||
|
||||
@@ -1202,14 +1202,6 @@ bool os_fileinfo(const char *path, FileInfo *file_info)
|
||||
return os_stat(path, &(file_info->stat)) == kLibuvSuccess;
|
||||
}
|
||||
|
||||
static const char *path_skip_sep(const char *path)
|
||||
{
|
||||
while (*path != NUL && vim_ispathsep_nocolon(*path)) {
|
||||
path++;
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/// Parses `path` into a `FileInfo` structure.
|
||||
///
|
||||
/// TODO(ntdiary): Could be extended for path.c cleanup and path normalization
|
||||
@@ -1223,15 +1215,15 @@ bool os_fileinfo2(const char *path, FileInfo *info)
|
||||
if (path_with_url(path)) {
|
||||
return true;
|
||||
}
|
||||
// Preserves the leading two "/"; runs of 3+ "/" collapse to a single "/" (IEEE 1003.1).
|
||||
// The same rule applies to kPathUNC and kPathGeneric on Windows, but not to kPathDevice
|
||||
// or kPathDeviceUNC, where the leading "//" is significant.
|
||||
const char *p = path_skip_sep(path);
|
||||
// Preserves the leading two "/"; 3+ "///…" collapse to a single "/" (IEEE 1003.1).
|
||||
// Same rule applies to kPathUNC/kPathGeneric on Windows, but not to kPathDevice or
|
||||
// kPathDeviceUNC, where the leading "//" is significant.
|
||||
const char *p = path_skip_sep(path, false);
|
||||
size_t leading_slashes = (size_t)(p - path);
|
||||
#ifdef MSWIN
|
||||
if (leading_slashes == 0 && ASCII_ISALPHA(p[0]) && p[1] == ':') {
|
||||
info->type = kPathDrive;
|
||||
p = path_skip_sep(p + 2);
|
||||
p = path_skip_sep(p + 2, false);
|
||||
info->rest_off = (size_t)(p - path);
|
||||
return true;
|
||||
}
|
||||
@@ -1241,10 +1233,10 @@ bool os_fileinfo2(const char *path, FileInfo *info)
|
||||
}
|
||||
info->type = kPathDevice;
|
||||
info->prefix_off = leading_slashes - 2;
|
||||
p = path_skip_sep(p + 2);
|
||||
p = path_skip_sep(p + 2, false);
|
||||
if (vim_strnicmp_asc(p, "unc", 3) == 0 && vim_ispathsep_nocolon(p[3])) {
|
||||
info->type = kPathDeviceUNC;
|
||||
p = path_skip_sep(p + 4);
|
||||
p = path_skip_sep(p + 4, false);
|
||||
info->root_off = (size_t)(p - path);
|
||||
goto server;
|
||||
}
|
||||
@@ -1252,15 +1244,15 @@ bool os_fileinfo2(const char *path, FileInfo *info)
|
||||
if (ASCII_ISALPHA(p[0]) && p[1] == ':') {
|
||||
p += 2;
|
||||
}
|
||||
p = path_skip_sep(path_next_component(p));
|
||||
p = path_skip_sep(path_next_component(p), false);
|
||||
info->rest_off = (size_t)(p - path);
|
||||
return true;
|
||||
}
|
||||
if (leading_slashes == 2) {
|
||||
info->type = kPathUNC;
|
||||
server:
|
||||
p = path_skip_sep(path_next_component(p));
|
||||
p = path_skip_sep(path_next_component(p));
|
||||
p = path_skip_sep(path_next_component(p), false);
|
||||
p = path_skip_sep(path_next_component(p), false);
|
||||
info->rest_off = (size_t)(p - path);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -188,7 +188,7 @@ const char *invocation_path_tail(const char *invocation, size_t *len)
|
||||
return tail;
|
||||
}
|
||||
|
||||
/// Get the next path component of a path name.
|
||||
/// Get the next separator-delimited component of a path name.
|
||||
///
|
||||
/// @param fname A file path. (Must be != NULL.)
|
||||
/// @return Pointer to first found path separator + 1.
|
||||
@@ -205,6 +205,20 @@ const char *path_next_component(const char *fname)
|
||||
return fname;
|
||||
}
|
||||
|
||||
/// Advances past consecutive path separators.
|
||||
///
|
||||
/// @param path Position in a path.
|
||||
/// @param colon Whether ':' counts as a separator on MS-Windows (see vim_ispathsep()).
|
||||
/// @return Pointer to the first non-separator byte (or terminating NUL).
|
||||
char *path_skip_sep(const char *path, bool colon)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_PURE
|
||||
{
|
||||
while (colon ? vim_ispathsep(*path) : vim_ispathsep_nocolon(*path)) {
|
||||
path++;
|
||||
}
|
||||
return (char *)path;
|
||||
}
|
||||
|
||||
/// Returns the length of the path head on the current platform.
|
||||
/// @return
|
||||
/// - 3 on windows
|
||||
@@ -249,9 +263,7 @@ char *get_past_head(const char *path)
|
||||
}
|
||||
#endif
|
||||
|
||||
while (vim_ispathsep(*retval)) {
|
||||
retval++;
|
||||
}
|
||||
retval = path_skip_sep(retval, true);
|
||||
|
||||
return (char *)retval;
|
||||
}
|
||||
@@ -1006,9 +1018,7 @@ static char *get_path_cutoff(char *fname, garray_T *gap)
|
||||
|
||||
// skip to the file or directory name
|
||||
if (cutoff != NULL) {
|
||||
while (vim_ispathsep(*cutoff)) {
|
||||
MB_PTR_ADV(cutoff);
|
||||
}
|
||||
cutoff = path_skip_sep(cutoff, true);
|
||||
}
|
||||
|
||||
return cutoff;
|
||||
@@ -1642,9 +1652,7 @@ size_t simplify_filename(char *filename)
|
||||
|
||||
if (vim_ispathsep(*p)) {
|
||||
relative = false;
|
||||
do {
|
||||
p++;
|
||||
} while (vim_ispathsep(*p));
|
||||
p = path_skip_sep(p, true);
|
||||
}
|
||||
char *start = p; // remember start after "c:/" or "/" or "///"
|
||||
char *p_end = p + strlen(p); // point to NUL at end of string "p"
|
||||
@@ -1674,9 +1682,7 @@ size_t simplify_filename(char *filename)
|
||||
// of an absolute path name.
|
||||
char *tail = p + 1;
|
||||
if (p[1] != NUL) {
|
||||
while (vim_ispathsep(*tail)) {
|
||||
MB_PTR_ADV(tail);
|
||||
}
|
||||
tail = path_skip_sep(tail, true);
|
||||
} else if (p > start) {
|
||||
p--; // strip preceding path separator
|
||||
}
|
||||
@@ -1686,10 +1692,7 @@ size_t simplify_filename(char *filename)
|
||||
} else if (p[0] == '.' && p[1] == '.'
|
||||
&& (vim_ispathsep(p[2]) || p[2] == NUL)) {
|
||||
// Skip to after ".." or "../" or "..///".
|
||||
char *tail = p + 2;
|
||||
while (vim_ispathsep(*tail)) {
|
||||
MB_PTR_ADV(tail);
|
||||
}
|
||||
char *tail = path_skip_sep(p + 2, true);
|
||||
|
||||
if (components > 0) { // strip one preceding component
|
||||
bool do_strip = false;
|
||||
@@ -2175,10 +2178,8 @@ char *path_shorten_fname(char *full_path, char *dir_name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
do {
|
||||
p++;
|
||||
} while (vim_ispathsep_nocolon(*p));
|
||||
return p;
|
||||
// Skip the matched separator, then any following separators (but not a colon).
|
||||
return path_skip_sep(p + 1, false);
|
||||
}
|
||||
|
||||
/// Invoke expand_wildcards() for one pattern
|
||||
|
||||
Reference in New Issue
Block a user