To: vim_dev@googlegroups.com Subject: Patch 8.0.1389 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1389 Problem: getqflist() items are missing if not set, that makes it more difficult to handle the values. Solution: When a value is not available return zero or another invalid value. (Yegappan Lakshmanan, closes #2430) Files: runtime/doc/eval.txt, src/quickfix.c, src/testdir/test_quickfix.vim *** ../vim-8.0.1388/runtime/doc/eval.txt 2017-12-10 21:06:17.739851817 +0100 --- runtime/doc/eval.txt 2017-12-12 22:37:45.533011369 +0100 *************** *** 2331,2343 **** setcmdpos({pos}) Number set cursor position in command-line setfperm({fname}, {mode}) Number set {fname} file permissions to {mode} setline({lnum}, {line}) Number set line {lnum} to {line} ! setloclist({nr}, {list}[, {action}[, {what}]]) Number modify location list using {list} setmatches({list}) Number restore a list of matches setpos({expr}, {list}) Number set the {expr} position to {list} ! setqflist({list}[, {action}[, {what}]]) Number modify quickfix list using {list} ! setreg({n}, {v}[, {opt}]) Number set register to value and type settabvar({nr}, {varname}, {val}) none set {varname} in tab page {nr} to {val} settabwinvar({tabnr}, {winnr}, {varname}, {val}) none set {varname} in window {winnr} in tab --- 2331,2343 ---- setcmdpos({pos}) Number set cursor position in command-line setfperm({fname}, {mode}) Number set {fname} file permissions to {mode} setline({lnum}, {line}) Number set line {lnum} to {line} ! setloclist({nr}, {list} [, {action} [, {what}]]) Number modify location list using {list} setmatches({list}) Number restore a list of matches setpos({expr}, {list}) Number set the {expr} position to {list} ! setqflist({list} [, {action} [, {what}]]) Number modify quickfix list using {list} ! setreg({n}, {v} [, {opt}]) Number set register to value and type settabvar({nr}, {varname}, {val}) none set {varname} in tab page {nr} to {val} settabwinvar({tabnr}, {winnr}, {varname}, {val}) none set {varname} in window {winnr} in tab *************** *** 4564,4570 **** < To get lines from another buffer see |getbufline()| ! getloclist({nr}[, {what}]) *getloclist()* Returns a list with all the entries in the location list for window {nr}. {nr} can be the window number or the |window-ID|. When {nr} is zero the current window is used. --- 4574,4580 ---- < To get lines from another buffer see |getbufline()| ! getloclist({nr} [, {what}]) *getloclist()* Returns a list with all the entries in the location list for window {nr}. {nr} can be the window number or the |window-ID|. When {nr} is zero the current window is used. *************** *** 4677,4683 **** winid get the quickfix |window-ID| all all of the above quickfix properties Non-string items in {what} are ignored. To get the value of a ! particular item, set it to one. If "nr" is not present then the current quickfix list is used. If both "nr" and a non-zero "id" are specified, then the list specified by "id" is used. --- 4687,4693 ---- winid get the quickfix |window-ID| all all of the above quickfix properties Non-string items in {what} are ignored. To get the value of a ! particular item, set it to zero. If "nr" is not present then the current quickfix list is used. If both "nr" and a non-zero "id" are specified, then the list specified by "id" is used. *************** *** 4687,4703 **** When "lines" is specified, all the other items except "efm" are ignored. The returned dictionary contains the entry "items" with the list of entries. - In case of error processing {what}, an empty dictionary is - returned. The returned dictionary contains the following entries: ! context context information stored with |setqflist()| ! id quickfix list ID |quickfix-ID| ! idx index of the current entry in the list ! items quickfix list entries ! nr quickfix list number ! size number of entries in the quickfix list ! title quickfix list title text winid quickfix |window-ID|. If not present, set to 0 Examples: > --- 4697,4717 ---- When "lines" is specified, all the other items except "efm" are ignored. The returned dictionary contains the entry "items" with the list of entries. The returned dictionary contains the following entries: ! context context information stored with |setqflist()|. ! If not present, set to "". ! id quickfix list ID |quickfix-ID|. If not ! present, set to 0. ! idx index of the current entry in the list. If not ! present, set to 0. ! items quickfix list entries. If not present, set to ! an empty list. ! nr quickfix list number. If not present, set to 0 ! size number of entries in the quickfix list. If not ! present, set to 0. ! title quickfix list title text. If not present, set ! to "". winid quickfix |window-ID|. If not present, set to 0 Examples: > *** ../vim-8.0.1388/src/quickfix.c 2017-12-10 15:25:12.510523225 +0100 --- src/quickfix.c 2017-12-12 22:37:45.533011369 +0100 *************** *** 4863,4932 **** if (wp != NULL) qi = GET_LOC_LIST(wp); - /* List is not present or is empty */ - if (qi == NULL || qi->qf_listcount == 0) - { - /* If querying for the size of the list, return 0 */ - if (((di = dict_find(what, (char_u *)"nr", -1)) != NULL) - && (di->di_tv.v_type == VAR_STRING) - && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) - return dict_add_nr_str(retdict, "nr", 0, NULL); - return FAIL; - } - - qf_idx = qi->qf_curlist; /* default is the current list */ - if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) - { - /* Use the specified quickfix/location list */ - if (di->di_tv.v_type == VAR_NUMBER) - { - /* for zero use the current list */ - if (di->di_tv.vval.v_number != 0) - { - qf_idx = di->di_tv.vval.v_number - 1; - if (qf_idx < 0 || qf_idx >= qi->qf_listcount) - return FAIL; - } - } - else if ((di->di_tv.v_type == VAR_STRING) - && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) - /* Get the last quickfix list number */ - qf_idx = qi->qf_listcount - 1; - else - return FAIL; - flags |= QF_GETLIST_NR; - } - - if ((di = dict_find(what, (char_u *)"id", -1)) != NULL) - { - /* Look for a list with the specified id */ - if (di->di_tv.v_type == VAR_NUMBER) - { - /* For zero, use the current list or the list specifed by 'nr' */ - if (di->di_tv.vval.v_number != 0) - { - qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number); - if (qf_idx == -1) - return FAIL; /* List not found */ - } - flags |= QF_GETLIST_ID; - } - else - return FAIL; - } - if (dict_find(what, (char_u *)"all", -1) != NULL) flags |= QF_GETLIST_ALL; if (dict_find(what, (char_u *)"title", -1) != NULL) flags |= QF_GETLIST_TITLE; if (dict_find(what, (char_u *)"winid", -1) != NULL) flags |= QF_GETLIST_WINID; if (dict_find(what, (char_u *)"context", -1) != NULL) flags |= QF_GETLIST_CONTEXT; if (dict_find(what, (char_u *)"items", -1) != NULL) flags |= QF_GETLIST_ITEMS; --- 4863,4886 ---- if (wp != NULL) qi = GET_LOC_LIST(wp); if (dict_find(what, (char_u *)"all", -1) != NULL) flags |= QF_GETLIST_ALL; if (dict_find(what, (char_u *)"title", -1) != NULL) flags |= QF_GETLIST_TITLE; + if (dict_find(what, (char_u *)"nr", -1) != NULL) + flags |= QF_GETLIST_NR; + if (dict_find(what, (char_u *)"winid", -1) != NULL) flags |= QF_GETLIST_WINID; if (dict_find(what, (char_u *)"context", -1) != NULL) flags |= QF_GETLIST_CONTEXT; + if (dict_find(what, (char_u *)"id", -1) != NULL) + flags |= QF_GETLIST_ID; + if (dict_find(what, (char_u *)"items", -1) != NULL) flags |= QF_GETLIST_ITEMS; *************** *** 4936,4941 **** --- 4890,4966 ---- if (dict_find(what, (char_u *)"size", -1) != NULL) flags |= QF_GETLIST_SIZE; + if (qi != NULL && qi->qf_listcount != 0) + { + qf_idx = qi->qf_curlist; /* default is the current list */ + if ((di = dict_find(what, (char_u *)"nr", -1)) != NULL) + { + /* Use the specified quickfix/location list */ + if (di->di_tv.v_type == VAR_NUMBER) + { + /* for zero use the current list */ + if (di->di_tv.vval.v_number != 0) + { + qf_idx = di->di_tv.vval.v_number - 1; + if (qf_idx < 0 || qf_idx >= qi->qf_listcount) + qf_idx = -1; + } + } + else if ((di->di_tv.v_type == VAR_STRING) + && (STRCMP(di->di_tv.vval.v_string, "$") == 0)) + /* Get the last quickfix list number */ + qf_idx = qi->qf_listcount - 1; + else + qf_idx = -1; + flags |= QF_GETLIST_NR; + } + + if ((di = dict_find(what, (char_u *)"id", -1)) != NULL) + { + /* Look for a list with the specified id */ + if (di->di_tv.v_type == VAR_NUMBER) + { + /* + * For zero, use the current list or the list specifed by 'nr' + */ + if (di->di_tv.vval.v_number != 0) + qf_idx = qf_id2nr(qi, di->di_tv.vval.v_number); + flags |= QF_GETLIST_ID; + } + else + qf_idx = -1; + } + } + + /* List is not present or is empty */ + if (qi == NULL || qi->qf_listcount == 0 || qf_idx == -1) + { + if (flags & QF_GETLIST_TITLE) + status = dict_add_nr_str(retdict, "title", 0L, (char_u *)""); + if ((status == OK) && (flags & QF_GETLIST_ITEMS)) + { + list_T *l = list_alloc(); + if (l != NULL) + status = dict_add_list(retdict, "items", l); + else + status = FAIL; + } + if ((status == OK) && (flags & QF_GETLIST_NR)) + status = dict_add_nr_str(retdict, "nr", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_WINID)) + status = dict_add_nr_str(retdict, "winid", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_CONTEXT)) + status = dict_add_nr_str(retdict, "context", 0L, (char_u *)""); + if ((status == OK) && (flags & QF_GETLIST_ID)) + status = dict_add_nr_str(retdict, "id", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_IDX)) + status = dict_add_nr_str(retdict, "idx", 0L, NULL); + if ((status == OK) && (flags & QF_GETLIST_SIZE)) + status = dict_add_nr_str(retdict, "size", 0L, NULL); + + return status; + } + if (flags & QF_GETLIST_TITLE) { char_u *t; *** ../vim-8.0.1388/src/testdir/test_quickfix.vim 2017-12-10 15:25:12.510523225 +0100 --- src/testdir/test_quickfix.vim 2017-12-12 22:37:45.537011341 +0100 *************** *** 1833,1840 **** call assert_equal(-1, s) call assert_equal({}, g:Xgetlist({'abc':1})) ! call assert_equal({}, g:Xgetlist({'nr':99, 'title':1})) ! call assert_equal({}, g:Xgetlist({'nr':[], 'title':1})) if a:cchar == 'l' call assert_equal({}, getloclist(99, {'title': 1})) --- 1833,1840 ---- call assert_equal(-1, s) call assert_equal({}, g:Xgetlist({'abc':1})) ! call assert_equal('', g:Xgetlist({'nr':99, 'title':1}).title) ! call assert_equal('', g:Xgetlist({'nr':[], 'title':1}).title) if a:cchar == 'l' call assert_equal({}, getloclist(99, {'title': 1})) *************** *** 1870,1876 **** call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context) only call setloclist(0, [], 'f') ! call assert_equal({}, getloclist(0, {'context':1})) endif " Test for changing the context of previous quickfix lists --- 1870,1876 ---- call assert_equal([1, 2], getloclist(w2_id, {'context':1}).context) only call setloclist(0, [], 'f') ! call assert_equal('', getloclist(0, {'context':1}).context) endif " Test for changing the context of previous quickfix lists *************** *** 2383,2390 **** call g:Xsetlist([], 'f') call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) ! call assert_equal(1, len(g:Xgetlist({'nr':'$', 'all':1}))) ! call assert_equal(0, len(g:Xgetlist({'nr':0}))) Xexpr "File1:10:Line1" Xexpr "File2:20:Line2" --- 2383,2390 ---- call g:Xsetlist([], 'f') call assert_equal(0, g:Xgetlist({'nr':'$'}).nr) ! call assert_equal('', g:Xgetlist({'nr':'$', 'all':1}).title) ! call assert_equal(0, g:Xgetlist({'nr':0}).nr) Xexpr "File1:10:Line1" Xexpr "File2:20:Line2" *************** *** 2754,2760 **** call s:setup_commands(a:cchar) call g:Xsetlist([], 'f') ! call assert_equal({}, g:Xgetlist({'id':0})) Xexpr '' let start_id = g:Xgetlist({'id' : 0}).id Xexpr '' | Xexpr '' --- 2754,2760 ---- call s:setup_commands(a:cchar) call g:Xsetlist([], 'f') ! call assert_equal(0, g:Xgetlist({'id':0}).id) Xexpr '' let start_id = g:Xgetlist({'id' : 0}).id Xexpr '' | Xexpr '' *************** *** 2762,2771 **** call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id) call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id) call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id) ! call assert_equal({}, g:Xgetlist({'id':0, 'nr':99})) call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr) ! call assert_equal({}, g:Xgetlist({'id':99, 'nr':0})) ! call assert_equal({}, g:Xgetlist({'id':"abc", 'nr':0})) call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]}) call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context) --- 2762,2771 ---- call assert_equal(start_id, g:Xgetlist({'id':0, 'nr':1}).id) call assert_equal(start_id + 1, g:Xgetlist({'id':0, 'nr':0}).id) call assert_equal(start_id + 2, g:Xgetlist({'id':0, 'nr':'$'}).id) ! call assert_equal(0, g:Xgetlist({'id':0, 'nr':99}).id) call assert_equal(2, g:Xgetlist({'id':start_id + 1, 'nr':0}).nr) ! call assert_equal(0, g:Xgetlist({'id':99, 'nr':0}).id) ! call assert_equal(0, g:Xgetlist({'id':"abc", 'nr':0}).id) call g:Xsetlist([], 'a', {'id':start_id, 'context':[1,2]}) call assert_equal([1,2], g:Xgetlist({'nr':1, 'context':1}).context) *************** *** 2776,2782 **** let qfid = g:Xgetlist({'id':0, 'nr':0}) call g:Xsetlist([], 'f') ! call assert_equal({}, g:Xgetlist({'id':qfid, 'nr':0})) endfunc func Test_qf_id() --- 2776,2782 ---- let qfid = g:Xgetlist({'id':0, 'nr':0}) call g:Xsetlist([], 'f') ! call assert_equal(0, g:Xgetlist({'id':qfid, 'nr':0}).id) endfunc func Test_qf_id() *************** *** 2880,2882 **** --- 2880,2941 ---- call Xqfjump_tests('c') call Xqfjump_tests('l') endfunc + + " Tests for the getqflist() and getloclist() functions when the list is not + " present or is empty + func Xgetlist_empty_tests(cchar) + call s:setup_commands(a:cchar) + + " Empty quickfix stack + call g:Xsetlist([], 'f') + call assert_equal('', g:Xgetlist({'context' : 0}).context) + call assert_equal(0, g:Xgetlist({'id' : 0}).id) + call assert_equal(0, g:Xgetlist({'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'items' : 0}).items) + call assert_equal(0, g:Xgetlist({'nr' : 0}).nr) + call assert_equal(0, g:Xgetlist({'size' : 0}).size) + call assert_equal('', g:Xgetlist({'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'winid' : 0}).winid) + call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'all' : 0})) + + " Empty quickfix list + Xexpr "" + call assert_equal('', g:Xgetlist({'context' : 0}).context) + call assert_notequal(0, g:Xgetlist({'id' : 0}).id) + call assert_equal(0, g:Xgetlist({'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'items' : 0}).items) + call assert_notequal(0, g:Xgetlist({'nr' : 0}).nr) + call assert_equal(0, g:Xgetlist({'size' : 0}).size) + call assert_notequal('', g:Xgetlist({'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'winid' : 0}).winid) + + let qfid = g:Xgetlist({'id' : 0}).id + call g:Xsetlist([], 'f') + + " Non-existing quickfix identifier + call assert_equal('', g:Xgetlist({'id' : qfid, 'context' : 0}).context) + call assert_equal(0, g:Xgetlist({'id' : qfid}).id) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'id' : qfid, 'items' : 0}).items) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'nr' : 0}).nr) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'size' : 0}).size) + call assert_equal('', g:Xgetlist({'id' : qfid, 'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'id' : qfid, 'winid' : 0}).winid) + call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'id' : qfid, 'all' : 0})) + + " Non-existing quickfix list number + call assert_equal('', g:Xgetlist({'nr' : 5, 'context' : 0}).context) + call assert_equal(0, g:Xgetlist({'nr' : 5}).nr) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'idx' : 0}).idx) + call assert_equal([], g:Xgetlist({'nr' : 5, 'items' : 0}).items) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'id' : 0}).id) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'size' : 0}).size) + call assert_equal('', g:Xgetlist({'nr' : 5, 'title' : 0}).title) + call assert_equal(0, g:Xgetlist({'nr' : 5, 'winid' : 0}).winid) + call assert_equal({'context' : '', 'id' : 0, 'idx' : 0, 'items' : [], 'nr' : 0, 'size' : 0, 'title' : '', 'winid' : 0}, g:Xgetlist({'nr' : 5, 'all' : 0})) + endfunc + + func Test_getqflist() + call Xgetlist_empty_tests('c') + call Xgetlist_empty_tests('l') + endfunc *** ../vim-8.0.1388/src/version.c 2017-12-12 22:29:26.968498598 +0100 --- src/version.c 2017-12-12 22:42:43.882853940 +0100 *************** *** 773,774 **** --- 773,776 ---- { /* Add new patch number below this line */ + /**/ + 1389, /**/ -- From "know your smileys": :-E Has major dental problems /// 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 ///