To: vim_dev@googlegroups.com Subject: Patch 8.1.0017 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0017 Problem: Shell command completion has duplicates. (Yegappan Lakshmanan) Solution: Use a hash table to avoid duplicates. (Ozaki Kiichi, closes #539, closes #2733) Files: src/ex_getln.c, src/testdir/test_cmdline.vim *** ../vim-8.1.0016/src/ex_getln.c 2018-05-13 18:28:45.000000000 +0200 --- src/ex_getln.c 2018-05-22 16:50:19.196716156 +0200 *************** *** 5147,5153 **** { char_u *pat; int i; ! char_u *path; int mustfree = FALSE; garray_T ga; char_u *buf = alloc(MAXPATHL); --- 5147,5153 ---- { char_u *pat; int i; ! char_u *path = NULL; int mustfree = FALSE; garray_T ga; char_u *buf = alloc(MAXPATHL); *************** *** 5156,5161 **** --- 5156,5164 ---- int flags = flagsarg; int ret; int did_curdir = FALSE; + hashtab_T found_ht; + hashitem_T *hi; + hash_T hash; if (buf == NULL) return FAIL; *************** *** 5169,5183 **** flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; ! /* For an absolute name we don't use $PATH. */ ! if (mch_isFullName(pat)) ! path = (char_u *)" "; ! else if ((pat[0] == '.' && (vim_ispathsep(pat[1]) ! || (pat[1] == '.' && vim_ispathsep(pat[2]))))) path = (char_u *)"."; else { ! path = vim_getenv((char_u *)"PATH", &mustfree); if (path == NULL) path = (char_u *)""; } --- 5172,5185 ---- flags |= EW_FILE | EW_EXEC | EW_SHELLCMD; ! if (pat[0] == '.' && (vim_ispathsep(pat[1]) ! || (pat[1] == '.' && vim_ispathsep(pat[2])))) path = (char_u *)"."; else { ! /* For an absolute name we don't use $PATH. */ ! if (!mch_isFullName(pat)) ! path = vim_getenv((char_u *)"PATH", &mustfree); if (path == NULL) path = (char_u *)""; } *************** *** 5188,5193 **** --- 5190,5196 ---- * current directory, to find "subdir/cmd". */ ga_init2(&ga, (int)sizeof(char *), 10); + hash_init(&found_ht); for (s = path; ; s = e) { if (*s == NUL) *************** *** 5200,5208 **** else if (*s == '.') did_curdir = TRUE; - if (*s == ' ') - ++s; /* Skip space used for absolute path name. */ - #if defined(MSWIN) e = vim_strchr(s, ';'); #else --- 5203,5208 ---- *************** *** 5229,5243 **** { for (i = 0; i < *num_file; ++i) { ! s = (*file)[i]; ! if (STRLEN(s) > l) { ! /* Remove the path again. */ ! STRMOVE(s, s + l); ! ((char_u **)ga.ga_data)[ga.ga_len++] = s; } ! else ! vim_free(s); } vim_free(*file); } --- 5229,5251 ---- { for (i = 0; i < *num_file; ++i) { ! char_u *name = (*file)[i]; ! ! if (STRLEN(name) > l) { ! // Check if this name was already found. ! hash = hash_hash(name + l); ! hi = hash_lookup(&found_ht, name + l, hash); ! if (HASHITEM_EMPTY(hi)) ! { ! // Remove the path that was prepended. ! STRMOVE(name, name + l); ! ((char_u **)ga.ga_data)[ga.ga_len++] = name; ! hash_add_item(&found_ht, hi, name, hash); ! name = NULL; ! } } ! vim_free(name); } vim_free(*file); } *************** *** 5252,5257 **** --- 5260,5266 ---- vim_free(pat); if (mustfree) vim_free(path); + hash_clear(&found_ht); return OK; } *** ../vim-8.1.0016/src/testdir/test_cmdline.vim 2018-05-12 13:15:47.000000000 +0200 --- src/testdir/test_cmdline.vim 2018-05-22 16:46:15.281766628 +0200 *************** *** 231,236 **** --- 231,245 ---- let l = getcompletion('not', 'mapclear') call assert_equal([], l) + let l = getcompletion('.', 'shellcmd') + call assert_equal(['./', '../'], l[0:1]) + call assert_equal(-1, match(l[2:], '^\.\.\?/$')) + let root = has('win32') ? 'C:\\' : '/' + let l = getcompletion(root, 'shellcmd') + let expected = map(filter(glob(root . '*', 0, 1), + \ 'isdirectory(v:val) || executable(v:val)'), 'isdirectory(v:val) ? v:val . ''/'' : v:val') + call assert_equal(expected, l) + if has('cscope') let l = getcompletion('', 'cscope') let cmds = ['add', 'find', 'help', 'kill', 'reset', 'show'] *************** *** 258,265 **** endif " For others test if the name is recognized. ! let names = ['buffer', 'environment', 'file_in_path', ! \ 'mapping', 'shellcmd', 'tag', 'tag_listfiles', 'user'] if has('cmdline_hist') call add(names, 'history') endif --- 267,273 ---- endif " For others test if the name is recognized. ! let names = ['buffer', 'environment', 'file_in_path', 'mapping', 'tag', 'tag_listfiles', 'user'] if has('cmdline_hist') call add(names, 'history') endif *** ../vim-8.1.0016/src/version.c 2018-05-21 22:50:22.514568516 +0200 --- src/version.c 2018-05-22 16:48:23.473237408 +0200 *************** *** 763,764 **** --- 763,766 ---- { /* Add new patch number below this line */ + /**/ + 17, /**/ -- ARTHUR: You are indeed brave Sir knight, but the fight is mine. BLACK KNIGHT: Had enough? ARTHUR: You stupid bastard. You havn't got any arms left. "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD /// 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 ///