From ce561c18db42a60394b63fc96f10aec17788cfaf Mon Sep 17 00:00:00 2001 From: Adam Gessaman Date: Mon, 12 Jan 2026 09:16:34 -0800 Subject: [PATCH] feat: Enhance keyword response handling with escape sequence support - Updated `config.ini.example` and `README.md` to document the use of escape sequences for newlines and other formatting in keyword responses. - Implemented `_decode_escape_sequences` method in `CommandManager` to process escape sequences like `\\n`, `\\t`, and `\\r`, allowing users to format responses more flexibly. - Modified `load_keywords` and `load_syntax_patterns` methods to decode escape sequences in keyword responses and formats, improving user experience. --- README.md | 18 ++++++++++++++++++ config.ini.example | 9 +++++++++ modules/command_manager.py | 25 +++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/README.md b/README.md index c21cc5c..615db68 100644 --- a/README.md +++ b/README.md @@ -205,6 +205,24 @@ Keyword responses support these template variables: - `{timestamp}` - Message timestamp - `{path}` - Message routing path +### Adding Newlines + +To add newlines in keyword responses, use `\\n` (double backslash + n): + +```ini +[Keywords] +test = "Line 1\\nLine 2\\nLine 3" +``` + +This will output: +``` +Line 1 +Line 2 +Line 3 +``` + +Other escape sequences: `\\t` (tab), `\\r` (carriage return), `\\\\` (literal backslash) + Example: ```ini [Keywords] diff --git a/config.ini.example b/config.ini.example index f5f5f1d..33471cb 100644 --- a/config.ini.example +++ b/config.ini.example @@ -229,6 +229,15 @@ long_jokes = false # {path_distance} - Total distance between all hops in path with locations (e.g., "123.4km (3 segs, 1 no-loc)") # {firstlast_distance} - Distance between first and last repeater in path (e.g., "45.6km" or empty if locations missing) # {elapsed} - Message elapsed time +# +# To add newlines in responses, use \\n (double backslash + n): +# Example: test = "Line 1\\nLine 2\\nLine 3" +# This will output: +# Line 1 +# Line 2 +# Line 3 +# +# Other escape sequences: \\t (tab), \\r (carriage return), \\\\ (literal backslash) # # Available placeholders (mesh network info - same as Scheduled_Messages): # Total counts (ever heard): diff --git a/modules/command_manager.py b/modules/command_manager.py index b1453b0..53c49e8 100644 --- a/modules/command_manager.py +++ b/modules/command_manager.py @@ -177,6 +177,27 @@ class CommandManager: self.bot.bot_tx_rate_limiter.record_tx() return True + def _decode_escape_sequences(self, text: str) -> str: + """Decode escape sequences in config strings. + + Processes common escape sequences like \\n (newline), \\t (tab), \\\\ (backslash). + This allows users to add newlines in keyword responses using \\n. + + Args: + text: The text string to process. + + Returns: + str: The text with escape sequences decoded. + """ + # Replace escape sequences + # Order matters: \\ must be processed first to avoid double-processing + text = text.replace('\\\\', '\x00') # Temporary placeholder for backslash + text = text.replace('\\n', '\n') # Newline + text = text.replace('\\t', '\t') # Tab + text = text.replace('\\r', '\r') # Carriage return + text = text.replace('\x00', '\\') # Restore backslash + return text + def load_keywords(self) -> Dict[str, str]: """Load keywords from config. @@ -189,6 +210,8 @@ class CommandManager: # Strip quotes from the response if present if response.startswith('"') and response.endswith('"'): response = response[1:-1] + # Decode escape sequences (e.g., \\n for newlines) + response = self._decode_escape_sequences(response) keywords[keyword.lower()] = response return keywords @@ -200,6 +223,8 @@ class CommandManager: # Strip quotes from the response format if present if response_format.startswith('"') and response_format.endswith('"'): response_format = response_format[1:-1] + # Decode escape sequences (e.g., \\n for newlines) + response_format = self._decode_escape_sequences(response_format) syntax_patterns[pattern] = response_format return syntax_patterns