From 282dd9b48aa8fdfb189eb9bc4527206b9ea7968b Mon Sep 17 00:00:00 2001 From: jamiedsmith95 Date: Sun, 28 Jul 2024 16:25:01 +0100 Subject: [PATCH 1/5] implement smart case implement smart case using (?c), this activates ignore case until an upper char is present (not escape or modifier etc..) --- src/regex_impl.cc | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/regex_impl.cc b/src/regex_impl.cc index 9b307f2368..4430f40805 100644 --- a/src/regex_impl.cc +++ b/src/regex_impl.cc @@ -1,5 +1,4 @@ #include "regex_impl.hh" - #include "exception.hh" #include "string.hh" #include "unicode.hh" @@ -9,7 +8,6 @@ #include "string_utils.hh" #include "vector.hh" #include "utils.hh" - #include #include #include @@ -153,6 +151,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 +211,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; m_flags |= Flags::IgnoreCase; break; case ')': m_pos = Iterator{it, m_regex}; return true; @@ -328,6 +328,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; + } + + } return add_node(ParsedRegex::Literal, cp); } } From ec84fb51c333c304cee5601545d2f6451f32d55f Mon Sep 17 00:00:00 2001 From: jamiedsmith95 Date: Sun, 28 Jul 2024 16:25:26 +0100 Subject: [PATCH 2/5] Jamie Smith Copyright Waiver I dedicate any and all copyright interest in this software to the public domain. I make this dedication for the benefit of the public at large and to the detriment of my heirs and successors. I intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. From 1461caccc30f8514ff241d6472d8fa0dcc536cb1 Mon Sep 17 00:00:00 2001 From: jamiedsmith95 Date: Tue, 30 Jul 2024 23:20:07 +0100 Subject: [PATCH 3/5] formatting --- src/regex_impl.cc | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/regex_impl.cc b/src/regex_impl.cc index 4430f40805..3c306b398a 100644 --- a/src/regex_impl.cc +++ b/src/regex_impl.cc @@ -1,4 +1,5 @@ #include "regex_impl.hh" + #include "exception.hh" #include "string.hh" #include "unicode.hh" @@ -8,6 +9,7 @@ #include "string_utils.hh" #include "vector.hh" #include "utils.hh" + #include #include #include @@ -211,7 +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; m_flags |= Flags::IgnoreCase; break; + case 'c': m_flags |= Flags::SmartCase |= Flags::IgnoreCase; break; case ')': m_pos = Iterator{it, m_regex}; return true; @@ -329,11 +331,10 @@ struct RegexParser 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; - } + m_flags &= ~Flags::IgnoreCase; + for (ParsedRegex::Node &node : m_parsed_regex.nodes) + node.ignore_case = false; + } return add_node(ParsedRegex::Literal, cp); From c6fb089c6ee5307f31fe35b30bfbfc7c3a1356f7 Mon Sep 17 00:00:00 2001 From: jamiedsmith95 Date: Sun, 4 Aug 2024 11:26:35 +0100 Subject: [PATCH 4/5] char class --- src/regex_impl.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/regex_impl.cc b/src/regex_impl.cc index 3c306b398a..db555812eb 100644 --- a/src/regex_impl.cc +++ b/src/regex_impl.cc @@ -213,7 +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 'c': m_flags |= Flags::SmartCase | Flags::IgnoreCase; break; case ')': m_pos = Iterator{it, m_regex}; return true; @@ -334,8 +334,9 @@ struct RegexParser 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); } From 2773d2cfbb34987502f5a6d4f2596cd8f9371f59 Mon Sep 17 00:00:00 2001 From: jamiedsmith95 Date: Sun, 4 Aug 2024 12:23:56 +0100 Subject: [PATCH 5/5] tests and docs --- doc/pages/regex.asciidoc | 1 + src/regex_impl.cc | 2 +- test/normal/search-character-class/cmd | 1 + test/normal/search-character-class/in | 1 + test/normal/search-character-class/kak_quoted_selections | 1 + test/normal/search-smartcase/cmd | 1 + test/normal/search-smartcase/in | 1 + test/normal/search-smartcase/kak_quoted_selections | 1 + 8 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 test/normal/search-character-class/cmd create mode 100644 test/normal/search-character-class/in create mode 100644 test/normal/search-character-class/kak_quoted_selections create mode 100644 test/normal/search-smartcase/cmd create mode 100644 test/normal/search-smartcase/in create mode 100644 test/normal/search-smartcase/kak_quoted_selections 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 db555812eb..19057f1097 100644 --- a/src/regex_impl.cc +++ b/src/regex_impl.cc @@ -336,7 +336,7 @@ struct RegexParser 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'