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)
diff --git a/src/quickfix.c b/src/quickfix.c
index 463056b..7243a0c 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -1373,7 +1373,7 @@
/*
* 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?
@@ -2990,19 +2990,183 @@
}
/*
+ * Returns the number of valid entries in the current quickfix/location list.
+ */
+ int
+qf_get_size(eap)
+ exarg_T *eap;
+{
+ qf_info_T *qi = &ql_info;
+ qfline_T *qfp;
+ int i, sz = 0;
+ int prev_fnum = 0;
+
+ if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo)
+ {
+ /* Location list */
+ qi = GET_LOC_LIST(curwin);
+ if (qi == NULL)
+ return 0;
+ }
+
+ for (i = 0, qfp = qi->qf_lists[qi->qf_curlist].qf_start;
+ (i < qi->qf_lists[qi->qf_curlist].qf_count) && (qfp != NULL);
+ ++i, qfp = qfp->qf_next)
+ {
+ if (qfp->qf_valid)
+ {
+ if (eap->cmdidx == CMD_cdo || eap->cmdidx == CMD_ldo)
+ sz++; /* Count all valid entries */
+ 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.
+ */
+ int
+qf_get_cur_idx(eap)
+ exarg_T *eap;
+{
+ 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;
+ }
+
+ return qi->qf_lists[qi->qf_curlist].qf_index;
+}
+
+/*
+ * Returns the current index in the quickfix/location list (counting only valid
+ * entries). If no valid entries are in the list, then returns 1.
+ */
+ int
+qf_get_cur_valid_idx(eap)
+ exarg_T *eap;
+{
+ qf_info_T *qi = &ql_info;
+ qf_list_T *qfl;
+ qfline_T *qfp;
+ int i, eidx = 0;
+ int prev_fnum = 0;
+
+ if (eap->cmdidx == CMD_ldo || eap->cmdidx == CMD_lfdo)
+ {
+ /* Location list */
+ qi = GET_LOC_LIST(curwin);
+ if (qi == NULL)
+ return 1;
+ }
+
+ qfl = &qi->qf_lists[qi->qf_curlist];
+ qfp = qfl->qf_start;
+
+ /* check if the list has valid errors */
+ if (qfl->qf_count <= 0 || qfl->qf_nonevalid)
+ return 1;
+
+ for (i = 1; i <= qfl->qf_index && qfp!= NULL; i++, qfp = qfp->qf_next)
+ {
+ if (qfp->qf_valid)
+ {
+ 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 ? 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 int
+qf_get_nth_valid_entry(qi, n, fdo)
+ qf_info_T *qi;
+ int n;
+ int fdo;
+{
+ qf_list_T *qfl = &qi->qf_lists[qi->qf_curlist];
+ qfline_T *qfp = qfl->qf_start;
+ int i, eidx;
+ int prev_fnum = 0;
+
+ /* check if the list has valid errors */
+ if (qfl->qf_count <= 0 || qfl->qf_nonevalid)
+ return 1;
+
+ for (i = 1, eidx = 0; i <= 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;
+ }
+
+ if (i <= qfl->qf_count)
+ return i;
+ else
+ return 1;
+}
+
+/*
* ":cc", ":crewind", ":cfirst" and ":clast".
* ":ll", ":lrewind", ":lfirst" and ":llast".
+ * ":cdo", ":ldo", ":cfdo" and ":lfdo"
*/
void
ex_cc(eap)
exarg_T *eap;
{
qf_info_T *qi = &ql_info;
+ int errornr;
if (eap->cmdidx == CMD_ll
|| eap->cmdidx == CMD_lrewind
|| eap->cmdidx == CMD_lfirst
- || eap->cmdidx == CMD_llast)
+ || eap->cmdidx == CMD_llast
+ || eap->cmdidx == CMD_ldo
+ || eap->cmdidx == CMD_lfdo)
{
qi = GET_LOC_LIST(curwin);
if (qi == NULL)
@@ -3012,34 +3176,51 @@
}
}
- 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);
+ 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)
+ errornr = qf_get_nth_valid_entry(qi,
+ eap->addr_count > 0 ? (int)eap->line1 : 1,
+ eap->cmdidx == CMD_cfdo || eap->cmdidx == CMD_lfdo);
+
+ qf_jump(qi, 0, errornr, eap->forceit);
}
/*
* ":cnext", ":cnfile", ":cNext" and ":cprevious".
* ":lnext", ":lNext", ":lprevious", ":lnfile", ":lNfile" and ":lpfile".
+ * Also, used by ":cdo", ":ldo", ":cfdo" and ":lfdo" commands.
*/
void
ex_cnext(eap)
exarg_T *eap;
{
qf_info_T *qi = &ql_info;
+ int errornr;
if (eap->cmdidx == CMD_lnext
|| eap->cmdidx == CMD_lNext
|| eap->cmdidx == CMD_lprevious
|| eap->cmdidx == CMD_lnfile
|| eap->cmdidx == CMD_lNfile
- || eap->cmdidx == CMD_lpfile)
+ || eap->cmdidx == CMD_lpfile
+ || eap->cmdidx == CMD_ldo
+ || eap->cmdidx == CMD_lfdo)
{
qi = GET_LOC_LIST(curwin);
if (qi == NULL)
@@ -3049,15 +3230,24 @@
}
}
- qf_jump(qi, (eap->cmdidx == CMD_cnext || eap->cmdidx == CMD_lnext)
+ 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);
}
/*