diff --git a/src/azure-cli-core/azure/cli/core/style.py b/src/azure-cli-core/azure/cli/core/style.py index 335922eb8d7..e61fa61d410 100644 --- a/src/azure-cli-core/azure/cli/core/style.py +++ b/src/azure-cli-core/azure/cli/core/style.py @@ -164,6 +164,41 @@ def format_styled_text(styled_text, theme=None): return ''.join(formatted_parts) +def highlight_command(raw_command): + """Highlight a command with colors. + + For example, for + + az group create --name myrg --location westus + + The command name 'az group create', argument name '--name', '--location' are marked as ACTION style. + The argument value 'myrg' and 'westus' are marked as PRIMARY style. + If the argument is provided as '--location=westus', it will be marked as PRIMARY style. + + :param raw_command: The command that needs to be highlighted. + :type raw_command: str + :return: The styled command text. + :rtype: list + """ + + styled_command = [] + argument_begins = False + + for index, arg in enumerate(raw_command.split()): + spaced_arg = ' {}'.format(arg) if index > 0 else arg + style = Style.PRIMARY + + if arg.startswith('-') and '=' not in arg: + style = Style.ACTION + argument_begins = True + elif not argument_begins and '=' not in arg: + style = Style.ACTION + + styled_command.append((style, spaced_arg)) + + return styled_command + + def _is_modern_terminal(): # Windows Terminal: https://github.com/microsoft/terminal/issues/1040 if 'WT_SESSION' in os.environ: diff --git a/src/azure-cli-core/azure/cli/core/tests/test_style.py b/src/azure-cli-core/azure/cli/core/tests/test_style.py index 69f32b80408..68ac9fe1561 100644 --- a/src/azure-cli-core/azure/cli/core/tests/test_style.py +++ b/src/azure-cli-core/azure/cli/core/tests/test_style.py @@ -68,6 +68,42 @@ def test_format_styled_text_on_error(self): with self.assertRaisesRegex(CLIInternalError, "Invalid styled text."): format_styled_text(["dummy text"]) + def test_highlight_command(self): + from azure.cli.core.style import Style, highlight_command, format_styled_text + + raw_commands = [ + 'az cmd', + 'az cmd sub-cmd', + 'az cmd --arg val', + 'az cmd --arg=val', + 'az cmd --arg "content with space"', + 'az cmd --arg val1 val2', + 'az cmd sub-cmd --arg1 val1 --arg2=" " --arg3 "val2 val3" --arg4 val4' + ] + + expected = [ + [(Style.ACTION, 'az'), (Style.ACTION, ' cmd')], + [(Style.ACTION, 'az'), (Style.ACTION, ' cmd'), (Style.ACTION, ' sub-cmd')], + [(Style.ACTION, 'az'), (Style.ACTION, ' cmd'), (Style.ACTION, ' --arg'), (Style.PRIMARY, ' val')], + [(Style.ACTION, 'az'), (Style.ACTION, ' cmd'), (Style.PRIMARY, ' --arg=val')], + [(Style.ACTION, 'az'), (Style.ACTION, ' cmd'), (Style.ACTION, ' --arg'), (Style.PRIMARY, ' "content'), + (Style.PRIMARY, ' with'), (Style.PRIMARY, ' space"')], + [(Style.ACTION, 'az'), (Style.ACTION, ' cmd'), (Style.ACTION, ' --arg'), + (Style.PRIMARY, ' val1'), (Style.PRIMARY, ' val2')], + [(Style.ACTION, 'az'), (Style.ACTION, ' cmd'), (Style.ACTION, ' sub-cmd'), (Style.ACTION, ' --arg1'), + (Style.PRIMARY, ' val1'), (Style.PRIMARY, ' --arg2="'), (Style.PRIMARY, ' "'), (Style.ACTION, ' --arg3'), + (Style.PRIMARY, ' "val2'), (Style.PRIMARY, ' val3"'), (Style.ACTION, ' --arg4'), (Style.PRIMARY, ' val4')] + ] + + for cmd_index, command in enumerate(raw_commands): + styled_command = highlight_command(command) + expected_style = expected[cmd_index] + + for tpl_index, style_tuple in enumerate(styled_command): + expected_tuple = expected_style[tpl_index] + self.assertEqual(style_tuple[0], expected_tuple[0]) + self.assertEqual(style_tuple[1], expected_tuple[1]) + def test_format_styled_text_theme(self): from azure.cli.core.style import Style, format_styled_text styled_text = [