summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-01-31 15:34:40 +0100
committerBram Moolenaar <Bram@vim.org>2019-01-31 15:34:40 +0100
commit221cd9f4dd866503777b2fffa721c1403716ad63 (patch)
treee852c86a815d0f8667655a6a9c1ac920b2925620
parent60f807b3f71a92881e2b3bf48bd016294957130e (diff)
downloadvim-git-221cd9f4dd866503777b2fffa721c1403716ad63.tar.gz
patch 8.1.0862: no verbose version of character classesv8.1.0862
Problem: No verbose version of character classes. Solution: Add [:ident:], [:keyword:] and [:fname:]. (Ozaki Kiichi, closes #1373)
-rw-r--r--runtime/doc/pattern.txt3
-rw-r--r--src/regexp.c32
-rw-r--r--src/regexp_nfa.c29
-rw-r--r--src/testdir/test_regexp_utf8.vim55
-rw-r--r--src/version.c2
5 files changed, 120 insertions, 1 deletions
diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt
index b0c7f2e6a..f17db9682 100644
--- a/runtime/doc/pattern.txt
+++ b/runtime/doc/pattern.txt
@@ -1118,6 +1118,9 @@ x A single character, with no special meaning, matches itself
*[:tab:]* [:tab:] the <Tab> character
*[:escape:]* [:escape:] the <Esc> character
*[:backspace:]* [:backspace:] the <BS> character
+*[:ident:]* [:ident:] identifier character (same as "\i")
+*[:keyword:]* [:keyword:] keyword character (same as "\k")
+*[:fname:]* [:fname:] file name character (same as "\f")
The brackets in character class expressions are additional to the
brackets delimiting a collection. For example, the following is a
plausible pattern for a UNIX filename: "[-./[:alnum:]_~]\+" That is,
diff --git a/src/regexp.c b/src/regexp.c
index 20894ea72..9e6cf702d 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -484,6 +484,12 @@ get_char_class(char_u **pp)
#define CLASS_BACKSPACE 14
"escape:]",
#define CLASS_ESCAPE 15
+ "ident:]",
+#define CLASS_IDENT 16
+ "keyword:]",
+#define CLASS_KEYWORD 17
+ "fname:]",
+#define CLASS_FNAME 18
};
#define CLASS_NONE 99
int i;
@@ -698,6 +704,7 @@ static char_u *re_put_long(char_u *pr, long_u val);
static int read_limits(long *, long *);
static void regtail(char_u *, char_u *);
static void regoptail(char_u *, char_u *);
+static int reg_iswordc(int);
static regengine_T bt_regengine;
static regengine_T nfa_regengine;
@@ -2545,6 +2552,21 @@ collection:
case CLASS_ESCAPE:
regc('\033');
break;
+ case CLASS_IDENT:
+ for (cu = 1; cu <= 255; cu++)
+ if (vim_isIDc(cu))
+ regmbc(cu);
+ break;
+ case CLASS_KEYWORD:
+ for (cu = 1; cu <= 255; cu++)
+ if (reg_iswordc(cu))
+ regmbc(cu);
+ break;
+ case CLASS_FNAME:
+ for (cu = 1; cu <= 255; cu++)
+ if (vim_isfilec(cu))
+ regmbc(cu);
+ break;
}
}
else
@@ -3590,6 +3612,16 @@ free_regexp_stuff(void)
#endif
/*
+ * Return TRUE if character 'c' is included in 'iskeyword' option for
+ * "reg_buf" buffer.
+ */
+ static int
+reg_iswordc(int c)
+{
+ return vim_iswordc_buf(c, rex.reg_buf);
+}
+
+/*
* Get pointer to the line "lnum", which is relative to "reg_firstlnum".
*/
static char_u *
diff --git a/src/regexp_nfa.c b/src/regexp_nfa.c
index 863ad6cac..031a6cf20 100644
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -226,7 +226,10 @@ enum
NFA_CLASS_TAB,
NFA_CLASS_RETURN,
NFA_CLASS_BACKSPACE,
- NFA_CLASS_ESCAPE
+ NFA_CLASS_ESCAPE,
+ NFA_CLASS_IDENT,
+ NFA_CLASS_KEYWORD,
+ NFA_CLASS_FNAME
};
/* Keep in sync with classchars. */
@@ -1718,6 +1721,15 @@ collection:
case CLASS_ESCAPE:
EMIT(NFA_CLASS_ESCAPE);
break;
+ case CLASS_IDENT:
+ EMIT(NFA_CLASS_IDENT);
+ break;
+ case CLASS_KEYWORD:
+ EMIT(NFA_CLASS_KEYWORD);
+ break;
+ case CLASS_FNAME:
+ EMIT(NFA_CLASS_FNAME);
+ break;
}
EMIT(NFA_CONCAT);
continue;
@@ -2555,6 +2567,9 @@ nfa_set_code(int c)
case NFA_CLASS_RETURN: STRCPY(code, "NFA_CLASS_RETURN"); break;
case NFA_CLASS_BACKSPACE: STRCPY(code, "NFA_CLASS_BACKSPACE"); break;
case NFA_CLASS_ESCAPE: STRCPY(code, "NFA_CLASS_ESCAPE"); break;
+ case NFA_CLASS_IDENT: STRCPY(code, "NFA_CLASS_IDENT"); break;
+ case NFA_CLASS_KEYWORD: STRCPY(code, "NFA_CLASS_KEYWORD"); break;
+ case NFA_CLASS_FNAME: STRCPY(code, "NFA_CLASS_FNAME"); break;
case NFA_ANY: STRCPY(code, "NFA_ANY"); break;
case NFA_IDENT: STRCPY(code, "NFA_IDENT"); break;
@@ -4846,6 +4861,18 @@ check_char_class(int class, int c)
if (c == '\033')
return OK;
break;
+ case NFA_CLASS_IDENT:
+ if (vim_isIDc(c))
+ return OK;
+ break;
+ case NFA_CLASS_KEYWORD:
+ if (reg_iswordc(c))
+ return OK;
+ break;
+ case NFA_CLASS_FNAME:
+ if (vim_isfilec(c))
+ return OK;
+ break;
default:
/* should not be here :P */
diff --git a/src/testdir/test_regexp_utf8.vim b/src/testdir/test_regexp_utf8.vim
index f61887031..98b9e73de 100644
--- a/src/testdir/test_regexp_utf8.vim
+++ b/src/testdir/test_regexp_utf8.vim
@@ -51,6 +51,12 @@ func s:classes_test()
let tabchar = ''
let upperchars = ''
let xdigitchars = ''
+ let identchars = ''
+ let identchars1 = ''
+ let kwordchars = ''
+ let kwordchars1 = ''
+ let fnamechars = ''
+ let fnamechars1 = ''
let i = 1
while i <= 255
let c = nr2char(i)
@@ -102,6 +108,24 @@ func s:classes_test()
if c =~ '[[:xdigit:]]'
let xdigitchars .= c
endif
+ if c =~ '[[:ident:]]'
+ let identchars .= c
+ endif
+ if c =~ '\i'
+ let identchars1 .= c
+ endif
+ if c =~ '[[:keyword:]]'
+ let kwordchars .= c
+ endif
+ if c =~ '\k'
+ let kwordchars1 .= c
+ endif
+ if c =~ '[[:fname:]]'
+ let fnamechars .= c
+ endif
+ if c =~ '\f'
+ let fnamechars1 .= c
+ endif
let i += 1
endwhile
@@ -121,6 +145,37 @@ func s:classes_test()
call assert_equal("\t\n\x0b\f\r ", spacechars)
call assert_equal("\t", tabchar)
call assert_equal('0123456789ABCDEFabcdef', xdigitchars)
+
+ if has('win32')
+ let identchars_ok = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ'
+ let kwordchars_ok = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyzµÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ elseif has('ebcdic')
+ let identchars_ok = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz€ŒŽœž¬®µº¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ let kwordchars_ok = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz€ŒŽœž¬®µº¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ else
+ let identchars_ok = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyzµÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ let kwordchars_ok = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyzµÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ endif
+
+ if has('win32')
+ let fnamechars_ok = '!#$%+,-./0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]_abcdefghijklmnopqrstuvwxyz{}~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ elseif has('amiga')
+ let fnamechars_ok = '$+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ elseif has('vms')
+ let fnamechars_ok = '#$%+,-./0123456789:;<>ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ elseif has('ebcdic')
+ let fnamechars_ok = '#$%+,-./=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ else
+ let fnamechars_ok = '#$%+,-./0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
+ endif
+
+ call assert_equal(identchars_ok, identchars)
+ call assert_equal(kwordchars_ok, kwordchars)
+ call assert_equal(fnamechars_ok, fnamechars)
+
+ call assert_equal(identchars1, identchars)
+ call assert_equal(kwordchars1, kwordchars)
+ call assert_equal(fnamechars1, fnamechars)
endfunc
func Test_classes_re1()
diff --git a/src/version.c b/src/version.c
index 6470c4670..1b4eef9f4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -784,6 +784,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 862,
+/**/
861,
/**/
860,