aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-02-06 16:29:12 +0800
committerzeertzjq <zeertzjq@outlook.com>2022-02-06 16:29:12 +0800
commitd65ee129143fedd43178c9be52095b5d2d06b5c2 (patch)
treebbf175cc42425a37cbdef14efde2892bdb07683b
parent8215c05945054755b2c3cadae198894372dbfe0f (diff)
downloadrneovim-d65ee129143fedd43178c9be52095b5d2d06b5c2.tar.gz
rneovim-d65ee129143fedd43178c9be52095b5d2d06b5c2.tar.bz2
rneovim-d65ee129143fedd43178c9be52095b5d2d06b5c2.zip
vim-patch:8.2.1741: pathshorten() only supports using one character
Problem: pathshorten() only supports using one character. Solution: Add an argument to control the length. (closes vim/vim#7006) https://github.com/vim/vim/commit/6a33ef0deb5c75c003a9f3bd1c57f3ca5e77327e Cherry-pick a line in test from patch 8.2.0634. Use Nvim's config paths in docs. shorten_dir() returning a pointer looks a bit confusing here, as it is actually the same pointer passed to it, and it doesn't really reduce much code, so change it back to void. Assigning rettv->vval.v_string = NULL is not needed if a pointer is within 64 bits. While this is usually the case, I'm not sure if it can be taken for granted.
-rw-r--r--runtime/doc/builtin.txt12
-rw-r--r--src/nvim/eval.lua2
-rw-r--r--src/nvim/eval/funcs.c19
-rw-r--r--src/nvim/path.c29
-rw-r--r--src/nvim/screen.c2
-rw-r--r--src/nvim/testdir/test_functions.vim19
6 files changed, 65 insertions, 18 deletions
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index c68e86462d..56bc8bfb3e 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -314,7 +314,7 @@ nextnonblank({lnum}) Number line nr of non-blank line >= {lnum}
nr2char({expr}[, {utf8}]) String single char with ASCII/UTF-8 value {expr}
nvim_...({args}...) any call nvim |api| functions
or({expr}, {expr}) Number bitwise OR
-pathshorten({expr}) String shorten directory names in a path
+pathshorten({expr} [, {len}]) String shorten directory names in a path
perleval({expr}) any evaluate |perl| expression
pow({x}, {y}) Float {x} to the power of {y}
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
@@ -5204,13 +5204,17 @@ or({expr}, {expr}) *or()*
< Can also be used as a |method|: >
:let bits = bits->or(0x80)
-pathshorten({path}) *pathshorten()*
+pathshorten({expr} [, {len}]) *pathshorten()*
Shorten directory names in the path {path} and return the
result. The tail, the file name, is kept as-is. The other
- components in the path are reduced to single letters. Leading
- '~' and '.' characters are kept. Example: >
+ components in the path are reduced to {len} letters in length.
+ If {len} is omitted or smaller than 1 then 1 is used (single
+ letters). Leading '~' and '.' characters are kept. Examples: >
:echo pathshorten('~/.config/nvim/autoload/file1.vim')
< ~/.c/n/a/file1.vim ~
+>
+ :echo pathshorten('~/.config/nvim/autoload/file2.vim', 2)
+< ~/.co/nv/au/file2.vim ~
It doesn't matter if the path exists or not.
Can also be used as a |method|: >
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 5c85d764fb..eedc8ac45d 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -262,7 +262,7 @@ return {
nextnonblank={args=1, base=1},
nr2char={args={1, 2}, base=1},
['or']={args=2, base=1},
- pathshorten={args=1, base=1},
+ pathshorten={args={1, 2}, base=1},
pow={args=2, base=1},
prevnonblank={args=1, base=1},
printf={args=varargs(1), base=2},
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index edf6ed3c12..475c6bfffb 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -6846,12 +6846,23 @@ static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
+ 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;
- const char *const s = tv_get_string_chk(&argvars[0]);
- if (!s) {
- return;
+ const char_u *p = (char_u *)tv_get_string_chk(&argvars[0]);
+ if (p == NULL) {
+ rettv->vval.v_string = NULL;
+ } else {
+ rettv->vval.v_string = vim_strsave(p);
+ shorten_dir_len(rettv->vval.v_string, trim_len);
}
- rettv->vval.v_string = shorten_dir((char_u *)xstrdup(s));
}
/*
diff --git a/src/nvim/path.c b/src/nvim/path.c
index 39e276e0a5..fe564182d8 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -269,16 +269,17 @@ int vim_ispathlistsep(int c)
#endif
}
-/*
- * Shorten the path of a file from "~/foo/../.bar/fname" to "~/f/../.b/fname"
- * It's done in-place.
- */
-char_u *shorten_dir(char_u *str)
+/// 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.
+void shorten_dir_len(char_u *str, int trim_len)
{
char_u *tail = path_tail(str);
char_u *d = str;
bool skip = false;
- for (char_u *s = str;; ++s) {
+ int dirchunk_len = 0;
+ for (char_u *s = str;; s++) {
if (s >= tail) { // copy the whole tail
*d++ = *s;
if (*s == NUL) {
@@ -287,10 +288,16 @@ char_u *shorten_dir(char_u *str)
} 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 "."
- skip = true;
+ 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;
+ }
}
int l = utfc_ptr2len(s);
while (--l > 0) {
@@ -298,7 +305,13 @@ char_u *shorten_dir(char_u *str)
}
}
}
- return str;
+}
+
+/// 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);
}
/*
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 7e7115b6af..6b2a2afa41 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -7350,7 +7350,7 @@ void draw_tabline(void)
if (room > 0) {
// Get buffer name in NameBuff[]
get_trans_bufname(cwp->w_buffer);
- (void)shorten_dir(NameBuff);
+ shorten_dir(NameBuff);
len = vim_strsize(NameBuff);
p = NameBuff;
while (len > room) {
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index 6c2b0b97b6..438bed51c6 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -376,6 +376,25 @@ func Test_pathshorten()
call assert_equal('~.f/bar', pathshorten('~.foo/bar'))
call assert_equal('.~f/bar', pathshorten('.~foo/bar'))
call assert_equal('~/f/bar', pathshorten('~/foo/bar'))
+ call assert_fails('call pathshorten([])', 'E730:')
+
+ " test pathshorten with optional variable to set preferred size of shortening
+ call assert_equal('', pathshorten('', 2))
+ call assert_equal('foo', pathshorten('foo', 2))
+ call assert_equal('/foo', pathshorten('/foo', 2))
+ call assert_equal('fo/', pathshorten('foo/', 2))
+ call assert_equal('fo/bar', pathshorten('foo/bar', 2))
+ call assert_equal('fo/ba/foobar', pathshorten('foo/bar/foobar', 2))
+ call assert_equal('/fo/ba/foobar', pathshorten('/foo/bar/foobar', 2))
+ call assert_equal('.fo/bar', pathshorten('.foo/bar', 2))
+ call assert_equal('~fo/bar', pathshorten('~foo/bar', 2))
+ call assert_equal('~.fo/bar', pathshorten('~.foo/bar', 2))
+ call assert_equal('.~fo/bar', pathshorten('.~foo/bar', 2))
+ call assert_equal('~/fo/bar', pathshorten('~/foo/bar', 2))
+ call assert_fails('call pathshorten([],2)', 'E730:')
+ call assert_notequal('~/fo/bar', pathshorten('~/foo/bar', 3))
+ call assert_equal('~/foo/bar', pathshorten('~/foo/bar', 3))
+ call assert_equal('~/f/bar', pathshorten('~/foo/bar', 0))
endfunc
func Test_strpart()