comparison src/quickfix.c @ 16505:28e3ba82d8c8 v8.1.1256

patch 8.1.1256: cannot navigate through errors relative to the cursor commit https://github.com/vim/vim/commit/3ff33114d70fc0f7e9c3187c5fec9028f6499cf3 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 3 21:56:35 2019 +0200 patch 8.1.1256: cannot navigate through errors relative to the cursor Problem: Cannot navigate through errors relative to the cursor. Solution: Add :cabove, :cbelow, :labove and :lbelow. (Yegappan Lakshmanan, closes #4316)
author Bram Moolenaar <Bram@vim.org>
date Fri, 03 May 2019 22:00:06 +0200
parents 393dd420a753
children 6e87a69b8e0c
comparison
equal deleted inserted replaced
16504:d70715c33e4f 16505:28e3ba82d8c8
175 static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last); 175 static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last);
176 static buf_T *load_dummy_buffer(char_u *fname, char_u *dirname_start, char_u *resulting_dir); 176 static buf_T *load_dummy_buffer(char_u *fname, char_u *dirname_start, char_u *resulting_dir);
177 static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start); 177 static void wipe_dummy_buffer(buf_T *buf, char_u *dirname_start);
178 static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start); 178 static void unload_dummy_buffer(buf_T *buf, char_u *dirname_start);
179 static qf_info_T *ll_get_or_alloc_list(win_T *); 179 static qf_info_T *ll_get_or_alloc_list(win_T *);
180 static char_u *e_no_more_items = (char_u *)N_("E553: No more items");
180 181
181 // Quickfix window check helper macro 182 // Quickfix window check helper macro
182 #define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL) 183 #define IS_QF_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref == NULL)
183 // Location list window check helper macro 184 // Location list window check helper macro
184 #define IS_LL_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL) 185 #define IS_LL_WINDOW(wp) (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)
1492 { 1493 {
1493 return qfl == NULL || qfl->qf_count <= 0; 1494 return qfl == NULL || qfl->qf_count <= 0;
1494 } 1495 }
1495 1496
1496 /* 1497 /*
1498 * Returns TRUE if the specified quickfix/location list is not empty and
1499 * has valid entries.
1500 */
1501 static int
1502 qf_list_has_valid_entries(qf_list_T *qfl)
1503 {
1504 return !qf_list_empty(qfl) && !qfl->qf_nonevalid;
1505 }
1506
1507 /*
1497 * Return a pointer to a list in the specified quickfix stack 1508 * Return a pointer to a list in the specified quickfix stack
1498 */ 1509 */
1499 static qf_list_T * 1510 static qf_list_T *
1500 qf_get_list(qf_info_T *qi, int idx) 1511 qf_get_list(qf_info_T *qi, int idx)
1501 { 1512 {
2698 { 2709 {
2699 qfline_T *qf_ptr = qfl->qf_ptr; 2710 qfline_T *qf_ptr = qfl->qf_ptr;
2700 int qf_idx = qfl->qf_index; 2711 int qf_idx = qfl->qf_index;
2701 qfline_T *prev_qf_ptr; 2712 qfline_T *prev_qf_ptr;
2702 int prev_index; 2713 int prev_index;
2703 static char_u *e_no_more_items = (char_u *)N_("E553: No more items");
2704 char_u *err = e_no_more_items; 2714 char_u *err = e_no_more_items;
2705 2715
2706 while (errornr--) 2716 while (errornr--)
2707 { 2717 {
2708 prev_qf_ptr = qf_ptr; 2718 prev_qf_ptr = qf_ptr;
4884 4894
4885 qfl = qf_get_curlist(qi); 4895 qfl = qf_get_curlist(qi);
4886 qfp = qfl->qf_start; 4896 qfp = qfl->qf_start;
4887 4897
4888 // check if the list has valid errors 4898 // check if the list has valid errors
4889 if (qfl->qf_count <= 0 || qfl->qf_nonevalid) 4899 if (!qf_list_has_valid_entries(qfl))
4890 return 1; 4900 return 1;
4891 4901
4892 for (i = 1; i <= qfl->qf_index && qfp!= NULL; i++, qfp = qfp->qf_next) 4902 for (i = 1; i <= qfl->qf_index && qfp!= NULL; i++, qfp = qfp->qf_next)
4893 { 4903 {
4894 if (qfp->qf_valid) 4904 if (qfp->qf_valid)
4922 qfline_T *qfp; 4932 qfline_T *qfp;
4923 int i, eidx; 4933 int i, eidx;
4924 int prev_fnum = 0; 4934 int prev_fnum = 0;
4925 4935
4926 // check if the list has valid errors 4936 // check if the list has valid errors
4927 if (qfl->qf_count <= 0 || qfl->qf_nonevalid) 4937 if (!qf_list_has_valid_entries(qfl))
4928 return 1; 4938 return 1;
4929 4939
4930 eidx = 0; 4940 eidx = 0;
4931 FOR_ALL_QFL_ITEMS(qfl, qfp, i) 4941 FOR_ALL_QFL_ITEMS(qfl, qfp, i)
4932 { 4942 {
5040 dir = FORWARD; 5050 dir = FORWARD;
5041 break; 5051 break;
5042 } 5052 }
5043 5053
5044 qf_jump(qi, dir, errornr, eap->forceit); 5054 qf_jump(qi, dir, errornr, eap->forceit);
5055 }
5056
5057 /*
5058 * Find the first entry in the quickfix list 'qfl' from buffer 'bnr'.
5059 * The index of the entry is stored in 'errornr'.
5060 * Returns NULL if an entry is not found.
5061 */
5062 static qfline_T *
5063 qf_find_first_entry_in_buf(qf_list_T *qfl, int bnr, int *errornr)
5064 {
5065 qfline_T *qfp = NULL;
5066 int idx = 0;
5067
5068 // Find the first entry in this file
5069 FOR_ALL_QFL_ITEMS(qfl, qfp, idx)
5070 if (qfp->qf_fnum == bnr)
5071 break;
5072
5073 *errornr = idx;
5074 return qfp;
5075 }
5076
5077 /*
5078 * Find the first quickfix entry on the same line as 'entry'. Updates 'errornr'
5079 * with the error number for the first entry. Assumes the entries are sorted in
5080 * the quickfix list by line number.
5081 */
5082 static qfline_T *
5083 qf_find_first_entry_on_line(qfline_T *entry, int *errornr)
5084 {
5085 while (!got_int
5086 && entry->qf_prev != NULL
5087 && entry->qf_fnum == entry->qf_prev->qf_fnum
5088 && entry->qf_lnum == entry->qf_prev->qf_lnum)
5089 {
5090 entry = entry->qf_prev;
5091 --*errornr;
5092 }
5093
5094 return entry;
5095 }
5096
5097 /*
5098 * Find the last quickfix entry on the same line as 'entry'. Updates 'errornr'
5099 * with the error number for the last entry. Assumes the entries are sorted in
5100 * the quickfix list by line number.
5101 */
5102 static qfline_T *
5103 qf_find_last_entry_on_line(qfline_T *entry, int *errornr)
5104 {
5105 while (!got_int &&
5106 entry->qf_next != NULL
5107 && entry->qf_fnum == entry->qf_next->qf_fnum
5108 && entry->qf_lnum == entry->qf_next->qf_lnum)
5109 {
5110 entry = entry->qf_next;
5111 ++*errornr;
5112 }
5113
5114 return entry;
5115 }
5116
5117 /*
5118 * Find the first quickfix entry below line 'lnum' in buffer 'bnr'.
5119 * 'qfp' points to the very first entry in the buffer and 'errornr' is the
5120 * index of the very first entry in the quickfix list.
5121 * Returns NULL if an entry is not found after 'lnum'.
5122 */
5123 static qfline_T *
5124 qf_find_entry_on_next_line(
5125 int bnr,
5126 linenr_T lnum,
5127 qfline_T *qfp,
5128 int *errornr)
5129 {
5130 if (qfp->qf_lnum > lnum)
5131 // First entry is after line 'lnum'
5132 return qfp;
5133
5134 // Find the entry just before or at the line 'lnum'
5135 while (qfp->qf_next != NULL
5136 && qfp->qf_next->qf_fnum == bnr
5137 && qfp->qf_next->qf_lnum <= lnum)
5138 {
5139 qfp = qfp->qf_next;
5140 ++*errornr;
5141 }
5142
5143 if (qfp->qf_next == NULL || qfp->qf_next->qf_fnum != bnr)
5144 // No entries found after 'lnum'
5145 return NULL;
5146
5147 // Use the entry just after line 'lnum'
5148 qfp = qfp->qf_next;
5149 ++*errornr;
5150
5151 return qfp;
5152 }
5153
5154 /*
5155 * Find the first quickfix entry before line 'lnum' in buffer 'bnr'.
5156 * 'qfp' points to the very first entry in the buffer and 'errornr' is the
5157 * index of the very first entry in the quickfix list.
5158 * Returns NULL if an entry is not found before 'lnum'.
5159 */
5160 static qfline_T *
5161 qf_find_entry_on_prev_line(
5162 int bnr,
5163 linenr_T lnum,
5164 qfline_T *qfp,
5165 int *errornr)
5166 {
5167 // Find the entry just before the line 'lnum'
5168 while (qfp->qf_next != NULL
5169 && qfp->qf_next->qf_fnum == bnr
5170 && qfp->qf_next->qf_lnum < lnum)
5171 {
5172 qfp = qfp->qf_next;
5173 ++*errornr;
5174 }
5175
5176 if (qfp->qf_lnum >= lnum) // entry is after 'lnum'
5177 return NULL;
5178
5179 // If multiple entries are on the same line, then use the first entry
5180 qfp = qf_find_first_entry_on_line(qfp, errornr);
5181
5182 return qfp;
5183 }
5184
5185 /*
5186 * Find a quickfix entry in 'qfl' closest to line 'lnum' in buffer 'bnr' in
5187 * the direction 'dir'.
5188 */
5189 static qfline_T *
5190 qf_find_closest_entry(
5191 qf_list_T *qfl,
5192 int bnr,
5193 linenr_T lnum,
5194 int dir,
5195 int *errornr)
5196 {
5197 qfline_T *qfp;
5198
5199 *errornr = 0;
5200
5201 // Find the first entry in this file
5202 qfp = qf_find_first_entry_in_buf(qfl, bnr, errornr);
5203 if (qfp == NULL)
5204 return NULL; // no entry in this file
5205
5206 if (dir == FORWARD)
5207 qfp = qf_find_entry_on_next_line(bnr, lnum, qfp, errornr);
5208 else
5209 qfp = qf_find_entry_on_prev_line(bnr, lnum, qfp, errornr);
5210
5211 return qfp;
5212 }
5213
5214 /*
5215 * Get the nth quickfix entry below the specified entry treating multiple
5216 * entries on a single line as one. Searches forward in the list.
5217 */
5218 static qfline_T *
5219 qf_get_nth_below_entry(qfline_T *entry, int *errornr, int n)
5220 {
5221 while (n-- > 0 && !got_int)
5222 {
5223 qfline_T *first_entry = entry;
5224 int first_errornr = *errornr;
5225
5226 // Treat all the entries on the same line in this file as one
5227 entry = qf_find_last_entry_on_line(entry, errornr);
5228
5229 if (entry->qf_next == NULL
5230 || entry->qf_next->qf_fnum != entry->qf_fnum)
5231 {
5232 // If multiple entries are on the same line, then use the first
5233 // entry
5234 entry = first_entry;
5235 *errornr = first_errornr;
5236 break;
5237 }
5238
5239 entry = entry->qf_next;
5240 ++*errornr;
5241 }
5242
5243 return entry;
5244 }
5245
5246 /*
5247 * Get the nth quickfix entry above the specified entry treating multiple
5248 * entries on a single line as one. Searches backwards in the list.
5249 */
5250 static qfline_T *
5251 qf_get_nth_above_entry(qfline_T *entry, int *errornr, int n)
5252 {
5253 while (n-- > 0 && !got_int)
5254 {
5255 if (entry->qf_prev == NULL
5256 || entry->qf_prev->qf_fnum != entry->qf_fnum)
5257 break;
5258
5259 entry = entry->qf_prev;
5260 --*errornr;
5261
5262 // If multiple entries are on the same line, then use the first entry
5263 entry = qf_find_first_entry_on_line(entry, errornr);
5264 }
5265
5266 return entry;
5267 }
5268
5269 /*
5270 * Find the n'th quickfix entry adjacent to line 'lnum' in buffer 'bnr' in the
5271 * specified direction.
5272 * Returns the error number in the quickfix list or 0 if an entry is not found.
5273 */
5274 static int
5275 qf_find_nth_adj_entry(qf_list_T *qfl, int bnr, linenr_T lnum, int n, int dir)
5276 {
5277 qfline_T *adj_entry;
5278 int errornr;
5279
5280 // Find an entry closest to the specified line
5281 adj_entry = qf_find_closest_entry(qfl, bnr, lnum, dir, &errornr);
5282 if (adj_entry == NULL)
5283 return 0;
5284
5285 if (--n > 0)
5286 {
5287 // Go to the n'th entry in the current buffer
5288 if (dir == FORWARD)
5289 adj_entry = qf_get_nth_below_entry(adj_entry, &errornr, n);
5290 else
5291 adj_entry = qf_get_nth_above_entry(adj_entry, &errornr, n);
5292 }
5293
5294 return errornr;
5295 }
5296
5297 /*
5298 * Jump to a quickfix entry in the current file nearest to the current line.
5299 * ":cabove", ":cbelow", ":labove" and ":lbelow" commands
5300 */
5301 void
5302 ex_cbelow(exarg_T *eap)
5303 {
5304 qf_info_T *qi;
5305 qf_list_T *qfl;
5306 int dir;
5307 int buf_has_flag;
5308 int errornr = 0;
5309
5310 if (eap->addr_count > 0 && eap->line2 <= 0)
5311 {
5312 emsg(_(e_invrange));
5313 return;
5314 }
5315
5316 // Check whether the current buffer has any quickfix entries
5317 if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow)
5318 buf_has_flag = BUF_HAS_QF_ENTRY;
5319 else
5320 buf_has_flag = BUF_HAS_LL_ENTRY;
5321 if (!(curbuf->b_has_qf_entry & buf_has_flag))
5322 {
5323 emsg(_(e_quickfix));
5324 return;
5325 }
5326
5327 if ((qi = qf_cmd_get_stack(eap, TRUE)) == NULL)
5328 return;
5329
5330 qfl = qf_get_curlist(qi);
5331 // check if the list has valid errors
5332 if (!qf_list_has_valid_entries(qfl))
5333 {
5334 emsg(_(e_quickfix));
5335 return;
5336 }
5337
5338 if (eap->cmdidx == CMD_cbelow || eap->cmdidx == CMD_lbelow)
5339 dir = FORWARD;
5340 else
5341 dir = BACKWARD;
5342
5343 errornr = qf_find_nth_adj_entry(qfl, curbuf->b_fnum, curwin->w_cursor.lnum,
5344 eap->addr_count > 0 ? eap->line2 : 0, dir);
5345
5346 if (errornr > 0)
5347 qf_jump(qi, 0, errornr, FALSE);
5348 else
5349 emsg(_(e_no_more_items));
5045 } 5350 }
5046 5351
5047 /* 5352 /*
5048 * Return the autocmd name for the :cfile Ex commands 5353 * Return the autocmd name for the :cfile Ex commands
5049 */ 5354 */