summaryrefslogtreecommitdiff
path: root/cmd2/cmd2.py
diff options
context:
space:
mode:
Diffstat (limited to 'cmd2/cmd2.py')
-rw-r--r--cmd2/cmd2.py66
1 files changed, 63 insertions, 3 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index ce19cda8..045e6a1b 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -408,6 +408,10 @@ class Cmd(cmd.Cmd):
import atexit
atexit.register(readline.write_history_file, persistent_history_file)
+ # 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)
@@ -1670,7 +1674,7 @@ class Cmd(cmd.Cmd):
statement = self.statement_parser.parse_command_only(line)
return statement.command, statement.args, statement.command_and_args
- def onecmd_plus_hooks(self, line):
+ def onecmd_plus_hooks(self, line: str) -> bool:
"""Top-level function called by cmdloop() to handle parsing a line and running the command and all of its hooks.
:param line: str - line of text read from input
@@ -1680,9 +1684,17 @@ class Cmd(cmd.Cmd):
stop = False
try:
statement = self._complete_statement(line)
- (stop, statement) = self.postparsing_precmd(statement)
+ # call the postparsing hooks
+ for func in self._postparsing_hooks:
+ (stop, statement) = func(statement)
+ if stop:
+ break
+ if not stop:
+ (stop, statement) = self.postparsing_precmd(statement)
if stop:
- return self.postparsing_postcmd(stop)
+ # we need to not run the command, but
+ # we need to run the finalization hooks
+ raise EmptyStatement
try:
if self.allow_redirection:
@@ -1690,9 +1702,20 @@ class Cmd(cmd.Cmd):
timestart = datetime.datetime.now()
if self._in_py:
self._last_result = None
+
+ # precommand hooks
+ for func in self._precmd_hooks:
+ statement = func(statement)
statement = self.precmd(statement)
+
+ # go run the command function
stop = self.onecmd(statement)
+
+ # postcommand hooks
+ for func in self._postcmd_hooks:
+ stop = func(stop, statement)
stop = self.postcmd(stop, statement)
+
if self.timing:
self.pfeedback('Elapsed: %s' % str(datetime.datetime.now() - timestart))
finally:
@@ -3047,6 +3070,8 @@ Script should contain one command per line, just like command would be typed in
self.cmdqueue.extend(callargs)
# Always run the preloop first
+ for func in self._preloop_hooks:
+ func()
self.preloop()
# If transcript-based regression testing was requested, then do that instead of the main loop
@@ -3065,8 +3090,43 @@ Script should contain one command per line, just like command would be typed in
self._cmdloop()
# Run the postloop() no matter what
+ for func in self._postloop_hooks:
+ func()
self.postloop()
+ ###
+ #
+ # plugin related functions
+ #
+ ###
+ def _initialize_plugin_system(self):
+ """Initialize the plugin system"""
+ self._preloop_hooks = []
+ self._postloop_hooks = []
+ self._postparsing_hooks = []
+ self._precmd_hooks = []
+ self._postcmd_hooks = []
+
+ def register_preloop_hook(self, func):
+ """Register a function to be called at the beginning of the command loop."""
+ self._preloop_hooks.append(func)
+
+ def register_postloop_hook(self, func):
+ """Register a function to be called at the end of the command loop."""
+ self._postloop_hooks.append(func)
+
+ def register_postparsing_hook(self, func):
+ """Register a function to be called after parsing user input but before running the command"""
+ self._postparsing_hooks.append(func)
+
+ def register_precmd_hook(self, func):
+ """Register a function to be called before the command function."""
+ self._precmd_hooks.append(func)
+
+ def register_postcmd_hook(self, func):
+ """Register a function to be called after the command function."""
+ self._postcmd_hooks.append(func)
+
class HistoryItem(str):
"""Class used to represent an item in the History list.