diff --git a/doc/pages/regex.asciidoc b/doc/pages/regex.asciidoc index 416efd1f04..9548e70227 100644 --- a/doc/pages/regex.asciidoc +++ b/doc/pages/regex.asciidoc @@ -167,6 +167,7 @@ them: * `(?I)` starts case-sensitive matching (default). * `(?s)` allows `.` to match newlines (default). * `(?S)` prevents `.` from matching newlines. +* `(?c)` enable smartcase, starts case-insensitive matching unless an uppercase character is present in the pattern. == Quoting diff --git a/src/regex_impl.cc b/src/regex_impl.cc index 9b307f2368..19057f1097 100644 --- a/src/regex_impl.cc +++ b/src/regex_impl.cc @@ -153,6 +153,7 @@ struct RegexParser None = 0, IgnoreCase = 1 << 0, DotMatchesNewLine = 1 << 1, + SmartCase = 1 << 2, }; friend constexpr bool with_bit_ops(Meta::Type) { return true; } @@ -212,6 +213,7 @@ struct RegexParser case 'I': m_flags &= ~Flags::IgnoreCase; break; case 's': m_flags |= Flags::DotMatchesNewLine; break; case 'S': m_flags &= ~Flags::DotMatchesNewLine; break; + case 'c': m_flags |= Flags::SmartCase | Flags::IgnoreCase; break; case ')': m_pos = Iterator{it, m_regex}; return true; @@ -328,6 +330,14 @@ struct RegexParser if (contains(StringView{"^$.*+?[]{}"}, cp) or (cp >= 0xF0000 and cp <= 0xFFFFF)) parse_error(format("unexpected '{}'", cp)); ++m_pos; + if (is_upper(cp) && (m_flags & Flags::SmartCase)) { + m_flags &= ~Flags::IgnoreCase; + for (ParsedRegex::Node &node : m_parsed_regex.nodes) + node.ignore_case = false; + for (CharacterClass &char_class : m_parsed_regex.character_classes) + char_class.ignore_case = false; + + } return add_node(ParsedRegex::Literal, cp); } } diff --git a/test/normal/search-character-class/cmd b/test/normal/search-character-class/cmd new file mode 100644 index 0000000000..550a9483e0 --- /dev/null +++ b/test/normal/search-character-class/cmd @@ -0,0 +1 @@ +/(?c)[a-z]ooBar diff --git a/test/normal/search-character-class/in b/test/normal/search-character-class/in new file mode 100644 index 0000000000..9f8516477a --- /dev/null +++ b/test/normal/search-character-class/in @@ -0,0 +1 @@ +%(f)oobar FooBar fooBar diff --git a/test/normal/search-character-class/kak_quoted_selections b/test/normal/search-character-class/kak_quoted_selections new file mode 100644 index 0000000000..ce3237251d --- /dev/null +++ b/test/normal/search-character-class/kak_quoted_selections @@ -0,0 +1 @@ +'fooBar' diff --git a/test/normal/search-smartcase/cmd b/test/normal/search-smartcase/cmd new file mode 100644 index 0000000000..da8801a85b --- /dev/null +++ b/test/normal/search-smartcase/cmd @@ -0,0 +1 @@ +/fooBar diff --git a/test/normal/search-smartcase/in b/test/normal/search-smartcase/in new file mode 100644 index 0000000000..9f8516477a --- /dev/null +++ b/test/normal/search-smartcase/in @@ -0,0 +1 @@ +%(f)oobar FooBar fooBar diff --git a/test/normal/search-smartcase/kak_quoted_selections b/test/normal/search-smartcase/kak_quoted_selections new file mode 100644 index 0000000000..ce3237251d --- /dev/null +++ b/test/normal/search-smartcase/kak_quoted_selections @@ -0,0 +1 @@ +'fooBar'