summaryrefslogtreecommitdiff
path: root/examples/hooks.py
diff options
context:
space:
mode:
authorkotfu <kotfu@kotfu.net>2018-07-21 12:56:25 -0600
committerkotfu <kotfu@kotfu.net>2018-07-21 12:56:25 -0600
commitcb0c58db58920122a66cafedc764e59d5087c841 (patch)
tree74144c7d0b498705f3f6c23fed512843f6c8fd03 /examples/hooks.py
parent3f737b4b25810cbdc8386777ade0c9b819bb25c1 (diff)
downloadcmd2-git-cb0c58db58920122a66cafedc764e59d5087c841.tar.gz
Add hook example
Diffstat (limited to 'examples/hooks.py')
-rw-r--r--examples/hooks.py115
1 files changed, 115 insertions, 0 deletions
diff --git a/examples/hooks.py b/examples/hooks.py
new file mode 100644
index 00000000..66922b79
--- /dev/null
+++ b/examples/hooks.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python
+# coding=utf-8
+"""
+A sample application for cmd2 demonstrating how to use hooks.
+
+This application shows how to use postparsing hooks to allow case insensitive
+command names, abbreviated commands, as well as allowing numeric arguments to
+follow a command without any intervening whitespace.
+
+"""
+
+import re
+
+from typing import List
+
+import cmd2
+
+
+class CmdLineApp(cmd2.Cmd):
+ """Example cmd2 application demonstrating the use of hooks.
+
+ This simple application has one command, `list` which generates a list
+ of 10 numbers. This command takes one optional argument, which is the
+ number to start on.
+
+ We have three postparsing hooks, which allow the user to enter:
+
+ (Cmd) list 5
+ (Cmd) L 5
+ (Cmd) l 5
+ (Cmd) L5
+ (Cmd) LI5
+
+ and have them all treated as valid input which prints a list of 10 numbers
+ starting with the number 5.
+ """
+
+ # Setting this true makes it run a shell command if a cmd2/cmd command doesn't exist
+ # default_to_shell = True
+ def __init__(self, *args, **kwargs):
+ # sneakily remove the cmd2.Cmd command called load
+ # this lets a user enter a command like "l5" and allows it to
+ # be unambiguous
+ delattr(cmd2.Cmd, "do_load")
+
+ super().__init__(*args, **kwargs)
+
+ # register three hooks
+ self.register_postparsing_hook(self.add_whitespace_hook)
+ self.register_postparsing_hook(self.downcase_hook)
+ self.register_postparsing_hook(self.abbrev_hook)
+
+ def add_whitespace_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.PostparsingData:
+ """A hook to split alphabetic command names immediately followed by a number.
+
+ l24 -> l 24
+ list24 -> list 24
+ list 24 -> list 24
+
+ """
+ command = data.statement.command
+ # regular expression with looks for:
+ # ^ - the beginning of the string
+ # ([^\s\d]+) - one or more non-whitespace non-digit characters, set as capture group 1
+ # (\d+) - one or more digit characters, set as capture group 2
+ command_pattern = re.compile(r'^([^\s\d]+)(\d+)')
+ match = command_pattern.search(command)
+ if match:
+ data.statement = self.statement_parser.parse("{} {} {}".format(
+ match.group(1),
+ match.group(2),
+ '' if data.statement.args is None else data.statement.args
+ ))
+ return data
+
+ def downcase_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.PostparsingData:
+ """A hook to make uppercase commands lowercase."""
+ command = data.statement.command.lower()
+ data.statement = self.statement_parser.parse("{} {}".format(
+ command,
+ '' if data.statement.args is None else data.statement.args
+ ))
+ return data
+
+ def abbrev_hook(self, data: cmd2.plugin.PostparsingData) -> cmd2.plugin.PostparsingData:
+ """Accept unique abbreviated commands"""
+ target = 'do_' + data.statement.command
+ if not target in dir(self):
+ # check if the entered command might be an abbreviation
+ funcs = [func for func in self.keywords if func.startswith(data.statement.command)]
+ if len(funcs) == 1:
+ raw = data.statement.raw.replace(data.statement.command, funcs[0], 1)
+ data.statement = self.statement_parser.parse(raw)
+ return data
+
+ @cmd2.with_argument_list
+ def do_list(self, arglist: List[str]) -> None:
+ """Generate a list of 10 numbers."""
+ if arglist:
+ first = arglist[0]
+ try:
+ first = int(first)
+ except ValueError:
+ first = 1
+ else:
+ first = 1
+ last = first + 10
+
+ for x in range(first, last):
+ self.poutput(x)
+
+
+if __name__ == '__main__':
+ c = CmdLineApp()
+ c.cmdloop()