summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2021-02-19 21:35:13 -0500
committerTodd Leonhardt <todd.leonhardt@gmail.com>2021-02-19 21:35:13 -0500
commit3e180a810e9c4b9d251c135667d1d150b0bbd0dd (patch)
tree03e49d5da86d40efa9118eccfd8bd4bbf3dcf86b /examples
parent4c70bdb03d34c43f833bf77c441452cd402d0715 (diff)
parent06aaf962689840631325c70ea7e9056d176c7f67 (diff)
downloadcmd2-git-3e180a810e9c4b9d251c135667d1d150b0bbd0dd.tar.gz
Merge branch 'master' into black
# Conflicts: # cmd2/__init__.py # cmd2/argparse_completer.py # cmd2/argparse_custom.py # cmd2/cmd2.py # cmd2/decorators.py # cmd2/exceptions.py # cmd2/utils.py # examples/arg_decorators.py # examples/argparse_completion.py # examples/modular_commands_main.py # tests/test_argparse_completer.py # tests/test_argparse_custom.py # tests/test_cmd2.py # tests/test_completion.py # tests/test_history.py
Diffstat (limited to 'examples')
-rwxr-xr-xexamples/arg_decorators.py3
-rw-r--r--examples/argparse_completion.py116
-rwxr-xr-xexamples/async_printing.py14
-rw-r--r--examples/modular_commands/commandset_basic.py4
-rw-r--r--examples/modular_commands/commandset_complex.py5
-rw-r--r--examples/modular_commands_main.py121
-rw-r--r--examples/read_input.py112
7 files changed, 187 insertions, 188 deletions
diff --git a/examples/arg_decorators.py b/examples/arg_decorators.py
index f4d92624..49ea9a10 100755
--- a/examples/arg_decorators.py
+++ b/examples/arg_decorators.py
@@ -16,7 +16,8 @@ class ArgparsingApp(cmd2.Cmd):
fsize_parser = cmd2.Cmd2ArgumentParser(description='Obtain the size of a file')
fsize_parser.add_argument('-c', '--comma', action='store_true', help='add comma for thousands separator')
fsize_parser.add_argument('-u', '--unit', choices=['MB', 'KB'], help='unit to display size in')
- fsize_parser.add_argument('file_path', help='path of file', completer_method=cmd2.Cmd.path_complete)
+ fsize_parser.add_argument('file_path', help='path of file',
+ completer=cmd2.Cmd.path_complete)
@cmd2.with_argparser(fsize_parser)
def do_fsize(self, args: argparse.Namespace) -> None:
diff --git a/examples/argparse_completion.py b/examples/argparse_completion.py
index 68da442b..5355cd87 100644
--- a/examples/argparse_completion.py
+++ b/examples/argparse_completion.py
@@ -12,62 +12,22 @@ from typing import (
from cmd2 import (
Cmd,
Cmd2ArgumentParser,
+ CompletionError,
CompletionItem,
with_argparser,
)
-from cmd2.utils import (
- CompletionError,
- basic_complete,
-)
# Data source for argparse.choices
food_item_strs = ['Pizza', 'Ham', 'Ham Sandwich', 'Potato']
-def choices_function() -> List[str]:
- """Choices functions are useful when the choice list is dynamically generated (e.g. from data in a database)"""
- return ['a', 'dynamic', 'list', 'goes', 'here']
-
-
-def completer_function(text: str, line: str, begidx: int, endidx: int) -> List[str]:
- """
- A tab completion function not dependent on instance data. Since custom tab completion operations commonly
- need to modify cmd2's instance variables related to tab completion, it will be rare to need a completer
- function. completer_method should be used in those cases.
- """
- match_against = ['a', 'dynamic', 'list', 'goes', 'here']
- return basic_complete(text, line, begidx, endidx, match_against)
-
-
-def choices_completion_item() -> List[CompletionItem]:
- """Return CompletionItem instead of strings. These give more context to what's being tab completed."""
- items = {1: "My item", 2: "Another item", 3: "Yet another item"}
- return [CompletionItem(item_id, description) for item_id, description in items.items()]
-
-
-def choices_arg_tokens(arg_tokens: Dict[str, List[str]]) -> List[str]:
- """
- If a choices or completer function/method takes a value called arg_tokens, then it will be
- passed a dictionary that maps the command line tokens up through the one being completed
- to their argparse argument name. All values of the arg_tokens dictionary are lists, even if
- a particular argument expects only 1 token.
- """
- # Check if choices_function flag has appeared
- values = ['choices_function', 'flag']
- if 'choices_function' in arg_tokens:
- values.append('is {}'.format(arg_tokens['choices_function'][0]))
- else:
- values.append('not supplied')
- return values
-
-
class ArgparseCompletion(Cmd):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.sport_item_strs = ['Bat', 'Basket', 'Basketball', 'Football', 'Space Ball']
- def choices_method(self) -> List[str]:
- """Choices methods are useful when the choice list is based on instance data of your application"""
+ def choices_provider(self) -> List[str]:
+ """A choices provider is useful when the choice list is based on instance data of your application"""
return self.sport_item_strs
def choices_completion_error(self) -> List[str]:
@@ -82,6 +42,33 @@ class ArgparseCompletion(Cmd):
return self.sport_item_strs
raise CompletionError("debug must be true")
+ # noinspection PyMethodMayBeStatic
+ def choices_completion_item(self) -> List[CompletionItem]:
+ """Return CompletionItem instead of strings. These give more context to what's being tab completed."""
+ items = \
+ {
+ 1: "My item",
+ 2: "Another item",
+ 3: "Yet another item"
+ }
+ return [CompletionItem(item_id, description) for item_id, description in items.items()]
+
+ # noinspection PyMethodMayBeStatic
+ def choices_arg_tokens(self, arg_tokens: Dict[str, List[str]]) -> List[str]:
+ """
+ If a choices or completer function/method takes a value called arg_tokens, then it will be
+ passed a dictionary that maps the command line tokens up through the one being completed
+ to their argparse argument name. All values of the arg_tokens dictionary are lists, even if
+ a particular argument expects only 1 token.
+ """
+ # Check if choices_provider flag has appeared
+ values = ['choices_provider', 'flag']
+ if 'choices_provider' in arg_tokens:
+ values.append('is {}'.format(arg_tokens['choices_provider'][0]))
+ else:
+ values.append('not supplied')
+ return values
+
# Parser for example command
example_parser = Cmd2ArgumentParser(
description="Command demonstrating tab completion with argparse\n" "Notice even the flags of this command tab complete"
@@ -91,40 +78,29 @@ class ArgparseCompletion(Cmd):
# want the entire choices list showing in the usage text for this command.
example_parser.add_argument('--choices', choices=food_item_strs, metavar="CHOICE", help="tab complete using choices")
- # Tab complete from choices provided by a choices function and choices method
- example_parser.add_argument(
- '--choices_function', choices_function=choices_function, help="tab complete using a choices_function"
- )
- example_parser.add_argument('--choices_method', choices_method=choices_method, help="tab complete using a choices_method")
+ example_parser.add_argument('--choices', choices=food_item_strs, metavar="CHOICE",
+ help="tab complete using choices")
- # Tab complete using a completer function and completer method
- example_parser.add_argument(
- '--completer_function', completer_function=completer_function, help="tab complete using a completer_function"
- )
- example_parser.add_argument(
- '--completer_method', completer_method=Cmd.path_complete, help="tab complete using a completer_method"
- )
+ # Tab complete from choices provided by a choices_provider
+ example_parser.add_argument('--choices_provider', choices_provider=choices_provider,
+ help="tab complete using a choices_provider")
+
+ # Tab complete using a completer
+ example_parser.add_argument('--completer', completer=Cmd.path_complete,
+ help="tab complete using a completer")
# Demonstrate raising a CompletionError while tab completing
- example_parser.add_argument(
- '--completion_error',
- choices_method=choices_completion_error,
- help="raise a CompletionError while tab completing if debug is False",
- )
+ example_parser.add_argument('--completion_error', choices_provider=choices_completion_error,
+ help="raise a CompletionError while tab completing if debug is False")
# Demonstrate returning CompletionItems instead of strings
- example_parser.add_argument(
- '--completion_item',
- choices_function=choices_completion_item,
- metavar="ITEM_ID",
- descriptive_header="Description",
- help="demonstrate use of CompletionItems",
- )
+ example_parser.add_argument('--completion_item', choices_provider=choices_completion_item, metavar="ITEM_ID",
+ descriptive_header="Description",
+ help="demonstrate use of CompletionItems")
# Demonstrate use of arg_tokens dictionary
- example_parser.add_argument(
- '--arg_tokens', choices_function=choices_arg_tokens, help="demonstrate use of arg_tokens dictionary"
- )
+ example_parser.add_argument('--arg_tokens', choices_provider=choices_arg_tokens,
+ help="demonstrate use of arg_tokens dictionary")
@with_argparser(example_parser)
def do_example(self, _: argparse.Namespace) -> None:
diff --git a/examples/async_printing.py b/examples/async_printing.py
index 74c4f41f..bcdbc8f0 100755
--- a/examples/async_printing.py
+++ b/examples/async_printing.py
@@ -41,7 +41,7 @@ class AlerterApp(cmd2.Cmd):
self.prompt = "(APR)> "
# The thread that will asynchronously alert the user of events
- self._stop_thread = False
+ self._stop_event = threading.Event()
self._alerter_thread = threading.Thread()
self._alert_count = 0
self._next_alert_time = 0
@@ -56,7 +56,7 @@ class AlerterApp(cmd2.Cmd):
# Therefore this is the best place to start the alerter thread since there is no risk of it alerting
# before the prompt is displayed. You can also start it via a command if its not something that should
# be running during the entire application. See do_start_alerts().
- self._stop_thread = False
+ self._stop_event.clear()
self._alerter_thread = threading.Thread(name='alerter', target=self._alerter_thread_func)
self._alerter_thread.start()
@@ -67,7 +67,7 @@ class AlerterApp(cmd2.Cmd):
# After this function returns, cmdloop() releases self.terminal_lock which could make the alerter
# thread think the prompt is on screen. Therefore this is the best place to stop the alerter thread.
# You can also stop it via a command. See do_stop_alerts().
- self._stop_thread = True
+ self._stop_event.set()
if self._alerter_thread.is_alive():
self._alerter_thread.join()
@@ -76,13 +76,13 @@ class AlerterApp(cmd2.Cmd):
if self._alerter_thread.is_alive():
print("The alert thread is already started")
else:
- self._stop_thread = False
+ self._stop_event.clear()
self._alerter_thread = threading.Thread(name='alerter', target=self._alerter_thread_func)
self._alerter_thread.start()
def do_stop_alerts(self, _):
""" Stops the alerter thread """
- self._stop_thread = True
+ self._stop_event.set()
if self._alerter_thread.is_alive():
self._alerter_thread.join()
else:
@@ -172,7 +172,7 @@ class AlerterApp(cmd2.Cmd):
self._alert_count = 0
self._next_alert_time = 0
- while not self._stop_thread:
+ while not self._stop_event.is_set():
# Always acquire terminal_lock before printing alerts or updating the prompt
# To keep the app responsive, do not block on this call
if self.terminal_lock.acquire(blocking=False):
@@ -197,7 +197,7 @@ class AlerterApp(cmd2.Cmd):
# Don't forget to release the lock
self.terminal_lock.release()
- time.sleep(0.5)
+ self._stop_event.wait(0.5)
if __name__ == '__main__':
diff --git a/examples/modular_commands/commandset_basic.py b/examples/modular_commands/commandset_basic.py
index 226703b8..ab52a326 100644
--- a/examples/modular_commands/commandset_basic.py
+++ b/examples/modular_commands/commandset_basic.py
@@ -9,13 +9,11 @@ from typing import (
from cmd2 import (
Cmd,
CommandSet,
+ CompletionError,
Statement,
with_category,
with_default_category,
)
-from cmd2.utils import (
- CompletionError,
-)
@with_default_category('Basic Completion')
diff --git a/examples/modular_commands/commandset_complex.py b/examples/modular_commands/commandset_complex.py
index a9c39e55..7ab84ac3 100644
--- a/examples/modular_commands/commandset_complex.py
+++ b/examples/modular_commands/commandset_complex.py
@@ -10,9 +10,6 @@ from typing import (
)
import cmd2
-from cmd2 import (
- utils,
-)
@cmd2.with_default_category('Fruits')
@@ -45,7 +42,7 @@ class CommandSetA(cmd2.CommandSet):
self._cmd.poutput(', '.join(['{}'] * len(args)).format(*args))
def complete_durian(self, text: str, line: str, begidx: int, endidx: int) -> List[str]:
- return utils.basic_complete(text, line, begidx, endidx, ['stinks', 'smells', 'disgusting'])
+ return self._cmd.basic_complete(text, line, begidx, endidx, ['stinks', 'smells', 'disgusting'])
elderberry_parser = cmd2.Cmd2ArgumentParser()
elderberry_parser.add_argument('arg1')
diff --git a/examples/modular_commands_main.py b/examples/modular_commands_main.py
index 16b0a798..fc0be7b0 100644
--- a/examples/modular_commands_main.py
+++ b/examples/modular_commands_main.py
@@ -6,73 +6,26 @@ with examples of how to integrate tab completion with argparse-based commands.
"""
import argparse
from typing import (
- Dict,
Iterable,
List,
Optional,
)
-from modular_commands.commandset_basic import ( # noqa: F401
- BasicCompletionCommandSet,
-)
-from modular_commands.commandset_complex import ( # noqa: F401
- CommandSetA,
-)
-from modular_commands.commandset_custominit import ( # noqa: F401
- CustomInitCommandSet,
-)
-
from cmd2 import (
Cmd,
Cmd2ArgumentParser,
CommandSet,
- CompletionItem,
with_argparser,
)
-from cmd2.utils import (
- CompletionError,
- basic_complete,
+from modular_commands.commandset_basic import ( # noqa: F401
+ BasicCompletionCommandSet,
+)
+from modular_commands.commandset_complex import ( # noqa: F401
+ CommandSetA,
+)
+from modular_commands.commandset_custominit import (
+ CustomInitCommandSet, # noqa: F401
)
-
-# Data source for argparse.choices
-food_item_strs = ['Pizza', 'Ham', 'Ham Sandwich', 'Potato']
-
-
-def choices_function() -> List[str]:
- """Choices functions are useful when the choice list is dynamically generated (e.g. from data in a database)"""
- return ['a', 'dynamic', 'list', 'goes', 'here']
-
-
-def completer_function(text: str, line: str, begidx: int, endidx: int) -> List[str]:
- """
- A tab completion function not dependent on instance data. Since custom tab completion operations commonly
- need to modify cmd2's instance variables related to tab completion, it will be rare to need a completer
- function. completer_method should be used in those cases.
- """
- match_against = ['a', 'dynamic', 'list', 'goes', 'here']
- return basic_complete(text, line, begidx, endidx, match_against)
-
-
-def choices_completion_item() -> List[CompletionItem]:
- """Return CompletionItem instead of strings. These give more context to what's being tab completed."""
- items = {1: "My item", 2: "Another item", 3: "Yet another item"}
- return [CompletionItem(item_id, description) for item_id, description in items.items()]
-
-
-def choices_arg_tokens(arg_tokens: Dict[str, List[str]]) -> List[str]:
- """
- If a choices or completer function/method takes a value called arg_tokens, then it will be
- passed a dictionary that maps the command line tokens up through the one being completed
- to their argparse argument name. All values of the arg_tokens dictionary are lists, even if
- a particular argument expects only 1 token.
- """
- # Check if choices_function flag has appeared
- values = ['choices_function', 'flag']
- if 'choices_function' in arg_tokens:
- values.append('is {}'.format(arg_tokens['choices_function'][0]))
- else:
- values.append('not supplied')
- return values
class WithCommandSets(Cmd):
@@ -80,22 +33,10 @@ class WithCommandSets(Cmd):
super().__init__(command_sets=command_sets)
self.sport_item_strs = ['Bat', 'Basket', 'Basketball', 'Football', 'Space Ball']
- def choices_method(self) -> List[str]:
- """Choices methods are useful when the choice list is based on instance data of your application"""
+ def choices_provider(self) -> List[str]:
+ """A choices provider is useful when the choice list is based on instance data of your application"""
return self.sport_item_strs
- def choices_completion_error(self) -> List[str]:
- """
- CompletionErrors can be raised if an error occurs while tab completing.
-
- Example use cases
- - Reading a database to retrieve a tab completion data set failed
- - A previous command line argument that determines the data set being completed is invalid
- """
- if self.debug:
- return self.sport_item_strs
- raise CompletionError("debug must be true")
-
# Parser for example command
example_parser = Cmd2ArgumentParser(
description="Command demonstrating tab completion with argparse\n" "Notice even the flags of this command tab complete"
@@ -103,42 +44,16 @@ class WithCommandSets(Cmd):
# Tab complete from a list using argparse choices. Set metavar if you don't
# want the entire choices list showing in the usage text for this command.
- example_parser.add_argument('--choices', choices=food_item_strs, metavar="CHOICE", help="tab complete using choices")
+ example_parser.add_argument('--choices', choices=['some', 'choices', 'here'], metavar="CHOICE",
+ help="tab complete using choices")
- # Tab complete from choices provided by a choices function and choices method
- example_parser.add_argument(
- '--choices_function', choices_function=choices_function, help="tab complete using a choices_function"
- )
- example_parser.add_argument('--choices_method', choices_method=choices_method, help="tab complete using a choices_method")
+ # Tab complete from choices provided by a choices provider
+ example_parser.add_argument('--choices_provider', choices_provider=choices_provider,
+ help="tab complete using a choices_provider")
- # Tab complete using a completer function and completer method
- example_parser.add_argument(
- '--completer_function', completer_function=completer_function, help="tab complete using a completer_function"
- )
- example_parser.add_argument(
- '--completer_method', completer_method=Cmd.path_complete, help="tab complete using a completer_method"
- )
-
- # Demonstrate raising a CompletionError while tab completing
- example_parser.add_argument(
- '--completion_error',
- choices_method=choices_completion_error,
- help="raise a CompletionError while tab completing if debug is False",
- )
-
- # Demonstrate returning CompletionItems instead of strings
- example_parser.add_argument(
- '--completion_item',
- choices_function=choices_completion_item,
- metavar="ITEM_ID",
- descriptive_header="Description",
- help="demonstrate use of CompletionItems",
- )
-
- # Demonstrate use of arg_tokens dictionary
- example_parser.add_argument(
- '--arg_tokens', choices_function=choices_arg_tokens, help="demonstrate use of arg_tokens dictionary"
- )
+ # Tab complete using a completer
+ example_parser.add_argument('--completer', completer=Cmd.path_complete,
+ help="tab complete using a completer")
@with_argparser(example_parser)
def do_example(self, _: argparse.Namespace) -> None:
diff --git a/examples/read_input.py b/examples/read_input.py
new file mode 100644
index 00000000..e772a106
--- /dev/null
+++ b/examples/read_input.py
@@ -0,0 +1,112 @@
+#!/usr/bin/env python
+# coding=utf-8
+"""
+A simple example demonstrating the various ways to call cmd2.Cmd.read_input() for input history and tab completion
+"""
+from typing import List
+
+import cmd2
+
+EXAMPLE_COMMANDS = "Example Commands"
+
+
+class ReadInputApp(cmd2.Cmd):
+ def __init__(self, *args, **kwargs) -> None:
+ super().__init__(*args, **kwargs)
+ self.prompt = "\n" + self.prompt
+ self.custom_history = ['history 1', 'history 2']
+
+ @cmd2.with_category(EXAMPLE_COMMANDS)
+ def do_basic(self, _) -> None:
+ """Call read_input with no history or tab completion"""
+ self.poutput("Tab completion and up-arrow history is off")
+ try:
+ self.read_input("> ")
+ except EOFError:
+ pass
+
+ @cmd2.with_category(EXAMPLE_COMMANDS)
+ def do_basic_with_history(self, _) -> None:
+ """Call read_input with custom history and no tab completion"""
+ self.poutput("Tab completion is off but using custom history")
+ try:
+ input_str = self.read_input("> ", history=self.custom_history)
+ except EOFError:
+ pass
+ else:
+ self.custom_history.append(input_str)
+
+ @cmd2.with_category(EXAMPLE_COMMANDS)
+ def do_commands(self, _) -> None:
+ """Call read_input the same way cmd2 prompt does to read commands"""
+ self.poutput("Tab completing and up-arrow history configured for commands")
+ try:
+ self.read_input("> ", completion_mode=cmd2.CompletionMode.COMMANDS)
+ except EOFError:
+ pass
+
+ @cmd2.with_category(EXAMPLE_COMMANDS)
+ def do_custom_choices(self, _) -> None:
+ """Call read_input to use custom history and choices"""
+ self.poutput("Tab completing with static choices list and using custom history")
+ try:
+ input_str = self.read_input("> ", history=self.custom_history, completion_mode=cmd2.CompletionMode.CUSTOM,
+ choices=['choice_1', 'choice_2', 'choice_3'])
+ except EOFError:
+ pass
+ else:
+ self.custom_history.append(input_str)
+
+ # noinspection PyMethodMayBeStatic
+ def choices_provider(self) -> List[str]:
+ """Example choices provider function"""
+ return ["from_provider_1", "from_provider_2", "from_provider_3"]
+
+ @cmd2.with_category(EXAMPLE_COMMANDS)
+ def do_custom_choices_provider(self, _) -> None:
+ """Call read_input to use custom history and choices provider function"""
+ self.poutput("Tab completing with choices from provider function and using custom history")
+ try:
+ input_str = self.read_input("> ", history=self.custom_history, completion_mode=cmd2.CompletionMode.CUSTOM,
+ choices_provider=ReadInputApp.choices_provider)
+ except EOFError:
+ pass
+ else:
+ self.custom_history.append(input_str)
+
+ @cmd2.with_category(EXAMPLE_COMMANDS)
+ def do_custom_completer(self, _) -> None:
+ """all read_input to use custom history and completer function"""
+ self.poutput("Tab completing paths and using custom history")
+ try:
+ input_str = self.read_input("> ", history=self.custom_history, completion_mode=cmd2.CompletionMode.CUSTOM,
+ completer=cmd2.Cmd.path_complete)
+ self.custom_history.append(input_str)
+ except EOFError:
+ pass
+
+ @cmd2.with_category(EXAMPLE_COMMANDS)
+ def do_custom_parser(self, _) -> None:
+ """Call read_input to use a custom history and an argument parser"""
+ parser = cmd2.Cmd2ArgumentParser(prog='', description="An example parser")
+ parser.add_argument('-o', '--option', help="an optional arg")
+ parser.add_argument('arg_1', help="a choice for this arg", metavar='arg_1',
+ choices=['my_choice', 'your_choice'])
+ parser.add_argument('arg_2', help="path of something", completer=cmd2.Cmd.path_complete)
+
+ self.poutput("Tab completing with argument parser and using custom history")
+ self.poutput(parser.format_usage())
+
+ try:
+ input_str = self.read_input("> ", history=self.custom_history, completion_mode=cmd2.CompletionMode.CUSTOM,
+ parser=parser)
+ except EOFError:
+ pass
+ else:
+ self.custom_history.append(input_str)
+
+
+if __name__ == '__main__':
+ import sys
+ app = ReadInputApp()
+ sys.exit(app.cmdloop())