fix: Update escape sequence documentation for consistency

- Revised `config.ini.example` and `README.md` to clarify the usage of escape sequences for newlines, changing from double backslashes (`\\n`) to single backslashes (`\n`).
- Enhanced comments in `CommandManager` and `GreeterCommand` to reflect the updated escape sequence behavior, ensuring accurate processing of newline characters and literal backslashes.
- Improved logging in `GreeterCommand` for better debugging of mesh info formatting.
This commit is contained in:
Adam Gessaman
2026-01-13 10:55:59 -08:00
parent 89ecc34ef6
commit c04ecd9ffd
4 changed files with 47 additions and 20 deletions
+4 -3
View File
@@ -207,11 +207,11 @@ Keyword responses support these template variables:
### Adding Newlines
To add newlines in keyword responses, use `\\n` (double backslash + n):
To add newlines in keyword responses, use `\n` (single backslash + n):
```ini
[Keywords]
test = "Line 1\\nLine 2\\nLine 3"
test = "Line 1\nLine 2\nLine 3"
```
This will output:
@@ -221,7 +221,8 @@ Line 2
Line 3
```
Other escape sequences: `\\t` (tab), `\\r` (carriage return), `\\\\` (literal backslash)
To use a literal backslash + n, use `\\n` (double backslash + n).
Other escape sequences: `\t` (tab), `\r` (carriage return), `\\` (literal backslash)
Example:
```ini
+4 -3
View File
@@ -230,14 +230,15 @@ long_jokes = false
# {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"
# To add newlines in responses, use \n (single 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)
# To use a literal backslash + n, use \\n (double backslash + n)
# Other escape sequences: \t (tab), \r (carriage return), \\ (literal backslash)
#
# Available placeholders (mesh network info - same as Scheduled_Messages):
# Total counts (ever heard):
+6 -1
View File
@@ -181,7 +181,11 @@ class CommandManager:
"""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.
This allows users to add newlines in keyword responses using \n (single backslash).
Behavior:
- \n in config file newline character
- \\n in config file literal backslash + n
Args:
text: The text string to process.
@@ -191,6 +195,7 @@ class CommandManager:
"""
# Replace escape sequences
# Order matters: \\ must be processed first to avoid double-processing
# This preserves literal backslashes (\\n becomes \n, not a newline)
text = text.replace('\\\\', '\x00') # Temporary placeholder for backslash
text = text.replace('\\n', '\n') # Newline
text = text.replace('\\t', '\t') # Tab
+33 -13
View File
@@ -123,7 +123,11 @@ class GreeterCommand(BaseCommand):
"""Decode escape sequences in config strings.
Processes common escape sequences like \\n (newline), \\t (tab), \\\\ (backslash).
This allows users to add newlines in greeting messages using \\n.
This allows users to add newlines in greeting messages using \n (single backslash).
Behavior:
- \n in config file newline character
- \\n in config file literal backslash + n
Args:
text: The text string to process.
@@ -133,6 +137,7 @@ class GreeterCommand(BaseCommand):
"""
# Replace escape sequences
# Order matters: \\ must be processed first to avoid double-processing
# This preserves literal backslashes (\\n becomes \n, not a newline)
text = text.replace('\\\\', '\x00') # Temporary placeholder for backslash
text = text.replace('\\n', '\n') # Newline
text = text.replace('\\t', '\t') # Tab
@@ -153,9 +158,13 @@ class GreeterCommand(BaseCommand):
fallback=True, value_type='bool')
self.mesh_info_format = self.get_config_value('Greeter_Command', 'mesh_info_format',
fallback='\n\nMesh Info: {total_contacts} contacts, {repeaters} repeaters')
# Decode escape sequences (e.g., \\n for newlines)
# Decode escape sequences (e.g., \n for newlines)
self.mesh_info_format = self._decode_escape_sequences(self.mesh_info_format)
# Log configuration for debugging
self.logger.debug(f"Greeter config loaded: include_mesh_info={self.include_mesh_info}, "
f"mesh_info_format={repr(self.mesh_info_format)}")
self.per_channel_greetings = self.get_config_value('Greeter_Command', 'per_channel_greetings',
fallback=False, value_type='bool')
self.auto_backfill = self.get_config_value('Greeter_Command', 'auto_backfill',
@@ -1021,17 +1030,28 @@ class GreeterCommand(BaseCommand):
# Add mesh info to the last part if enabled
if self.include_mesh_info:
mesh_info_text = self.mesh_info_format.format(
total_contacts=mesh_info.get('total_contacts', 0),
repeaters=mesh_info.get('repeaters', 0),
companions=mesh_info.get('companions', 0),
recent_activity_24h=mesh_info.get('recent_activity_24h', 0)
)
# Append mesh info to the last greeting part
if formatted_parts:
formatted_parts[-1] += mesh_info_text
else:
formatted_parts.append(mesh_info_text)
self.logger.debug(f"Including mesh info. Format: {repr(self.mesh_info_format)}, Mesh info: {mesh_info}")
try:
mesh_info_text = self.mesh_info_format.format(
total_contacts=mesh_info.get('total_contacts', 0),
repeaters=mesh_info.get('repeaters', 0),
companions=mesh_info.get('companions', 0),
recent_activity_24h=mesh_info.get('recent_activity_24h', 0)
)
self.logger.debug(f"Formatted mesh info text: {repr(mesh_info_text)}")
# Append mesh info to the last greeting part
if formatted_parts:
formatted_parts[-1] += mesh_info_text
else:
formatted_parts.append(mesh_info_text)
except (KeyError, ValueError) as e:
self.logger.warning(f"Error formatting mesh info: {e}. Format string: {repr(self.mesh_info_format)}, Mesh info keys: {list(mesh_info.keys())}")
# Continue without mesh info rather than failing the entire greeting
except Exception as e:
self.logger.error(f"Unexpected error formatting mesh info: {e}", exc_info=True)
# Continue without mesh info rather than failing the entire greeting
else:
self.logger.debug("Mesh info not included (include_mesh_info is False)")
return formatted_parts