diff options
author | Florian Walch <florian@fwalch.com> | 2015-12-03 20:14:51 +0100 |
---|---|---|
committer | Florian Walch <florian@fwalch.com> | 2015-12-24 08:08:50 +0100 |
commit | 7f99d210fd6bf92619f295a439ee4ac7e1a8f353 (patch) | |
tree | 9e40030f51d4d157e3b01825dfd645d2c500ba6e /src/nvim/quickfix.c | |
parent | 25eaacd10fea833c1f915a9ae69678d3d1dc7501 (diff) | |
download | rneovim-7f99d210fd6bf92619f295a439ee4ac7e1a8f353.tar.gz rneovim-7f99d210fd6bf92619f295a439ee4ac7e1a8f353.tar.bz2 rneovim-7f99d210fd6bf92619f295a439ee4ac7e1a8f353.zip |
vim-patch:7.4.858
Problem: It's a bit clumsy to execute a command on a list of matches.
Solution: Add the ":ldo", ":lfdo", ":cdo" and ":cfdo" commands. (Yegappan
Lakshmanan)
https://github.com/vim/vim/commit/aa23b379421aa214e6543b06c974594a25799b09
Diffstat (limited to 'src/nvim/quickfix.c')
-rw-r--r-- | src/nvim/quickfix.c | 220 |
1 files changed, 204 insertions, 16 deletions
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 8e6ae46a3b..3abf43cb8c 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1202,7 +1202,7 @@ static void qf_clean_dir_stack(struct dir_stack_T **stackptr) /* * Check in which directory of the directory stack the given file can be * found. - * Returns a pointer to the directory name or NULL if not found + * Returns a pointer to the directory name or NULL if not found. * Cleans up intermediate directory entries. * * TODO: How to solve the following problem? @@ -2571,9 +2571,159 @@ static char_u *get_mef_name(void) return name; } +/// Returns the number of valid entries in the current quickfix/location list. +size_t qf_get_size(exarg_T *eap) + FUNC_ATTR_NONNULL_ALL +{ + qf_info_T *qi = &ql_info; + if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) { + // Location list. + qi = GET_LOC_LIST(curwin); + if (qi == NULL) { + return 0; + } + } + + int prev_fnum = 0; + size_t sz = 0; + qfline_T *qfp; + size_t i; + assert(qi->qf_lists[qi->qf_curlist].qf_count >= 0); + for (i = 0, qfp = qi->qf_lists[qi->qf_curlist].qf_start; + i < (size_t)qi->qf_lists[qi->qf_curlist].qf_count && qfp != NULL; + i++, qfp = qfp->qf_next) { + if (!qfp->qf_valid) { + continue; + } + + if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo) { + // Count all valid entries. + sz++; + } else if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) { + // Count the number of files. + sz++; + prev_fnum = qfp->qf_fnum; + } + } + + return sz; +} + +/// Returns the current index of the quickfix/location list. +/// Returns 0 if there is an error. +size_t qf_get_cur_idx(exarg_T *eap) + FUNC_ATTR_NONNULL_ALL +{ + qf_info_T *qi = &ql_info; + + if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) { + // Location list. + qi = GET_LOC_LIST(curwin); + if (qi == NULL) { + return 0; + } + } + + assert(qi->qf_lists[qi->qf_curlist].qf_index >= 0); + return (size_t)qi->qf_lists[qi->qf_curlist].qf_index; +} + +/// Returns the current index in the quickfix/location list, +/// counting only valid entries. +/// Returns 1 if there are no valid entries. +int qf_get_cur_valid_idx(exarg_T *eap) + FUNC_ATTR_NONNULL_ALL +{ + qf_info_T *qi = &ql_info; + + if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo) { + // Location list. + qi = GET_LOC_LIST(curwin); + if (qi == NULL) { + return 1; + } + } + + qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist]; + + // Check if the list has valid errors. + if (qfl->qf_count <= 0 || qfl->qf_nonevalid) { + return 1; + } + + int prev_fnum = 0; + int eidx = 0; + qfline_T *qfp; + size_t i; + assert(qfl->qf_index >= 0); + for (i = 1, qfp = qfl->qf_start; + i <= (size_t)qfl->qf_index && qfp != NULL; + i++, qfp = qfp->qf_next) { + if (!qfp->qf_valid) { + continue; + } + + if (eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { + if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) { + // Count the number of files. + eidx++; + prev_fnum = qfp->qf_fnum; + } + } else { + eidx++; + } + } + + return eidx != 0 ? eidx : 1; +} + +/// Get the 'n'th valid error entry in the quickfix or location list. +/// +/// Used by :cdo, :ldo, :cfdo and :lfdo commands. +/// For :cdo and :ldo, returns the 'n'th valid error entry. +/// For :cfdo and :lfdo, returns the 'n'th valid file entry. +static size_t qf_get_nth_valid_entry(qf_info_T *qi, size_t n, bool fdo) + FUNC_ATTR_NONNULL_ALL +{ + qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist]; + + // Check if the list has valid errors. + if (qfl->qf_count <= 0 || qfl->qf_nonevalid) { + return 1; + } + + int prev_fnum = 0; + size_t eidx = 0; + size_t i; + qfline_T *qfp; + assert(qfl->qf_count >= 0); + for (i = 1, qfp = qfl->qf_start; + i <= (size_t)qfl->qf_count && qfp != NULL; + i++, qfp = qfp->qf_next) { + if (qfp->qf_valid) { + if (fdo) { + if (qfp->qf_fnum > 0 && qfp->qf_fnum != prev_fnum) { + // Count the number of files. + eidx++; + prev_fnum = qfp->qf_fnum; + } + } else { + eidx++; + } + } + + if (eidx == n) { + break; + } + } + + return i <= (size_t)qfl->qf_count ? i : 1; +} + /* * ":cc", ":crewind", ":cfirst" and ":clast". * ":ll", ":lrewind", ":lfirst" and ":llast". + * ":cdo", ":ldo", ":cfdo" and ":lfdo". */ void ex_cc(exarg_T *eap) { @@ -2582,7 +2732,10 @@ void ex_cc(exarg_T *eap) if (eap->cmdidx == CMD_ll || eap->cmdidx == CMD_lrewind || eap->cmdidx == CMD_lfirst - || eap->cmdidx == CMD_llast) { + || eap->cmdidx == CMD_llast + || eap->cmdidx == CMD_llast + || eap->cmdidx == CMD_ldo + || eap->cmdidx == CMD_lfdo) { qi = GET_LOC_LIST(curwin); if (qi == NULL) { EMSG(_(e_loclist)); @@ -2590,21 +2743,42 @@ void ex_cc(exarg_T *eap) } } - qf_jump(qi, 0, - eap->addr_count > 0 - ? (int)eap->line2 - : (eap->cmdidx == CMD_cc || eap->cmdidx == CMD_ll) - ? 0 - : (eap->cmdidx == CMD_crewind || eap->cmdidx == CMD_lrewind - || eap->cmdidx == CMD_cfirst || eap->cmdidx == CMD_lfirst) - ? 1 - : 32767, - eap->forceit); + int errornr; + if (eap->addr_count > 0) { + errornr = (int)eap->line2; + } else if (eap->cmdidx == CMD_cc || eap->cmdidx == CMD_ll) { + errornr = 0; + } else if (eap->cmdidx == CMD_crewind || eap->cmdidx == CMD_lrewind + || eap->cmdidx == CMD_cfirst || eap->cmdidx == CMD_lfirst) { + errornr = 1; + } else { + errornr = 32767; + } + + // For cdo and ldo commands, jump to the nth valid error. + // For cfdo and lfdo commands, jump to the nth valid file entry. + if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo || + eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) { + size_t n; + if (eap->addr_count > 0) { + assert(eap->line1 >= 0); + n = (size_t)eap->line1; + } else { + n = 1; + } + size_t valid_entry = qf_get_nth_valid_entry(qi, n, + eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo); + assert(valid_entry <= INT_MAX); + errornr = (int)valid_entry; + } + + qf_jump(qi, 0, errornr, eap->forceit); } /* * ":cnext", ":cnfile", ":cNext" and ":cprevious". * ":lnext", ":lNext", ":lprevious", ":lnfile", ":lNfile" and ":lpfile". + * ":cdo", ":ldo", ":cfdo" and ":lfdo". */ void ex_cnext(exarg_T *eap) { @@ -2615,7 +2789,10 @@ void ex_cnext(exarg_T *eap) || eap->cmdidx == CMD_lprevious || eap->cmdidx == CMD_lnfile || eap->cmdidx == CMD_lNfile - || eap->cmdidx == CMD_lpfile) { + || eap->cmdidx == CMD_lpfile + || eap->cmdidx == CMD_lpfile + || eap->cmdidx == CMD_ldo + || eap->cmdidx == CMD_lfdo) { qi = GET_LOC_LIST(curwin); if (qi == NULL) { EMSG(_(e_loclist)); @@ -2623,15 +2800,26 @@ void ex_cnext(exarg_T *eap) } } - qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext) + int errornr; + if (eap->addr_count > 0 && + (eap->cmdidx != CMD_cdo && eap->cmdidx != CMD_ldo && + eap->cmdidx != CMD_cfdo && eap->cmdidx != CMD_lfdo)) { + errornr = (int)eap->line2; + } else { + errornr = 1; + } + + qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext + || eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo) ? FORWARD - : (eap->cmdidx == CMD_cnfile || eap->cmdidx == CMD_lnfile) + : (eap->cmdidx == CMD_cnfile || eap->cmdidx == CMD_lnfile + || eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo) ? FORWARD_FILE : (eap->cmdidx == CMD_cpfile || eap->cmdidx == CMD_lpfile || eap->cmdidx == CMD_cNfile || eap->cmdidx == CMD_lNfile) ? BACKWARD_FILE : BACKWARD, - eap->addr_count > 0 ? (int)eap->line2 : 1, eap->forceit); + errornr, eap->forceit); } /* |