Skip to content

Commit

Permalink
find: support double-backslash for literal backslash in search pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
dgw committed Jan 25, 2024
1 parent ba3170c commit 580094c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 6 deletions.
23 changes: 17 additions & 6 deletions sopel/builtins/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ def kick_cleanup(bot, trigger):
[:,]\s+)? # Followed by optional colon/comma and whitespace
s(?P<sep>/) # The literal s and a separator / as group 2
(?P<old> # Group 3 is the thing to find
(?:\\/|[^/])+ # One or more non-slashes or escaped slashes
(?:\\\\|\\/|[^/])+ # One or more non-slashes or escaped slashes
)
/ # The separator again
(?P<new> # Group 4 is what to replace with
(?:\\/|[^/])* # One or more non-slashes or escaped slashes
(?:\\\\|\\/|[^/])* # One or more non-slashes or escaped slashes
)
(?:/ # Optional separator followed by group 5 (flags)
(?P<flags>\S+)
Expand All @@ -136,11 +136,11 @@ def kick_cleanup(bot, trigger):
[:,]\s+)? # Followed by optional colon/comma and whitespace
s(?P<sep>\|) # The literal s and a separator | as group 2
(?P<old> # Group 3 is the thing to find
(?:\\\||[^|])+ # One or more non-pipe or escaped pipe
(?:\\\\|\\\||[^|])+ # One or more non-pipe or escaped pipe
)
\| # The separator again
(?P<new> # Group 4 is what to replace with
(?:\\\||[^|])* # One or more non-pipe or escaped pipe
(?:\\\\|\\\||[^|])* # One or more non-pipe or escaped pipe
)
(?:\| # Optional separator followed by group 5 (flags)
(?P<flags>\S+)
Expand All @@ -161,14 +161,16 @@ def findandreplace(bot, trigger):
return

sep = trigger.group('sep')
old = trigger.group('old').replace('\\%s' % sep, sep)
escape_sequence_pattern = re.compile(r'\\[\\%s]' % sep)

old = escape_sequence_pattern.sub(decode_escape, trigger.group('old'))
new = trigger.group('new')
me = False # /me command
flags = trigger.group('flags') or ''

# only clean/format the new string if it's non-empty
if new:
new = bold(new.replace('\\%s' % sep, sep))
new = bold(escape_sequence_pattern.sub(decode_escape, new))

# If g flag is given, replace all. Otherwise, replace once.
if 'g' in flags:
Expand Down Expand Up @@ -217,3 +219,12 @@ def repl(s):
phrase = '%s %s' % (trigger.nick, new_phrase)

bot.say(phrase)


def decode_escape(match):
print("Substituting %s" % match.group(0))
return {
r'\\': '\\',
r'\|': '|',
r'\/': '/',
}[match.group(0)]
1 change: 1 addition & 0 deletions test/builtins/test_builtins_find.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def channel():
("An escaped / line.", r"s/\//slash/", f"An escaped {bold('slash')} line."),
("A piped line.", r"s|line|replacement|", f"A piped {bold('replacement')}."),
("An escaped | line.", r"s|\||pipe|", f"An escaped {bold('pipe')} line."),
("An escaped \\ line.", r"s/\\/backslash/", f"An escaped {bold('backslash')} line."),
)


Expand Down

0 comments on commit 580094c

Please sign in to comment.