diff options
| author | James McCoy <jamessan@jamessan.com> | 2017-02-27 14:35:57 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-02-27 14:35:57 -0500 | 
| commit | d290c1342117867d4fb1e8ffbe685037553971a5 (patch) | |
| tree | b72fbf5e641bc2558ac5f34f9bbc7f4cc57e4b27 /src | |
| parent | be65fd88f40cc0a955b25f7ef78bd954f3986046 (diff) | |
| parent | a989851e3b66cd1c14c6c674b83f302648df0b82 (diff) | |
| download | rneovim-d290c1342117867d4fb1e8ffbe685037553971a5.tar.gz rneovim-d290c1342117867d4fb1e8ffbe685037553971a5.tar.bz2 rneovim-d290c1342117867d4fb1e8ffbe685037553971a5.zip | |
Merge pull request #6188 from jamessan/vim-7.4.2200
vim-patch:7.4.2200
Closes #5314
Diffstat (limited to 'src')
| -rw-r--r-- | src/nvim/eval.c | 64 | ||||
| -rw-r--r-- | src/nvim/eval.lua | 4 | ||||
| -rw-r--r-- | src/nvim/quickfix.c | 184 | ||||
| -rw-r--r-- | src/nvim/tag.c | 2 | ||||
| -rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 39 | ||||
| -rw-r--r-- | src/nvim/version.c | 2 | 
6 files changed, 248 insertions, 47 deletions
| diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 942a82a040..672c9158ce 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -11065,6 +11065,37 @@ static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr)    get_buffer_lines(curbuf, lnum, end, retlist, rettv);  } +static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, +                            typval_T *rettv) +{ +  if (what_arg->v_type == VAR_UNKNOWN) { +    rettv_list_alloc(rettv); +    if (is_qf || wp != NULL) { +      (void)get_errorlist(wp, -1, rettv->vval.v_list); +    } +  } else { +    rettv_dict_alloc(rettv); +    if (is_qf || wp != NULL) { +      if (what_arg->v_type == VAR_DICT) { +        dict_T *d = what_arg->vval.v_dict; + +        if (d != NULL) { +          get_errorlist_properties(wp, d, rettv->vval.v_dict); +        } +      } else { +        EMSG(_(e_dictreq)); +      } +    } +  } +} + +/// "getloclist()" function +static void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ +  win_T *wp = find_win_by_nr(&argvars[0], NULL); +  get_qf_loc_list(false, wp, &argvars[1], rettv); +} +  /*   * "getmatches()" function   */ @@ -11166,20 +11197,10 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)    getpos_both(argvars, rettv, false);  } -/* - * "getqflist()" and "getloclist()" functions - */ +/// "getqflist()" functions  static void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr)  { -  rettv_list_alloc(rettv); -  win_T *wp = NULL; -  if (argvars[0].v_type != VAR_UNKNOWN) { /* getloclist() */ -    wp = find_win_by_nr(&argvars[0], NULL); -    if (wp == NULL) { -      return; -    } -  } -  (void)get_errorlist(wp, rettv->vval.v_list); +  get_qf_loc_list(true, NULL, &argvars[0], rettv);  }  /// "getreg()" function @@ -15721,7 +15742,7 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr)  /// Create quickfix/location list from VimL values  ///  /// Used by `setqflist()` and `setloclist()` functions. Accepts invalid -/// list_arg, action_arg and title_arg arguments in which case errors out, +/// list_arg, action_arg and what_arg arguments in which case errors out,  /// including VAR_UNKNOWN parameters.  ///  /// @param[in,out]  wp  Window to create location list for. May be NULL in @@ -15738,6 +15759,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)    char_u *title = NULL;    int action = ' ';    rettv->vval.v_number = -1; +  dict_T *d = NULL;    typval_T *list_arg = &args[0];    if (list_arg->v_type != VAR_LIST) { @@ -15765,10 +15787,16 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv)    if (title_arg->v_type == VAR_UNKNOWN) {      // Option argument was not given.      goto skip_args; -  } -  title = get_tv_string_chk(title_arg); -  if (!title) { -    // Type error. Error already printed by get_tv_string_chk(). +  } else if (title_arg->v_type == VAR_STRING) { +    title = get_tv_string_chk(title_arg); +    if (!title) { +      // Type error. Error already printed by get_tv_string_chk(). +      return; +    } +  } else if (title_arg->v_type == VAR_DICT) { +    d = title_arg->vval.v_dict; +  } else { +    EMSG(_(e_dictreq));      return;    } @@ -15778,7 +15806,7 @@ skip_args:    }    list_T *l = list_arg->vval.v_list; -  if (l && set_errorlist(wp, l, action, title) == OK) { +  if (l && set_errorlist(wp, l, action, title, d) == OK) {      rettv->vval.v_number = 0;    }  } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index b0bf417207..fa19ff209e 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -126,11 +126,11 @@ return {      getftime={args=1},      getftype={args=1},      getline={args={1, 2}}, -    getloclist={args=1, func='f_getqflist'}, +    getloclist={args={1, 2}},      getmatches={},      getpid={},      getpos={args=1}, -    getqflist={}, +    getqflist={args={0, 1}},      getreg={args={0, 3}},      getregtype={args={0, 1}},      gettabinfo={args={0, 1}}, diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 0da98713df..a4c3ec2430 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2637,6 +2637,19 @@ static buf_T *qf_find_buf(qf_info_T *qi)    return NULL;  } +/// Update the w:quickfix_title variable in the quickfix/location list window +static void qf_update_win_titlevar(qf_info_T *qi) +{ +  win_T *win; + +  if ((win = qf_find_win(qi)) != NULL) { +    win_T *curwin_save = curwin; +    curwin = win; +    qf_set_title_var(qi); +    curwin = curwin_save; +  } +} +  /*   * Find the quickfix buffer.  If it exists, update the contents.   */ @@ -2644,7 +2657,6 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)  {    buf_T       *buf;    win_T       *win; -  win_T       *curwin_save;    aco_save_T aco;    /* Check if a buffer for the quickfix list exists.  Update it. */ @@ -2657,12 +2669,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)        aucmd_prepbuf(&aco, buf);      } -    if ((win = qf_find_win(qi)) != NULL) { -      curwin_save = curwin; -      curwin = win; -      qf_set_title_var(qi); -      curwin = curwin_save; -    } +    qf_update_win_titlevar(qi);      qf_fill_buffer(qi, buf, old_last); @@ -3849,10 +3856,9 @@ static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start)    }  } -/* - * Add each quickfix error to list "list" as a dictionary. - */ -int get_errorlist(win_T *wp, list_T *list) +/// Add each quickfix error to list "list" as a dictionary. +/// If qf_idx is -1, use the current list. Otherwise, use the specified list. +int get_errorlist(win_T *wp, int qf_idx, list_T *list)  {    qf_info_T   *qi = &ql_info;    dict_T      *dict; @@ -3867,13 +3873,18 @@ int get_errorlist(win_T *wp, list_T *list)        return FAIL;    } -  if (qi->qf_curlist >= qi->qf_listcount -      || qi->qf_lists[qi->qf_curlist].qf_count == 0) +  if (qf_idx == -1) { +    qf_idx = qi->qf_curlist; +  } + +  if (qf_idx >= qi->qf_listcount +      || qi->qf_lists[qf_idx].qf_count == 0) {      return FAIL; +  } -  qfp = qi->qf_lists[qi->qf_curlist].qf_start; -  for (i = 1; !got_int && i <= qi->qf_lists[qi->qf_curlist].qf_count; ++i) { -    /* Handle entries with a non-existing buffer number. */ +  qfp = qi->qf_lists[qf_idx].qf_start; +  for (i = 1; !got_int && i <= qi->qf_lists[qf_idx].qf_count; i++) { +    // Handle entries with a non-existing buffer number.      bufnum = qfp->qf_fnum;      if (bufnum != 0 && (buflist_findnr(bufnum) == NULL))        bufnum = 0; @@ -3904,22 +3915,91 @@ int get_errorlist(win_T *wp, list_T *list)    return OK;  } -// Populate the quickfix list with the items supplied in the list -// of dictionaries. "title" will be copied to w:quickfix_title -// "action" is 'a' for add, 'r' for replace.  Otherwise create a new list. -int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) +/// Flags used by getqflist()/getloclist() to determine which fields to return. +enum { +  QF_GETLIST_NONE = 0x0, +  QF_GETLIST_TITLE = 0x1, +  QF_GETLIST_ITEMS = 0x2, +  QF_GETLIST_NR = 0x4, +  QF_GETLIST_WINID = 0x8, +  QF_GETLIST_ALL = 0xFF +}; + +/// Return quickfix/location list details (title) as a +/// dictionary. 'what' contains the details to return. If 'list_idx' is -1, +/// then current list is used. Otherwise the specified list is used. +int get_errorlist_properties(win_T *wp, dict_T *what, dict_T *retdict) +{ +  qf_info_T *qi = &ql_info; + +  if (wp != NULL) { +    qi = GET_LOC_LIST(wp); +    if (qi == NULL) { +      return FAIL; +    } +  } + +  int status = OK; +  dictitem_T *di; +  int flags = QF_GETLIST_NONE; + +  int 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) { +      qf_idx = di->di_tv.vval.v_number - 1; +      if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { +        return FAIL; +      } +      flags |= QF_GETLIST_NR; +    } 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 (flags & QF_GETLIST_TITLE) { +    char_u *t = qi->qf_lists[qf_idx].qf_title; +    if (t == NULL) { +      t = (char_u *)""; +    } +    status = dict_add_nr_str(retdict, "title", 0L, t); +  } +  if ((status == OK) && (flags & QF_GETLIST_NR)) { +    status = dict_add_nr_str(retdict, "nr", qf_idx + 1, NULL); +  } +  if ((status == OK) && (flags & QF_GETLIST_WINID)) { +    win_T *win = qf_find_win(qi); +    if (win != NULL) { +      status = dict_add_nr_str(retdict, "winid", win->handle, NULL); +    } +  } + +  return status; +} + +/// Add list of entries to quickfix/location list. Each list entry is +/// a dictionary with item information. +static int qf_add_entries(qf_info_T *qi, list_T *list, char_u *title, +                          int action)  {    listitem_T *li;    dict_T *d;    qfline_T *old_last = NULL;    int retval = OK; -  qf_info_T *qi = &ql_info;    bool did_bufnr_emsg = false; -  if (wp != NULL) { -    qi = ll_get_or_alloc_list(wp); -  } -    if (action == ' ' || qi->qf_curlist == qi->qf_listcount) {      // make place for a new list      qf_new_list(qi, title); @@ -4010,6 +4090,60 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title)    return retval;  } +static int qf_set_properties(qf_info_T *qi, dict_T *what) +{ +  dictitem_T *di; +  int retval = FAIL; + +  int 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) { +      qf_idx = di->di_tv.vval.v_number - 1; +      if (qf_idx < 0 || qf_idx >= qi->qf_listcount) { +        return FAIL; +      } +    } else { +      return FAIL; +    } +  } + +  if ((di = dict_find(what, (char_u *)"title", -1)) != NULL) { +    if (di->di_tv.v_type == VAR_STRING) { +      xfree(qi->qf_lists[qf_idx].qf_title); +      qi->qf_lists[qf_idx].qf_title = get_dict_string(what, "title", true); +      if (qf_idx == qi->qf_curlist) { +        qf_update_win_titlevar(qi); +      } +      retval = OK; +    } +  } + +  return retval; +} + +// Populate the quickfix list with the items supplied in the list +// of dictionaries. "title" will be copied to w:quickfix_title +// "action" is 'a' for add, 'r' for replace.  Otherwise create a new list. +int set_errorlist(win_T *wp, list_T *list, int action, char_u *title, +                  dict_T *what) +{ +  qf_info_T *qi = &ql_info; +  int retval = OK; + +  if (wp != NULL) { +    qi = ll_get_or_alloc_list(wp); +  } + +  if (what != NULL) { +    retval = qf_set_properties(qi, what); +  } else { +    retval = qf_add_entries(qi, list, title, action); +  } + +  return retval; +} +  /*   * ":[range]cbuffer [bufnr]" command.   * ":[range]caddbuffer [bufnr]" command. diff --git a/src/nvim/tag.c b/src/nvim/tag.c index cc5aac6094..59f4c1e968 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -789,7 +789,7 @@ do_tag (          }          vim_snprintf((char *)IObuff, IOSIZE, "ltag %s", tag); -        set_errorlist(curwin, list, ' ', IObuff); +        set_errorlist(curwin, list, ' ', IObuff, NULL);          list_free(list);          xfree(fname); diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 7464a11abd..0d6e5e1830 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -1462,3 +1462,42 @@ func Test_duplicate_buf()    call delete('Xgrepthis')  endfunc + +" Quickfix/Location list set/get properties tests +function Xproperty_tests(cchar) +    call s:setup_commands(a:cchar) + +    " Error cases +    call assert_fails('call g:Xgetlist(99)', 'E715:') +    call assert_fails('call g:Xsetlist(99)', 'E714:') +    call assert_fails('call g:Xsetlist([], "a", [])', 'E715:') + +    " Set and get the title +    Xopen +    wincmd p +    call g:Xsetlist([{'filename':'foo', 'lnum':27}]) +    call g:Xsetlist([], 'a', {'title' : 'Sample'}) +    let d = g:Xgetlist({"title":1}) +    call assert_equal('Sample', d.title) + +    Xopen +    call assert_equal('Sample', w:quickfix_title) +    Xclose + +    " Invalid arguments +    call assert_fails('call g:Xgetlist([])', 'E715') +    call assert_fails('call g:Xsetlist([], "a", [])', 'E715') +    let s = g:Xsetlist([], 'a', {'abc':1}) +    call assert_equal(-1, s) + +    call assert_equal({}, g:Xgetlist({'abc':1})) + +    if a:cchar == 'l' +	call assert_equal({}, getloclist(99, ['title'])) +    endif +endfunction + +function Test_qf_property() +    call Xproperty_tests('c') +    call Xproperty_tests('l') +endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index fe443ce01f..0374e02e02 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -240,7 +240,7 @@ static int included_patches[] = {    // 2203 NA    // 2202 NA    2201, -  // 2200, +  2200,    // 2199 NA    // 2198 NA    2197, | 
