Commit 1d6a2cda53
Verified · cmc
Layout: unified · split
Sources/OrgCore/Agenda/AgendaSearch.swift +9 −3
| @@ -480,6 +480,9 @@ public struct TagsMatcher: Sendable { | ||
| 480 | 480 | /// Emacs regular expressions run through ICU, case-insensitively as the matcher binds |
| 481 | 481 | /// `case-fold-search`. |
| 482 | 482 | enum EmacsRegex { |
| 483 | /// Word syntax in an Org buffer: letters, digits, marks, `$` and `%`, but not `_`, `-` or `'`. | |
| 484 | static let word = "[\\p{L}\\p{N}\\p{M}$%\\u00b7]" | |
| 485 | ||
| 483 | 486 | static func translate(_ pattern: String) -> String { |
| 484 | 487 | var out = "" |
| 485 | 488 | var chars = Array(pattern) |
| @@ -522,11 +525,14 @@ enum EmacsRegex { | ||
| 522 | 525 | out += n == "s" ? "[\\t\\n\\f\\r \\u00a0]" : "[^\\t\\n\\f\\r \\u00a0]" |
| 523 | 526 | i += 3 |
| 524 | 527 | continue |
| 525 | case "<", ">": out += "\\b" | |
| 528 | case "<": out += "(?<!\(word))(?=\(word))" | |
| 529 | case ">": out += "(?<=\(word))(?!\(word))" | |
| 530 | case "b": out += "(?:(?<!\(word))(?=\(word))|(?<=\(word))(?!\(word)))" | |
| 531 | case "B": out += "(?:(?<=\(word))(?=\(word))|(?<!\(word))(?!\(word)))" | |
| 526 | 532 | case "`": out += "^" |
| 527 | 533 | case "'": out += "$" |
| 528 | case "w": out += "[\\p{L}\\p{N}]" | |
| 529 | case "W": out += "[^\\p{L}\\p{N}]" | |
| 534 | case "w": out += word | |
| 535 | case "W": out += "[^" + word.dropFirst() | |
| 530 | 536 | default: out += "\\" + String(n) |
| 531 | 537 | } |
| 532 | 538 | i += 2 |
Tests/OrgCoreTests/AgendaSearchTests.swift +4
| @@ -28,6 +28,7 @@ struct AgendaSearchTests { | ||
| 28 | 28 | * Two words |
| 29 | 29 | The phrase two words |
| 30 | 30 | spans here; foo_bar and foo-bar. |
| 31 | Costs $5 or 50% (don't) for the café. | |
| 31 | 32 | * The last |
| 32 | 33 | word ends this entry with last |
| 33 | 34 | * word starts the next heading |
| @@ -54,6 +55,9 @@ struct AgendaSearchTests { | ||
| 54 | 55 | "+alpha", "+alpha -beta", "+alpha +gamma", "-alpha", "+beta -nested", "{alph?a}", "+{^Gam}", "-{b[eo]}", |
| 55 | 56 | "+{\\<rent\\>}", "+\"two words\"", "+\"two words\"", "+\"the line\"", "{boiler\\b}", "+alpha +\"in the body\"", |
| 56 | 57 | "+{foo\\s-bar}", "+boiler -plate", "+{a b}", "+{alpha} -{x y}", |
| 58 | // Emacs word syntax in Org buffers: `_`, `-` and `'` are not word characters; `$` and `%` are. | |
| 59 | "+{\\<bar\\>}", "+{foo\\b}", "+{o\\B_}", "+{\\<5\\>}", "+{\\b50\\b}", "+{don\\>}", "+{\\w+_\\w+}", "+{\\W5}", | |
| 60 | "+{caf\\w\\>}", "+{\\<\\$5}", | |
| 57 | 61 | // Headlines only. |
| 58 | 62 | "*rent", "*alpha", "*+alpha -beta", "*+section", "*-alpha", "*pay rent", "*with alpha and", |
| 59 | 63 | // TODO only and whole words. |