Skip to content

Commit d29e28b

Browse files
committed
Added Cmd.macro_arg_complete() to allow custom tab completion for macro arguments.
1 parent 15a72b2 commit d29e28b

File tree

3 files changed

+38
-10
lines changed

3 files changed

+38
-10
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@
77
compatibility in `cmd2` 2.0 family.
88

99
- Enhancements
10+
1011
- Simplified the process to set a custom parser for `cmd2's` built-in commands. See
1112
[custom_parser.py](https://github.com/python-cmd2/cmd2/blob/main/examples/custom_parser.py)
1213
example for more details.
1314

15+
- Added `Cmd.macro_arg_complete()` which tab completes arguments to a macro. Its default
16+
behavior is to perform path completion, but it can be overridden as needed.
17+
1418
## 2.7.0 (June 30, 2025)
1519

1620
- Enhancements

cmd2/cmd2.py

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2062,7 +2062,7 @@ def _perform_completion(
20622062
if custom_settings is None:
20632063
# Check if a macro was entered
20642064
if command in self.macros:
2065-
completer_func = self.path_complete
2065+
completer_func = self.macro_arg_complete
20662066

20672067
# Check if a command was entered
20682068
elif command in self.get_all_commands():
@@ -3542,6 +3542,27 @@ def _alias_list(self, args: argparse.Namespace) -> None:
35423542
# Parsers and functions for macro command and subcommands
35433543
#############################################################
35443544

3545+
def macro_arg_complete(
3546+
self,
3547+
text: str,
3548+
line: str,
3549+
begidx: int,
3550+
endidx: int,
3551+
) -> list[str]:
3552+
"""Tab completes arguments to a macro.
3553+
3554+
Its default behavior is to call path_complete, but you can override this as needed.
3555+
3556+
The args required by this function are defined in the header of Python's cmd.py.
3557+
3558+
:param text: the string prefix we are attempting to match (all matches must begin with it)
3559+
:param line: the current input line with leading whitespace removed
3560+
:param begidx: the beginning index of the prefix text
3561+
:param endidx: the ending index of the prefix text
3562+
:return: a list of possible tab completions
3563+
"""
3564+
return self.path_complete(text, line, begidx, endidx)
3565+
35453566
# Top-level parser for macro
35463567
@staticmethod
35473568
def _build_macro_parser() -> Cmd2ArgumentParser:
@@ -3579,11 +3600,11 @@ def _build_macro_create_parser(cls) -> Cmd2ArgumentParser:
35793600
"\n",
35803601
"The following creates a macro called my_macro that expects two arguments:",
35813602
"\n",
3582-
" macro create my_macro make_dinner --meat {1} --veggie {2}",
3603+
" macro create my_macro make_dinner --meat {1} --veggie {2}",
35833604
"\n",
35843605
"When the macro is called, the provided arguments are resolved and the assembled command is run. For example:",
35853606
"\n",
3586-
" my_macro beef broccoli ---> make_dinner --meat beef --veggie broccoli",
3607+
" my_macro beef broccoli ---> make_dinner --meat beef --veggie broccoli",
35873608
)
35883609
macro_create_parser = argparse_custom.DEFAULT_ARGUMENT_PARSER(description=macro_create_description)
35893610

@@ -3598,19 +3619,19 @@ def _build_macro_create_parser(cls) -> Cmd2ArgumentParser:
35983619
"first argument will populate both {1} instances."
35993620
),
36003621
"\n",
3601-
" macro create ft file_taxes -p {1} -q {2} -r {1}",
3622+
" macro create ft file_taxes -p {1} -q {2} -r {1}",
36023623
"\n",
36033624
"To quote an argument in the resolved command, quote it during creation.",
36043625
"\n",
3605-
" macro create backup !cp \"{1}\" \"{1}.orig\"",
3626+
" macro create backup !cp \"{1}\" \"{1}.orig\"",
36063627
"\n",
36073628
"If you want to use redirection, pipes, or terminators in the value of the macro, then quote them.",
36083629
"\n",
3609-
" macro create show_results print_results -type {1} \"|\" less",
3630+
" macro create show_results print_results -type {1} \"|\" less",
36103631
"\n",
36113632
(
3612-
"Because macros do not resolve until after hitting Enter, tab completion "
3613-
"will only complete paths while typing a macro."
3633+
"Since macros don't resolve until after you press Enter, their arguments tab complete as paths. "
3634+
"This default behavior changes if custom tab completion for macro arguments has been implemented."
36143635
),
36153636
)
36163637
macro_create_parser.epilog = macro_create_parser.create_text_group("Notes", macro_create_notes)

docs/features/shortcuts_aliases_macros.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ Similar to aliases, pipes and redirectors need to be quoted in the definition of
7878

7979
macro create lc !cat "{1}" "|" less
8080

81-
To use the literal string `{1}` in your command, escape it this way: `{{1}}`. Because macros do not
82-
resolve until after hitting `<Enter>`, tab completion will only complete paths while typing a macro.
81+
To use the literal string `{1}` in your command, escape it this way: `{{1}}`.
82+
83+
Since macros don't resolve until after you press `<Enter>`, their arguments tab complete as paths.
84+
You can change this default behavior by overriding `Cmd.macro_arg_complete()` to implement custom
85+
tab completion for macro arguments.
8386

8487
For more details run: `help macro create`
8588

0 commit comments

Comments
 (0)