Skip to content

Initialization

Here is a basic example cmd2 application which demonstrates many capabilities which you may wish to utilize while initializing the app:

    #!/usr/bin/env python3
    # coding=utf-8
    """A simple example cmd2 application demonstrating the following:
         1) Colorizing/stylizing output
         2) Using multiline commands
         3) Persistent history
         4) How to run an initialization script at startup
         5) How to group and categorize commands when displaying them in help
         6) Opting-in to using the ipy command to run an IPython shell
         7) Allowing access to your application in py and ipy
         8) Displaying an intro banner upon starting your application
         9) Using a custom prompt
        10) How to make custom attributes settable at runtime
    """
    import cmd2
    from cmd2 import (
        Bg,
        Fg,
        style,
    )


    class BasicApp(cmd2.Cmd):
        CUSTOM_CATEGORY = 'My Custom Commands'

        def __init__(self):
            super().__init__(
                multiline_commands=['echo'],
                persistent_history_file='cmd2_history.dat',
                startup_script='scripts/startup.txt',
                include_ipy=True,
            )

            # Prints an intro banner once upon application startup
            self.intro = style('Welcome to cmd2!', fg=Fg.RED, bg=Bg.WHITE, bold=True)

            # Show this as the prompt when asking for input
            self.prompt = 'myapp> '

            # Used as prompt for multiline commands after the first line
            self.continuation_prompt = '... '

            # Allow access to your application in py and ipy via self
            self.self_in_py = True

            # Set the default category name
            self.default_category = 'cmd2 Built-in Commands'

            # Color to output text in with echo command
            self.foreground_color = Fg.CYAN.name.lower()

            # Make echo_fg settable at runtime
            fg_colors = [c.name.lower() for c in Fg]
            self.add_settable(
                cmd2.Settable('foreground_color', str, 'Foreground color to use with echo command', self,
                              choices=fg_colors)
            )

        @cmd2.with_category(CUSTOM_CATEGORY)
        def do_intro(self, _):
            """Display the intro banner"""
            self.poutput(self.intro)

        @cmd2.with_category(CUSTOM_CATEGORY)
        def do_echo(self, arg):
            """Example of a multiline command"""
            fg_color = Fg[self.foreground_color.upper()]
            self.poutput(style(arg, fg=fg_color))


    if __name__ == '__main__':
        app = BasicApp()
        app.cmdloop()

Cmd class initializer

A cmd2.Cmd instance or subclass instance is an interactive CLI application framework. There is no good reason to instantiate Cmd itself; rather, it's useful as a superclass of a class you define yourself in order to inherit Cmd's methods and encapsulate action methods.

Certain things must be initialized within the __init__() method of your class derived from cmd2.Cmd(all arguments to __init__() are optional):

cmd2.Cmd.__init__

__init__(completekey='tab', stdin=None, stdout=None, *, persistent_history_file='', persistent_history_length=1000, startup_script='', silence_startup_script=False, include_py=False, include_ipy=False, allow_cli_args=True, transcript_files=None, allow_redirection=True, multiline_commands=None, terminators=None, shortcuts=None, command_sets=None, auto_load_commands=True, allow_clipboard=True, suggest_similar_command=False)

An easy but powerful framework for writing line-oriented command interpreters. Extends Python's cmd package.

PARAMETER DESCRIPTION
completekey

readline name of a completion key, default to Tab

TYPE: str DEFAULT: 'tab'

stdin

alternate input file object, if not specified, sys.stdin is used

TYPE: Optional[TextIO] DEFAULT: None

stdout

alternate output file object, if not specified, sys.stdout is used

TYPE: Optional[TextIO] DEFAULT: None

persistent_history_file

file path to load a persistent cmd2 command history from

TYPE: str DEFAULT: ''

persistent_history_length

max number of history items to write to the persistent history file

TYPE: int DEFAULT: 1000

startup_script

file path to a script to execute at startup

TYPE: str DEFAULT: ''

silence_startup_script

if True, then the startup script's output will be suppressed. Anything written to stderr will still display.

TYPE: bool DEFAULT: False

include_py

should the "py" command be included for an embedded Python shell

TYPE: bool DEFAULT: False

include_ipy

should the "ipy" command be included for an embedded IPython shell

TYPE: bool DEFAULT: False

allow_cli_args

if True, then cmd2.Cmd.init will process command line arguments as either commands to be run or, if -t or --test are given, transcript files to run. This should be set to False if your application parses its own command line arguments.

TYPE: bool DEFAULT: True

transcript_files

pass a list of transcript files to be run on initialization. This allows running transcript tests when allow_cli_args is False. If allow_cli_args is True this parameter is ignored.

TYPE: Optional[List[str]] DEFAULT: None

allow_redirection

If False, prevent output redirection and piping to shell commands. This parameter prevents redirection and piping, but does not alter parsing behavior. A user can still type redirection and piping tokens, and they will be parsed as such but they won't do anything.

TYPE: bool DEFAULT: True

multiline_commands

list of commands allowed to accept multi-line input

TYPE: Optional[List[str]] DEFAULT: None

terminators

list of characters that terminate a command. These are mainly intended for terminating multiline commands, but will also terminate single-line commands. If not supplied, the default is a semicolon. If your app only contains single-line commands and you want terminators to be treated as literals by the parser, then set this to an empty list.

TYPE: Optional[List[str]] DEFAULT: None

shortcuts

dictionary containing shortcuts for commands. If not supplied, then defaults to constants.DEFAULT_SHORTCUTS. If you do not want any shortcuts, pass an empty dictionary.

TYPE: Optional[Dict[str, str]] DEFAULT: None

command_sets

Provide CommandSet instances to load during cmd2 initialization. This allows CommandSets with custom constructor parameters to be loaded. This also allows the a set of CommandSets to be provided when auto_load_commands is set to False

TYPE: Optional[Iterable[CommandSet]] DEFAULT: None

auto_load_commands

If True, cmd2 will check for all subclasses of CommandSet that are currently loaded by Python and automatically instantiate and register all commands. If False, CommandSets must be manually installed with register_command_set.

TYPE: bool DEFAULT: True

allow_clipboard

If False, cmd2 will disable clipboard interactions

TYPE: bool DEFAULT: True

suggest_similar_command

If True, cmd2 will attempt to suggest the most similar command when the user types a command that does not exist. Default: False.

TYPE: bool DEFAULT: False

Source code in cmd2/cmd2.py
def __init__(
    self,
    completekey: str = 'tab',
    stdin: Optional[TextIO] = None,
    stdout: Optional[TextIO] = None,
    *,
    persistent_history_file: str = '',
    persistent_history_length: int = 1000,
    startup_script: str = '',
    silence_startup_script: bool = False,
    include_py: bool = False,
    include_ipy: bool = False,
    allow_cli_args: bool = True,
    transcript_files: Optional[List[str]] = None,
    allow_redirection: bool = True,
    multiline_commands: Optional[List[str]] = None,
    terminators: Optional[List[str]] = None,
    shortcuts: Optional[Dict[str, str]] = None,
    command_sets: Optional[Iterable[CommandSet]] = None,
    auto_load_commands: bool = True,
    allow_clipboard: bool = True,
    suggest_similar_command: bool = False,
) -> None:
    """An easy but powerful framework for writing line-oriented command
    interpreters. Extends Python's cmd package.

    :param completekey: readline name of a completion key, default to Tab
    :param stdin: alternate input file object, if not specified, sys.stdin is used
    :param stdout: alternate output file object, if not specified, sys.stdout is used
    :param persistent_history_file: file path to load a persistent cmd2 command history from
    :param persistent_history_length: max number of history items to write
                                      to the persistent history file
    :param startup_script: file path to a script to execute at startup
    :param silence_startup_script: if ``True``, then the startup script's output will be
                                   suppressed. Anything written to stderr will still display.
    :param include_py: should the "py" command be included for an embedded Python shell
    :param include_ipy: should the "ipy" command be included for an embedded IPython shell
    :param allow_cli_args: if ``True``, then [cmd2.Cmd.__init__][] will process command
                           line arguments as either commands to be run or, if ``-t`` or
                           ``--test`` are given, transcript files to run. This should be
                           set to ``False`` if your application parses its own command line
                           arguments.
    :param transcript_files: pass a list of transcript files to be run on initialization.
                             This allows running transcript tests when ``allow_cli_args``
                             is ``False``. If ``allow_cli_args`` is ``True`` this parameter
                             is ignored.
    :param allow_redirection: If ``False``, prevent output redirection and piping to shell
                              commands. This parameter prevents redirection and piping, but
                              does not alter parsing behavior. A user can still type
                              redirection and piping tokens, and they will be parsed as such
                              but they won't do anything.
    :param multiline_commands: list of commands allowed to accept multi-line input
    :param terminators: list of characters that terminate a command. These are mainly
                        intended for terminating multiline commands, but will also
                        terminate single-line commands. If not supplied, the default
                        is a semicolon. If your app only contains single-line commands
                        and you want terminators to be treated as literals by the parser,
                        then set this to an empty list.
    :param shortcuts: dictionary containing shortcuts for commands. If not supplied,
                      then defaults to constants.DEFAULT_SHORTCUTS. If you do not want
                      any shortcuts, pass an empty dictionary.
    :param command_sets: Provide CommandSet instances to load during cmd2 initialization.
                         This allows CommandSets with custom constructor parameters to be
                         loaded.  This also allows the a set of CommandSets to be provided
                         when `auto_load_commands` is set to False
    :param auto_load_commands: If True, cmd2 will check for all subclasses of `CommandSet`
                               that are currently loaded by Python and automatically
                               instantiate and register all commands. If False, CommandSets
                               must be manually installed with `register_command_set`.
    :param allow_clipboard: If False, cmd2 will disable clipboard interactions
    :param suggest_similar_command: If ``True``, ``cmd2`` will attempt to suggest the most
                                    similar command when the user types a command that does
                                    not exist. Default: ``False``.
    """
    # Check if py or ipy need to be disabled in this instance
    if not include_py:
        setattr(self, 'do_py', None)
    if not include_ipy:
        setattr(self, 'do_ipy', None)

    # initialize plugin system
    # needs to be done before we call __init__(0)
    self._initialize_plugin_system()

    # Call super class constructor
    super().__init__(completekey=completekey, stdin=stdin, stdout=stdout)

    # Attributes which should NOT be dynamically settable via the set command at runtime
    self.default_to_shell = False  # Attempt to run unrecognized commands as shell commands
    self.allow_redirection = allow_redirection  # Security setting to prevent redirection of stdout

    # Attributes which ARE dynamically settable via the set command at runtime
    self.always_show_hint = False
    self.debug = False
    self.echo = False
    self.editor = Cmd.DEFAULT_EDITOR
    self.feedback_to_output = False  # Do not include nonessentials in >, | output by default (things like timing)
    self.quiet = False  # Do not suppress nonessential output
    self.scripts_add_to_history = True  # Scripts and pyscripts add commands to history
    self.timing = False  # Prints elapsed time for each command

    # The maximum number of CompletionItems to display during tab completion. If the number of completion
    # suggestions exceeds this number, they will be displayed in the typical columnized format and will
    # not include the description value of the CompletionItems.
    self.max_completion_items = 50

    # A dictionary mapping settable names to their Settable instance
    self._settables: Dict[str, Settable] = dict()
    self._always_prefix_settables: bool = False

    # CommandSet containers
    self._installed_command_sets: Set[CommandSet] = set()
    self._cmd_to_command_sets: Dict[str, CommandSet] = {}

    self.build_settables()

    # Use as prompt for multiline commands on the 2nd+ line of input
    self.continuation_prompt = '> '

    # Allow access to your application in embedded Python shells and scripts py via self
    self.self_in_py = False

    # Commands to exclude from the help menu and tab completion
    self.hidden_commands = ['eof', '_relative_run_script']

    # Initialize history
    self.persistent_history_file = ''
    self._persistent_history_length = persistent_history_length
    self._initialize_history(persistent_history_file)

    # Commands to exclude from the history command
    self.exclude_from_history = ['eof', 'history']

    # Dictionary of macro names and their values
    self.macros: Dict[str, Macro] = dict()

    # Keeps track of typed command history in the Python shell
    self._py_history: List[str] = []

    # The name by which Python environments refer to the PyBridge to call app commands
    self.py_bridge_name = 'app'

    # Defines app-specific variables/functions available in Python shells and pyscripts
    self.py_locals: Dict[str, Any] = dict()

    # True if running inside a Python shell or pyscript, False otherwise
    self._in_py = False

    self.statement_parser = StatementParser(
        terminators=terminators, multiline_commands=multiline_commands, shortcuts=shortcuts
    )

    # Stores results from the last command run to enable usage of results in Python shells and pyscripts
    self.last_result: Any = None

    # Used by run_script command to store current script dir as a LIFO queue to support _relative_run_script command
    self._script_dir: List[str] = []

    # Context manager used to protect critical sections in the main thread from stopping due to a KeyboardInterrupt
    self.sigint_protection = utils.ContextFlag()

    # If the current command created a process to pipe to, then this will be a ProcReader object.
    # Otherwise it will be None. It's used to know when a pipe process can be killed and/or waited upon.
    self._cur_pipe_proc_reader: Optional[utils.ProcReader] = None

    # Used to keep track of whether we are redirecting or piping output
    self._redirecting = False

    # Used to keep track of whether a continuation prompt is being displayed
    self._at_continuation_prompt = False

    # The multiline command currently being typed which is used to tab complete multiline commands.
    self._multiline_in_progress = ''

    # Set the header used for the help function's listing of documented functions
    self.doc_header = "Documented commands (use 'help -v' for verbose/'help <topic>' for details):"

    # The error that prints when no help information can be found
    self.help_error = "No help on {}"

    # The error that prints when a non-existent command is run
    self.default_error = "{} is not a recognized command, alias, or macro."

    # If non-empty, this string will be displayed if a broken pipe error occurs
    self.broken_pipe_warning = ''

    # Commands that will run at the beginning of the command loop
    self._startup_commands: List[str] = []

    # If a startup script is provided and exists, then execute it in the startup commands
    if startup_script:
        startup_script = os.path.abspath(os.path.expanduser(startup_script))
        if os.path.exists(startup_script):
            script_cmd = f"run_script {utils.quote_string(startup_script)}"
            if silence_startup_script:
                script_cmd += f" {constants.REDIRECTION_OUTPUT} {os.devnull}"
            self._startup_commands.append(script_cmd)

    # Transcript files to run instead of interactive command loop
    self._transcript_files: Optional[List[str]] = None

    # Check for command line args
    if allow_cli_args:
        parser = argparse_custom.DEFAULT_ARGUMENT_PARSER()
        parser.add_argument('-t', '--test', action="store_true", help='Test against transcript(s) in FILE (wildcards OK)')
        callopts, callargs = parser.parse_known_args()

        # If transcript testing was called for, use other arguments as transcript files
        if callopts.test:
            self._transcript_files = callargs
        # If commands were supplied at invocation, then add them to the command queue
        elif callargs:
            self._startup_commands.extend(callargs)
    elif transcript_files:
        self._transcript_files = transcript_files

    # Set the pager(s) for use with the ppaged() method for displaying output using a pager
    if sys.platform.startswith('win'):
        self.pager = self.pager_chop = 'more'
    else:
        # Here is the meaning of the various flags we are using with the less command:
        # -S causes lines longer than the screen width to be chopped (truncated) rather than wrapped
        # -R causes ANSI "style" escape sequences to be output in raw form (i.e. colors are displayed)
        # -X disables sending the termcap initialization and deinitialization strings to the terminal
        # -F causes less to automatically exit if the entire file can be displayed on the first screen
        self.pager = 'less -RXF'
        self.pager_chop = 'less -SRXF'

    # This boolean flag stores whether cmd2 will allow clipboard related features
    self.allow_clipboard = allow_clipboard

    # This determines the value returned by cmdloop() when exiting the application
    self.exit_code = 0

    # This lock should be acquired before doing any asynchronous changes to the terminal to
    # ensure the updates to the terminal don't interfere with the input being typed or output
    # being printed by a command.
    self.terminal_lock = threading.RLock()

    # Commands that have been disabled from use. This is to support commands that are only available
    # during specific states of the application. This dictionary's keys are the command names and its
    # values are DisabledCommand objects.
    self.disabled_commands: Dict[str, DisabledCommand] = dict()

    # If any command has been categorized, then all other commands that haven't been categorized
    # will display under this section in the help output.
    self.default_category = 'Uncategorized'

    # The default key for sorting string results. Its default value performs a case-insensitive alphabetical sort.
    # If natural sorting is preferred, then set this to NATURAL_SORT_KEY.
    # cmd2 uses this key for sorting:
    #     command and category names
    #     alias, macro, settable, and shortcut names
    #     tab completion results when self.matches_sorted is False
    self.default_sort_key = Cmd.ALPHABETICAL_SORT_KEY

    ############################################################################################################
    # The following variables are used by tab completion functions. They are reset each time complete() is run
    # in _reset_completion_defaults() and it is up to completer functions to set them before returning results.
    ############################################################################################################

    # If True and a single match is returned to complete(), then a space will be appended
    # if the match appears at the end of the line
    self.allow_appended_space = True

    # If True and a single match is returned to complete(), then a closing quote
    # will be added if there is an unmatched opening quote
    self.allow_closing_quote = True

    # An optional hint which prints above tab completion suggestions
    self.completion_hint = ''

    # Normally cmd2 uses readline's formatter to columnize the list of completion suggestions.
    # If a custom format is preferred, write the formatted completions to this string. cmd2 will
    # then print it instead of the readline format. ANSI style sequences and newlines are supported
    # when using this value. Even when using formatted_completions, the full matches must still be returned
    # from your completer function. ArgparseCompleter writes its tab completion tables to this string.
    self.formatted_completions = ''

    # Used by complete() for readline tab completion
    self.completion_matches: List[str] = []

    # Use this list if you need to display tab completion suggestions that are different than the actual text
    # of the matches. For instance, if you are completing strings that contain a common delimiter and you only
    # want to display the final portion of the matches as the tab completion suggestions. The full matches
    # still must be returned from your completer function. For an example, look at path_complete() which
    # uses this to show only the basename of paths as the suggestions. delimiter_complete() also populates
    # this list. These are ignored if self.formatted_completions is populated.
    self.display_matches: List[str] = []

    # Used by functions like path_complete() and delimiter_complete() to properly
    # quote matches that are completed in a delimited fashion
    self.matches_delimited = False

    # Set to True before returning matches to complete() in cases where matches have already been sorted.
    # If False, then complete() will sort the matches using self.default_sort_key before they are displayed.
    # This does not affect self.formatted_completions.
    self.matches_sorted = False

    # Command parsers for this Cmd instance.
    self._command_parsers = _CommandParsers(self)

    # Add functions decorated to be subcommands
    self._register_subcommands(self)

    ############################################################################################################
    # The following code block loads CommandSets, verifies command names, and registers subcommands.
    # This block should appear after all attributes have been created since the registration code
    # depends on them and it's possible a module's on_register() method may need to access some.
    ############################################################################################################
    # Load modular commands
    if command_sets:
        for command_set in command_sets:
            self.register_command_set(command_set)

    if auto_load_commands:
        self._autoload_commands()

    # Verify commands don't have invalid names (like starting with a shortcut)
    for cur_cmd in self.get_all_commands():
        valid, errmsg = self.statement_parser.is_valid_command(cur_cmd)
        if not valid:
            raise ValueError(f"Invalid command name '{cur_cmd}': {errmsg}")

    self.suggest_similar_command = suggest_similar_command
    self.default_suggestion_message = "Did you mean {}?"

    # the current command being executed
    self.current_command: Optional[Statement] = None

Cmd instance attributes

The cmd2.Cmd class provides a large number of public instance attributes which allow developers to customize a cmd2 application further beyond the options provided by the __init__() method.

Public instance attributes

Here are instance attributes of cmd2.Cmd which developers might wish override:

  • always_show_hint: if True, display tab completion hint even when completion suggestions print (Default: False)
  • broken_pipe_warning: if non-empty, this string will be displayed if a broken pipe error occurs
  • continuation_prompt: used for multiline commands on 2nd+ line of input
  • debug: if True, show full stack trace on error (Default: False)
  • default_category: if any command has been categorized, then all other commands that haven't been categorized will display under this section in the help output.
  • default_error: the error that prints when a non-existent command is run
  • default_sort_key: the default key for sorting string results. Its default value performs a case-insensitive alphabetical sort.
  • default_to_shell: if True, attempt to run unrecognized commands as shell commands (Default: False)
  • disabled_commands: commands that have been disabled from use. This is to support commands that are only available during specific states of the application. This dictionary's keys are the command names and its values are DisabledCommand objects.
  • doc_header: Set the header used for the help function's listing of documented functions
  • echo: if True, each command the user issues will be repeated to the screen before it is executed. This is particularly useful when running scripts. This behavior does not occur when running a command at the prompt. (Default: False)
  • editor: text editor program to use with edit command (e.g. vim)
  • exclude_from_history: commands to exclude from the history command
  • exit_code: this determines the value returned by cmdloop() when exiting the application
  • feedback_to_output: if True, send nonessential output to stdout, if False send them to stderr (Default: False)
  • help_error: the error that prints when no help information can be found
  • hidden_commands: commands to exclude from the help menu and tab completion
  • last_result: stores results from the last command run to enable usage of results in a Python script or interactive console. Built-in commands don't make use of this. It is purely there for user-defined commands and convenience.
  • macros: dictionary of macro names and their values
  • max_completion_items: max number of CompletionItems to display during tab completion (Default: 50)
  • pager: sets the pager command used by the Cmd.ppaged() method for displaying wrapped output using a pager
  • pager_chop: sets the pager command used by the Cmd.ppaged() method for displaying chopped/truncated output using a pager
  • py_bridge_name: name by which embedded Python environments and scripts refer to the cmd2 application by in order to call commands (Default: app)
  • py_locals: dictionary that defines specific variables/functions available in Python shells and scripts (provides more fine-grained control than making everything available with self_in_py)
  • quiet: if True, then completely suppress nonessential output (Default: False)
  • scripts_add_to_history: if True, scripts and pyscripts add commands to history (Default: True)
  • self_in_py: if True, allow access to your application in py command via self (Default: False)
  • settable: dictionary that controls which of these instance attributes are settable at runtime using the set command
  • timing: if True, display execution time for each command (Default: False)