Skip to content

Commit 34bfac9

Browse files
committed
Merge branch 'main' into refactor_complete
2 parents b3ee325 + 4482a79 commit 34bfac9

File tree

3 files changed

+75
-16
lines changed

3 files changed

+75
-16
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ repos:
1111
exclude: ^examples/transcripts/
1212

1313
- repo: https://github.com/astral-sh/ruff-pre-commit
14-
rev: "v0.15.0"
14+
rev: "v0.15.1"
1515
hooks:
1616
- id: ruff-format
1717
args: [--config=ruff.toml]

cmd2/pt_utils.py

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@
3232
class Cmd2Completer(Completer):
3333
"""Completer that delegates to cmd2's completion logic."""
3434

35-
def __init__(self, cmd_app: 'Cmd', custom_settings: utils.CustomCompletionSettings | None = None) -> None:
35+
def __init__(
36+
self,
37+
cmd_app: 'Cmd',
38+
custom_settings: utils.CustomCompletionSettings | None = None,
39+
) -> None:
3640
"""Initialize prompt_toolkit based completer class."""
3741
self.cmd_app = cmd_app
3842
self.custom_settings = custom_settings
@@ -168,10 +172,31 @@ def store_string(self, string: str) -> None:
168172
class Cmd2Lexer(Lexer):
169173
"""Lexer that highlights cmd2 command names, aliases, and macros."""
170174

171-
def __init__(self, cmd_app: 'Cmd') -> None:
172-
"""Initialize the lexer."""
175+
def __init__(
176+
self,
177+
cmd_app: 'Cmd',
178+
command_color: str = 'ansigreen',
179+
alias_color: str = 'ansicyan',
180+
macro_color: str = 'ansimagenta',
181+
flag_color: str = 'ansired',
182+
argument_color: str = 'ansiyellow',
183+
) -> None:
184+
"""Initialize the Lexer.
185+
186+
:param cmd_app: cmd2.Cmd instance
187+
:param command_color: color to use for commands, defaults to 'ansigreen'
188+
:param alias_color: color to use for aliases, defaults to 'ansicyan'
189+
:param macro_color: color to use for macros, defaults to 'ansimagenta'
190+
:param flag_color: color to use for flags, defaults to 'ansired'
191+
:param argument_color: color to use for arguments, defaults to 'ansiyellow'
192+
"""
173193
super().__init__()
174194
self.cmd_app = cmd_app
195+
self.command_color = command_color
196+
self.alias_color = alias_color
197+
self.macro_color = macro_color
198+
self.flag_color = flag_color
199+
self.argument_color = argument_color
175200

176201
def lex_document(self, document: Document) -> Callable[[int], Any]:
177202
"""Lex the document."""
@@ -195,16 +220,30 @@ def get_line(lineno: int) -> list[tuple[str, str]]:
195220

196221
if command:
197222
# Determine the style for the command
198-
style = ''
199-
if command in self.cmd_app.get_all_commands():
200-
style = 'ansigreen'
201-
elif command in self.cmd_app.aliases:
202-
style = 'ansicyan'
203-
elif command in self.cmd_app.macros:
204-
style = 'ansimagenta'
205-
206-
# Add the command with the determined style
207-
tokens.append((style, command))
223+
shortcut_found = False
224+
for shortcut, _ in self.cmd_app.statement_parser.shortcuts:
225+
if command.startswith(shortcut):
226+
# Add the shortcut with the command style
227+
tokens.append((self.command_color, shortcut))
228+
229+
# If there's more in the command word, it's an argument
230+
if len(command) > len(shortcut):
231+
tokens.append((self.argument_color, command[len(shortcut) :]))
232+
233+
shortcut_found = True
234+
break
235+
236+
if not shortcut_found:
237+
style = ''
238+
if command in self.cmd_app.get_all_commands():
239+
style = self.command_color
240+
elif command in self.cmd_app.aliases:
241+
style = self.alias_color
242+
elif command in self.cmd_app.macros:
243+
style = self.macro_color
244+
245+
# Add the command with the determined style
246+
tokens.append((style, command))
208247

209248
# Add the rest of the line
210249
if cmd_end < len(line):
@@ -224,9 +263,9 @@ def get_line(lineno: int) -> list[tuple[str, str]]:
224263
if space:
225264
tokens.append(('', text))
226265
elif flag:
227-
tokens.append(('ansired', text))
266+
tokens.append((self.flag_color, text))
228267
elif (quoted or word) and text not in exclude_tokens:
229-
tokens.append(('ansiyellow', text))
268+
tokens.append((self.argument_color, text))
230269
else:
231270
tokens.append(('', text))
232271
elif line:

tests/test_pt_utils.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def __init__(self):
3636
self.history = []
3737
self.statement_parser = Mock()
3838
self.statement_parser.terminators = [';']
39+
self.statement_parser.shortcuts = []
3940
self.statement_parser._command_pattern = re.compile(r'\A\s*(\S*?)(\s|\Z)')
4041
self.aliases = {}
4142
self.macros = {}
@@ -158,6 +159,25 @@ def test_lex_document_unclosed_quote(self, mock_cmd_app):
158159

159160
assert tokens == [('ansigreen', 'echo'), ('', ' '), ('ansiyellow', '"hello')]
160161

162+
def test_lex_document_shortcut(self, mock_cmd_app):
163+
"""Test lexing a shortcut."""
164+
mock_cmd_app.statement_parser.shortcuts = [('!', 'shell')]
165+
lexer = pt_utils.Cmd2Lexer(cast(Any, mock_cmd_app))
166+
167+
# Case 1: Shortcut glued to argument
168+
line = "!ls"
169+
document = Document(line)
170+
get_line = lexer.lex_document(document)
171+
tokens = get_line(0)
172+
assert tokens == [('ansigreen', '!'), ('ansiyellow', 'ls')]
173+
174+
# Case 2: Shortcut with space
175+
line = "! ls"
176+
document = Document(line)
177+
get_line = lexer.lex_document(document)
178+
tokens = get_line(0)
179+
assert tokens == [('ansigreen', '!'), ('', ' '), ('ansiyellow', 'ls')]
180+
161181

162182
class TestCmd2Completer:
163183
def test_get_completions(self, mock_cmd_app: MockCmd, monkeypatch) -> None:

0 commit comments

Comments
 (0)