To: vim_dev@googlegroups.com Subject: Patch 8.2.1741 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.1741 Problem: pathshorten() only supports using one character. Solution: Add an argument to control the length. (closes #7006) Files: runtime/doc/eval.txt, src/evalfunc.c, src/filepath.c, src/proto/filepath.pro, src/testdir/test_functions.vim *** ../vim-8.2.1740/runtime/doc/eval.txt 2020-09-22 21:55:16.210978678 +0200 --- runtime/doc/eval.txt 2020-09-25 22:41:50.968800452 +0200 *************** *** 2647,2653 **** nextnonblank({lnum}) Number line nr of non-blank line >= {lnum} nr2char({expr} [, {utf8}]) String single char with ASCII/UTF8 value {expr} or({expr}, {expr}) Number bitwise OR ! pathshorten({expr}) String shorten directory names in a path perleval({expr}) any evaluate |Perl| expression popup_atcursor({what}, {options}) Number create popup window near the cursor popup_beval({what}, {options}) Number create popup window for 'ballooneval' --- 2661,2667 ---- nextnonblank({lnum}) Number line nr of non-blank line >= {lnum} nr2char({expr} [, {utf8}]) String single char with ASCII/UTF8 value {expr} or({expr}, {expr}) Number bitwise OR ! pathshorten({expr} [, {len}]) String shorten directory names in a path perleval({expr}) any evaluate |Perl| expression popup_atcursor({what}, {options}) Number create popup window near the cursor popup_beval({what}, {options}) Number create popup window for 'ballooneval' *************** *** 7607,7619 **** :let bits = bits->or(0x80) ! pathshorten({expr}) *pathshorten()* Shorten directory names in the path {expr} 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: > :echo pathshorten('~/.vim/autoload/myfile.vim') < ~/.v/a/myfile.vim ~ It doesn't matter if the path exists or not. Can also be used as a |method|: > --- 7656,7672 ---- :let bits = bits->or(0x80) ! pathshorten({expr} [, {len}]) *pathshorten()* Shorten directory names in the path {expr} and return the result. The tail, the file name, is kept as-is. The other ! 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('~/.vim/autoload/myfile.vim') < ~/.v/a/myfile.vim ~ + > + :echo pathshorten('~/.vim/autoload/myfile.vim', 2) + < ~/.vi/au/myfile.vim ~ It doesn't matter if the path exists or not. Can also be used as a |method|: > *** ../vim-8.2.1740/src/evalfunc.c 2020-09-23 12:28:46.421898027 +0200 --- src/evalfunc.c 2020-09-25 22:28:04.710790114 +0200 *************** *** 779,785 **** {"nextnonblank", 1, 1, FEARG_1, ret_number, f_nextnonblank}, {"nr2char", 1, 2, FEARG_1, ret_string, f_nr2char}, {"or", 2, 2, FEARG_1, ret_number, f_or}, ! {"pathshorten", 1, 1, FEARG_1, ret_string, f_pathshorten}, {"perleval", 1, 1, FEARG_1, ret_any, #ifdef FEAT_PERL f_perleval --- 779,785 ---- {"nextnonblank", 1, 1, FEARG_1, ret_number, f_nextnonblank}, {"nr2char", 1, 2, FEARG_1, ret_string, f_nr2char}, {"or", 2, 2, FEARG_1, ret_number, f_or}, ! {"pathshorten", 1, 2, FEARG_1, ret_string, f_pathshorten}, {"perleval", 1, 1, FEARG_1, ret_any, #ifdef FEAT_PERL f_perleval *** ../vim-8.2.1740/src/filepath.c 2020-09-02 21:57:04.022422373 +0200 --- src/filepath.c 2020-09-25 22:39:30.341148104 +0200 *************** *** 1352,1366 **** --- 1352,1438 ---- } /* + * 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,1374 **** p = vim_strsave(p); rettv->vval.v_string = p; if (p != NULL) ! shorten_dir(p); } } --- 1440,1446 ---- p = vim_strsave(p); rettv->vval.v_string = p; if (p != NULL) ! shorten_dir_len(p, trim_len); } } *************** *** 2707,2753 **** } /* - * 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!. --- 2779,2784 ---- *** ../vim-8.2.1740/src/proto/filepath.pro 2020-06-01 16:09:30.266292734 +0200 --- src/proto/filepath.pro 2020-09-25 22:35:05.237796160 +0200 *************** *** 21,26 **** --- 21,27 ---- void f_globpath(typval_T *argvars, typval_T *rettv); void f_isdirectory(typval_T *argvars, typval_T *rettv); void f_mkdir(typval_T *argvars, typval_T *rettv); + void shorten_dir(char_u *str); void f_pathshorten(typval_T *argvars, typval_T *rettv); void f_readdir(typval_T *argvars, typval_T *rettv); void f_readdirex(typval_T *argvars, typval_T *rettv); *************** *** 40,46 **** char_u *get_past_head(char_u *path); int vim_ispathsep(int c); int vim_ispathsep_nocolon(int c); - void shorten_dir(char_u *str); int dir_of_file_exists(char_u *fname); int vim_fnamecmp(char_u *x, char_u *y); int vim_fnamencmp(char_u *x, char_u *y, size_t len); --- 41,46 ---- *** ../vim-8.2.1740/src/testdir/test_functions.vim 2020-09-23 22:38:01.503927513 +0200 --- src/testdir/test_functions.vim 2020-09-25 22:28:04.710790114 +0200 *************** *** 500,505 **** --- 500,523 ---- 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() *** ../vim-8.2.1740/src/version.c 2020-09-25 22:13:02.340553653 +0200 --- src/version.c 2020-09-25 22:32:20.066193012 +0200 *************** *** 752,753 **** --- 752,755 ---- { /* Add new patch number below this line */ + /**/ + 1741, /**/ -- Female engineers become irresistible at the age of consent and remain that way until about thirty minutes after their clinical death. Longer if it's a warm day. (Scott Adams - The Dilbert principle) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///