summaryrefslogtreecommitdiff
path: root/src/search.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2015-07-28 21:17:36 +0200
committerBram Moolenaar <Bram@vim.org>2015-07-28 21:17:36 +0200
commitf7bb86dc593913d055e4cce16cec43f6271adda3 (patch)
treed987f51511bb7af5395ea9adcc467b0a33660dd3 /src/search.c
parent52e21cf057e313a867b0f529c8e4d52ad5ae740d (diff)
downloadvim-f7bb86dc593913d055e4cce16cec43f6271adda3.zip
patch 7.4.803
Problem: C indent does not support C11 raw strings. (Mark Lodato) Solution: Do not change indent inside the raw string.
Diffstat (limited to 'src/search.c')
-rw-r--r--src/search.c91
1 files changed, 82 insertions, 9 deletions
diff --git a/src/search.c b/src/search.c
index 4905a49d7..238fc8160 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1725,20 +1725,71 @@ check_prevcol(linep, col, ch, prevcol)
return (col >= 0 && linep[col] == ch) ? TRUE : FALSE;
}
+static int find_rawstring_end __ARGS((char_u *linep, pos_T *startpos, pos_T *endpos));
+
+/*
+ * Raw string start is found at linep[startpos.col - 1].
+ * Return TRUE if the matching end can be found between startpos and endpos.
+ */
+ static int
+find_rawstring_end(linep, startpos, endpos)
+ char_u *linep;
+ pos_T *startpos;
+ pos_T *endpos;
+{
+ char_u *p;
+ char_u *delim_copy;
+ size_t delim_len;
+ linenr_T lnum;
+ int found = FALSE;
+
+ for (p = linep + startpos->col + 1; *p && *p != '('; ++p)
+ ;
+ delim_len = (p - linep) - startpos->col - 1;
+ delim_copy = vim_strnsave(linep + startpos->col + 1, delim_len);
+ if (delim_copy == NULL)
+ return FALSE;
+ for (lnum = startpos->lnum; lnum <= endpos->lnum; ++lnum)
+ {
+ char_u *line = ml_get(lnum);
+
+ for (p = line + (lnum == startpos->lnum
+ ? startpos->col + 1 : 0); *p; ++p)
+ {
+ if (lnum == endpos->lnum && (colnr_T)(p - line) >= endpos->col)
+ break;
+ if (*p == ')' && p[delim_len + 1] == '"'
+ && STRNCMP(delim_copy, p + 1, delim_len) == 0)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+ vim_free(delim_copy);
+ return found;
+}
+
/*
* findmatchlimit -- find the matching paren or brace, if it exists within
- * maxtravel lines of here. A maxtravel of 0 means search until falling off
- * the edge of the file.
+ * maxtravel lines of the cursor. A maxtravel of 0 means search until falling
+ * off the edge of the file.
*
* "initc" is the character to find a match for. NUL means to find the
- * character at or after the cursor.
+ * character at or after the cursor. Special values:
+ * '*' look for C-style comment / *
+ * '/' look for C-style comment / *, ignoring comment-end
+ * '#' look for preprocessor directives
+ * 'R' look for raw string start: R"delim(text)delim" (only backwards)
*
* flags: FM_BACKWARD search backwards (when initc is '/', '*' or '#')
* FM_FORWARD search forwards (when initc is '/', '*' or '#')
* FM_BLOCKSTOP stop at start/end of block ({ or } in column 0)
* FM_SKIPCOMM skip comments (not implemented yet!)
*
- * "oap" is only used to set oap->motion_type for a linewise motion, it be
+ * "oap" is only used to set oap->motion_type for a linewise motion, it can be
* NULL
*/
@@ -1754,6 +1805,7 @@ findmatchlimit(oap, initc, flags, maxtravel)
int c;
int count = 0; /* cumulative number of braces */
int backwards = FALSE; /* init for gcc */
+ int raw_string = FALSE; /* search for raw string */
int inquote = FALSE; /* TRUE when inside quotes */
char_u *linep; /* pointer to current line */
char_u *ptr;
@@ -1798,12 +1850,13 @@ findmatchlimit(oap, initc, flags, maxtravel)
* When '/' is used, we ignore running backwards into an star-slash, for
* "[*" command, we just want to find any comment.
*/
- if (initc == '/' || initc == '*')
+ if (initc == '/' || initc == '*' || initc == 'R')
{
comment_dir = dir;
if (initc == '/')
ignore_cend = TRUE;
backwards = (dir == FORWARD) ? FALSE : TRUE;
+ raw_string = (initc == 'R');
initc = NUL;
}
else if (initc != '#' && initc != NUL)
@@ -1812,12 +1865,12 @@ findmatchlimit(oap, initc, flags, maxtravel)
if (findc == NUL)
return NULL;
}
- /*
- * Either initc is '#', or no initc was given and we need to look under the
- * cursor.
- */
else
{
+ /*
+ * Either initc is '#', or no initc was given and we need to look
+ * under the cursor.
+ */
if (initc == '#')
{
hash_dir = dir;
@@ -2135,6 +2188,26 @@ findmatchlimit(oap, initc, flags, maxtravel)
*/
if (pos.col == 0)
continue;
+ else if (raw_string)
+ {
+ if (linep[pos.col - 1] == 'R'
+ && linep[pos.col] == '"'
+ && vim_strchr(linep + pos.col + 1, '(') != NULL)
+ {
+ /* Possible start of raw string. Now that we have the
+ * delimiter we can check if it ends before where we
+ * started searching, or before the previously found
+ * raw string start. */
+ if (!find_rawstring_end(linep, &pos,
+ count > 0 ? &match_pos : &curwin->w_cursor))
+ {
+ count++;
+ match_pos = pos;
+ match_pos.col--;
+ }
+ linep = ml_get(pos.lnum); /* may have been released */
+ }
+ }
else if ( linep[pos.col - 1] == '/'
&& linep[pos.col] == '*'
&& (int)pos.col < comment_col)