diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-09-25 22:42:48 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-09-25 22:42:48 +0200 |
commit | 6a33ef0deb5c75c003a9f3bd1c57f3ca5e77327e (patch) | |
tree | 1c34b542dbc6768a7fe26ffadabf0657d6a3d291 /src/filepath.c | |
parent | 58dbef330c42511f9d7d3b3990c73387041f3f3f (diff) | |
download | vim-git-6a33ef0deb5c75c003a9f3bd1c57f3ca5e77327e.tar.gz |
patch 8.2.1741: pathshorten() only supports using one characterv8.2.1741
Problem: pathshorten() only supports using one character.
Solution: Add an argument to control the length. (closes #7006)
Diffstat (limited to 'src/filepath.c')
-rw-r--r-- | src/filepath.c | 115 |
1 files changed, 73 insertions, 42 deletions
diff --git a/src/filepath.c b/src/filepath.c index bdd9098b8..197825db3 100644 --- a/src/filepath.c +++ b/src/filepath.c @@ -1352,15 +1352,87 @@ f_mkdir(typval_T *argvars, typval_T *rettv) } /* + * Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname" + * "trim_len" specifies how many characters to keep for each directory. + * Must be 1 or more. + * It's done in-place. + */ + static void +shorten_dir_len(char_u *str, int trim_len) +{ + char_u *tail, *s, *d; + int skip = FALSE; + int dirchunk_len = 0; + + tail = gettail(str); + d = str; + for (s = str; ; ++s) + { + if (s >= tail) // copy the whole tail + { + *d++ = *s; + if (*s == NUL) + break; + } + else if (vim_ispathsep(*s)) // copy '/' and next char + { + *d++ = *s; + skip = FALSE; + dirchunk_len = 0; + } + else if (!skip) + { + *d++ = *s; // copy next char + if (*s != '~' && *s != '.') // and leading "~" and "." + { + ++dirchunk_len; // only count word chars for the size + + // keep copying chars until we have our preferred length (or + // until the above if/else branches move us along) + if (dirchunk_len >= trim_len) + skip = TRUE; + } + + if (has_mbyte) + { + int l = mb_ptr2len(s); + + while (--l > 0) + *d++ = *++s; + } + } + } +} + +/* + * Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname" + * It's done in-place. + */ + void +shorten_dir(char_u *str) +{ + shorten_dir_len(str, 1); +} + +/* * "pathshorten()" function */ void f_pathshorten(typval_T *argvars, typval_T *rettv) { char_u *p; + int trim_len = 1; + + if (argvars[1].v_type != VAR_UNKNOWN) + { + trim_len = (int)tv_get_number(&argvars[1]); + if (trim_len < 1) + trim_len = 1; + } rettv->v_type = VAR_STRING; p = tv_get_string_chk(&argvars[0]); + if (p == NULL) rettv->vval.v_string = NULL; else @@ -1368,7 +1440,7 @@ f_pathshorten(typval_T *argvars, typval_T *rettv) p = vim_strsave(p); rettv->vval.v_string = p; if (p != NULL) - shorten_dir(p); + shorten_dir_len(p, trim_len); } } @@ -2707,47 +2779,6 @@ vim_ispathsep_nocolon(int c) } /* - * Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname" - * It's done in-place. - */ - void -shorten_dir(char_u *str) -{ - char_u *tail, *s, *d; - int skip = FALSE; - - tail = gettail(str); - d = str; - for (s = str; ; ++s) - { - if (s >= tail) // copy the whole tail - { - *d++ = *s; - if (*s == NUL) - break; - } - else if (vim_ispathsep(*s)) // copy '/' and next char - { - *d++ = *s; - skip = FALSE; - } - else if (!skip) - { - *d++ = *s; // copy next char - if (*s != '~' && *s != '.') // and leading "~" and "." - skip = TRUE; - if (has_mbyte) - { - int l = mb_ptr2len(s); - - while (--l > 0) - *d++ = *++s; - } - } - } -} - -/* * Return TRUE if the directory of "fname" exists, FALSE otherwise. * Also returns TRUE if there is no directory name. * "fname" must be writable!. |