diff options
author | Bram Moolenaar <Bram@vim.org> | 2004-12-29 20:58:21 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2004-12-29 20:58:21 +0000 |
commit | 81695250ef1bbc02016078044ac268129a33f333 (patch) | |
tree | c31ec7182b5b06ffeb5a14b79701127eaa5c0dc8 /src/quickfix.c | |
parent | 86b68359978c933419279e599d0a8cf536095d77 (diff) | |
download | vim-git-81695250ef1bbc02016078044ac268129a33f333.tar.gz |
updated for version 7.0026
Diffstat (limited to 'src/quickfix.c')
-rw-r--r-- | src/quickfix.c | 213 |
1 files changed, 182 insertions, 31 deletions
diff --git a/src/quickfix.c b/src/quickfix.c index dbde1550f..fd6eba648 100644 --- a/src/quickfix.c +++ b/src/quickfix.c @@ -105,6 +105,9 @@ static void qf_update_buffer __ARGS((void)); static void qf_fill_buffer __ARGS((void)); #endif static char_u *get_mef_name __ARGS((void)); +static buf_T *load_dummy_buffer __ARGS((char_u *fname)); +static void wipe_dummy_buffer __ARGS((buf_T *buf)); +static void unload_dummy_buffer __ARGS((buf_T *buf)); /* * Read the errorfile "efile" into memory, line by line, building the error @@ -2063,10 +2066,10 @@ buf_hide(buf) * Return TRUE when using ":vimgrep" for ":grep". */ int -grep_internal(eap) - exarg_T *eap; +grep_internal(cmdidx) + cmdidx_T cmdidx; { - return ((eap->cmdidx == CMD_grep || eap->cmdidx == CMD_grepadd) + return ((cmdidx == CMD_grep || cmdidx == CMD_grepadd) && STRCMP("internal", *curbuf->b_p_gp == NUL ? p_gp : curbuf->b_p_gp) == 0); } @@ -2083,7 +2086,7 @@ ex_make(eap) unsigned len; /* Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". */ - if (grep_internal(eap)) + if (grep_internal(eap->cmdidx)) { ex_vimgrep(eap); return; @@ -2249,35 +2252,50 @@ ex_cfile(eap) ex_vimgrep(eap) exarg_T *eap; { - regmatch_T regmatch; + regmmatch_T regmatch; char_u *save_cpo; int fcount; char_u **fnames; + char_u *s; char_u *p; int i; - FILE *fd; int fi; struct qf_line *prevp = NULL; long lnum; garray_T ga; + buf_T *buf; + int duplicate_name = FALSE; + int using_dummy; + int found_match; + int first_match = TRUE; /* Make 'cpoptions' empty, the 'l' flag should not be used here. */ save_cpo = p_cpo; p_cpo = empty_option; - /* Get the search pattern */ + /* Get the search pattern: either white-separated or enclosed in // */ regmatch.regprog = NULL; - p = skip_regexp(eap->arg + 1, *eap->arg, TRUE, NULL); - if (*p != *eap->arg) + if (vim_isIDc(*eap->arg)) { - EMSG(_("E682: Invalid search pattern or delimiter")); - goto theend; + s = eap->arg; + p = skiptowhite(s); + } + else + { + s = eap->arg + 1; + p = skip_regexp(s, *eap->arg, TRUE, NULL); + if (*p != *eap->arg) + { + EMSG(_("E682: Invalid search pattern or delimiter")); + goto theend; + } } - *p++ = NUL; - regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC); + if (*p != NUL) + *p++ = NUL; + regmatch.regprog = vim_regcomp(s, RE_MAGIC); if (regmatch.regprog == NULL) goto theend; - regmatch.rm_ic = FALSE; + regmatch.rmm_ic = FALSE; p = skipwhite(p); if (*p == NUL) @@ -2312,28 +2330,37 @@ ex_vimgrep(eap) for (fi = 0; fi < fcount && !got_int; ++fi) { - fd = fopen((char *)fnames[fi], "r"); - if (fd == NULL) + buf = buflist_findname_exp(fnames[fi]); + if (buf == NULL || buf->b_ml.ml_mfp == NULL) + { + /* Remember that a buffer with this name already exists. */ + duplicate_name = (buf != NULL); + + /* Load file into a buffer, so that 'fileencoding' is detected, + * autocommands applied, etc. */ + buf = load_dummy_buffer(fnames[fi]); + using_dummy = TRUE; + } + else + /* Use existing, loaded buffer. */ + using_dummy = FALSE; + if (buf == NULL) smsg((char_u *)_("Cannot open file \"%s\""), fnames[fi]); else { - lnum = 1; - while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int) + found_match = FALSE; + for (lnum = 1; lnum <= buf->b_ml.ml_line_count; ++lnum) { - if (vim_regexec(®match, IObuff, (colnr_T)0)) + if (vim_regexec_multi(®match, curwin, buf, lnum, + (colnr_T)0) > 0) { - int l = STRLEN(IObuff); - - /* remove trailing CR, LF, spaces, etc. */ - while (l > 0 && IObuff[l - 1] <= ' ') - IObuff[--l] = NUL; - if (qf_add_entry(&prevp, NULL, /* dir */ fnames[fi], - IObuff, - lnum, - (int)(regmatch.startp[0] - IObuff) + 1,/* col */ + ml_get_buf(buf, + regmatch.startpos[0].lnum + lnum, FALSE), + regmatch.startpos[0].lnum + lnum, + regmatch.startpos[0].col + 1, FALSE, /* virt_col */ 0, /* nr */ 0, /* type */ @@ -2343,11 +2370,34 @@ ex_vimgrep(eap) got_int = TRUE; break; } + else + found_match = TRUE; } - ++lnum; line_breakcheck(); + if (got_int) + break; + } + + if (using_dummy) + { + if (duplicate_name) + /* Never keep a dummy buffer if there is another buffer + * with the same name. */ + wipe_dummy_buffer(buf); + else if (!buf_hide(buf)) + { + /* When not hiding the buffer and no match was found we + * don't need to remember the buffer, wipe it out. If + * there was a match and it wasn't the first one: only + * unload the buffer. */ + if (!found_match) + wipe_dummy_buffer(buf); + else if (!first_match) + unload_dummy_buffer(buf); + } } - fclose(fd); + if (found_match) + first_match = FALSE; } } @@ -2364,6 +2414,8 @@ ex_vimgrep(eap) /* Jump to first match. */ if (qf_lists[qf_curlist].qf_count > 0) qf_jump(0, 0, FALSE); + else + EMSG2(_(e_nomatch2), s); theend: vim_free(regmatch.regprog); @@ -2376,6 +2428,104 @@ theend: } /* + * Load file "fname" into a dummy buffer and return the buffer pointer. + * Returns NULL if it fails. + * Must call unload_dummy_buffer() or wipe_dummy_buffer() later! + */ + static buf_T * +load_dummy_buffer(fname) + char_u *fname; +{ + buf_T *newbuf; + int failed = TRUE; +#ifdef FEAT_AUTOCMD + aco_save_T aco; +#else + buf_T *old_curbuf = curbuf; +#endif + + /* Allocate a buffer without putting it in the buffer list. */ + newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); + if (newbuf == NULL) + return NULL; + +#ifdef FEAT_AUTOCMD + /* set curwin/curbuf to buf and save a few things */ + aucmd_prepbuf(&aco, newbuf); +#else + curbuf = newbuf; + curwin->w_buffer = newbuf; +#endif + + /* Need to set the filename for autocommands. */ + (void)setfname(curbuf, fname, NULL, FALSE); + + if (ml_open() == OK) + { + /* Create swap file now to avoid the ATTENTION message. */ + check_need_swap(TRUE); + + /* Remove the "dummy" flag, otherwise autocommands may not + * work. */ + curbuf->b_flags &= ~BF_DUMMY; + + if (readfile(fname, NULL, + (linenr_T)0, (linenr_T)0, (linenr_T)MAXLNUM, + NULL, READ_NEW | READ_DUMMY) == OK + && !(curbuf->b_flags & BF_NEW)) + { + failed = FALSE; + if (curbuf != newbuf) + { + /* Bloody autocommands changed the buffer! */ + if (buf_valid(newbuf)) + wipe_buffer(newbuf, FALSE); + newbuf = curbuf; + } + } + } + +#ifdef FEAT_AUTOCMD + /* restore curwin/curbuf and a few other things */ + aucmd_restbuf(&aco); +#else + curbuf = old_curbuf; + curwin->w_buffer = old_curbuf; +#endif + + if (!buf_valid(newbuf)) + return NULL; + if (failed) + { + wipe_dummy_buffer(newbuf); + return NULL; + } + return newbuf; +} + +/* + * Wipe out the dummy buffer that load_dummy_buffer() created. + */ + static void +wipe_dummy_buffer(buf) + buf_T *buf; +{ + if (curbuf != buf) /* safety check */ + wipe_buffer(buf, FALSE); +} + +/* + * Unload the dummy buffer that load_dummy_buffer() created. + */ + static void +unload_dummy_buffer(buf) + buf_T *buf; +{ + if (curbuf != buf) /* safety check */ + close_buffer(NULL, buf, DOBUF_UNLOAD); +} + +/* * ":[range]cbuffer [bufnr]" command. */ void @@ -2487,7 +2637,8 @@ ex_helpgrep(eap) fnames[fi], IObuff, lnum, - 0, /* col */ + (int)(regmatch.startp[0] - IObuff) + + 1, /* col */ FALSE, /* virt_col */ 0, /* nr */ 1, /* type */ |