Skip to content

Commit 0070c52

Browse files
committed
regex: implement the short \N escape sequence from Perl/PCRE
With `.`, Kakoune matches newlines by default. Therefore `\N` comes in very handy, as it is quicker to type than the commonly used patterns `(?S).` and `[^\n]`.
1 parent 23aa04d commit 0070c52

File tree

6 files changed

+20
-6
lines changed

6 files changed

+20
-6
lines changed

doc/pages/changelog.asciidoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ released versions.
1616

1717
* `number-lines -full-relative` switch to keep a smaller line number gutter.
1818

19+
* Support the `\N` escape sequence in regex (like in PCRE, matches `[^\n]`).
20+
1921
== Kakoune 2025.06.03
2022

2123
* Expose env vars that are mentioned in the arguments passed to shell expansions

doc/pages/faq.asciidoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,8 @@ In most distributions, `/bin/sh` will end up being used.
292292

293293
Data in buffers is a stream of characters, and newlines do not receive special
294294
treatment compared to other characters, with regards to regex matching. In
295-
order to select data in a line without any trailing newline characters, one could
296-
use the `[^\n]+` pattern, which is arguably a good compromise when
295+
order to select data in a line without any trailing newline characters, one
296+
could use the `\N+` pattern, which is arguably a good compromise when
297297
balanced against the ability to select data over several lines.
298298

299299
You can instruct the regex engine to stop matching newline characters with

doc/pages/highlighters.asciidoc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ highlighter is replaced with the new one.
131131
This highlights C++ style comments in cyan, with an eventual 'TODO:'
132132
in yellow on red background:
133133

134-
--------------------------------------------------------------------
135-
add-highlighter window/ regex //\h*(TODO:)[^\n]* 0:cyan 1:yellow,red
136-
--------------------------------------------------------------------
134+
-----------------------------------------------------------------
135+
add-highlighter window/ regex //\h*(TODO:)\N* 0:cyan 1:yellow,red
136+
-----------------------------------------------------------------
137137

138138
capture_id can be either the capture number, or its name if a
139139
named capture is used in the regex (See

doc/pages/regex.asciidoc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ is equivalent to `[\d]`.
7474
`.` matches any character, including newlines, by default.
7575
(see <<regex#modifiers,:doc regex modifiers>> on how to change it)
7676

77+
`\N` matches any character but newlines (not affected by modifiers).
78+
7779
== Groups
7880

7981
Regex atoms can be grouped using `(` and `)` or `(?:` and `)`. If `(` is
@@ -184,7 +186,7 @@ by <https://www.ecma-international.org/ecma-262/8.0/>; some divergence
184186
exists for ease of use, or performance reasons:
185187

186188
* Lookarounds are not arbitrary, but lookbehind is supported.
187-
* `\K`, `\Q..\E`, `\A`, `\h` and `\z` are added.
189+
* `\K`, `\N`, `\Q..\E`, `\A`, `\h` and `\z` are added.
188190
* Stricter handling of escaping, as we introduce additional escapes;
189191
identity escapes like `\X` with `X` being a non-special character
190192
are not accepted, to avoid confusions between `\h` meaning literal

src/main.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ struct {
5555
"» {+b}%val\\{buffile}{} is now empty for scratch buffers\n"
5656
"» {+b}FocusIn{}/{+b}FocusOut{} events on suspend\n"
5757
"» {+u}number-lines -full-relative{} switch to keep a smaller line number gutter\n"
58+
"» support the {+b}\\N{} escape sequence in regex (matches {+b}[^\\n]{})\n"
5859
}, {
5960
20250603,
6061
"» kak_* appearing in shell arguments will be added to the environment\n"

src/regex_vm.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,9 @@ struct RegexParser
357357
{
358358
const Codepoint cp = *m_pos++;
359359

360+
if (cp == 'N')
361+
return add_node(ParsedRegex::AnyCharExceptNewLine);
362+
360363
if (cp == 'Q')
361364
{
362365
auto escaped_sequence = add_node(ParsedRegex::Sequence);
@@ -1562,6 +1565,12 @@ auto test_regex = UnitTest{[]{
15621565
kak_assert(*vm.captures()[0] == 'f');
15631566
}
15641567

1568+
{
1569+
TestVM<> vm{R"(a(?<=\N)\N+(?=.\N)\s(?S)d.+(?!.)\s(?<!\N)g)"};
1570+
kak_assert(vm.exec("abc\ndef\ng"));
1571+
kak_assert(not vm.exec("abc\ndef g"));
1572+
}
1573+
15651574
{
15661575
TestVM<> vm{R"([d-ea-dcf-k]+)"};
15671576
kak_assert(vm.exec("abcde"));

0 commit comments

Comments
 (0)