Action Completer Package¶
Types¶
Contains the base data types used to power the completion and validation of actions.
-
action_completer.types.
ActionCompletable_T
¶ Defines the base data types that are typically used for completion. This type feels like it should be used more, but it really isn’t necessary that often.
- Type
-
action_completer.types.
ActionContext_T
¶ Defines the value types to expect from the extraction of the context for the provided prompt document. Since we need various details about the current state of the prompt buffer, we explicitly define the types of the extracted context tuple through this type.
- Type
-
action_completer.types.
ActionParamBasic_T
¶ Defines the allowable types for basic completion and validation. Typically just a single value, in this case a string.
- Type
-
action_completer.types.
ActionParamIterable_T
¶ Defines the allowable types for iterable completion and validation. Only supports hashable iterables (tuples, lists) of strings.
- Type
-
action_completer.types.
ActionParamCompleter_T
¶ Defines the allowable types for nested completer completion (not validation). Currently just an alias of
Completer
.- Type
-
action_completer.types.
ActionParamCallable_T
¶ Defines the allowable type for callable completions and validation.
- Type
-
action_completer.types.
ActionParamSource_T
¶ Defines the allowable types for action parameter sources that can be completed and validated. This is a union of previously defined action param types.
- Type
-
action_completer.types.
ActionParamValidator_T
¶ Defines the allowable types for validation callables or instances.
- Type
-
action_completer.types.
LazyString_T
¶ Defines the allowable types for optionally lazy evaluated strings. This is either just an instance of a string or a callable that results in a string.
- Type
-
action_completer.types.
LazyText_T
¶ Similar to
LazyString_T
, this defines the allowable types for optionally lazy evaluated strings or instances ofFormattedText
. This is either just an instance or a callable that results in an instance.- Type
-
class
action_completer.types.
Action
(action=None, params=None, style=None, selected_style=None, display=None, display_meta=None, active=None, capture_all=False)[source]¶ Defines a completable action.
-
action
¶ The callable function that should be completeable and can be called after validation of the given action and associated parameters
- Type
Optional[Callable[.., Any]], optional
-
params
¶ The list of action parameters in the same order of positional arguments for the
action
callable.- Type
Optional[List[ActionParam]], optional
-
style
¶ The style string to apply to completion results for the action
- Type
Optional[
LazyString_T
], optional
-
selected_style
¶ The style string to apply to selected completion results for the action
- Type
Optional[
LazyString_T
], optional
-
display
¶ The custom display to apply to completion results for the action
- Type
Optional[
LazyText_T
], optional
-
display_meta
¶ The custom display meta (description) to apply to completion results for the action
- Type
Optional[
LazyText_T
], optional
-
active
¶ A callable filter that results in a boolean to indicate if the action should be considred as active and displayed as a completion result
- Type
Optional[Filter], optional
-
capture_all
¶ If there is the option for this action to accept more arguments than defined by the provided parameters, this flag will allow for any number of following arguments (after parameters) as additional positional arguments to the provided
action
callable, defaults to False- Type
bool, optional
-
-
class
action_completer.types.
ActionGroup
(children, style=None, selected_style=None, display=None, display_meta=None, active=None)[source]¶ Defines a completable group of either nested action groups or leaf actions.
Important
It is crucial for proper fragment extraction that no children keys contain spaces. Each non-escaped space is considered a new fragment and used to find the context for both completion and validation. Although it would technically be possible to support child key completion with spaces, it involves more complex features of prompt-toolkit than just completion.
Therefore, I have decided to hold the opinion that no spaces should be allowable as keys in a group’s children. A post-initialization validator exists to ensure this is true for any action group you define.
-
children
¶ The dictionary of completion text (keys) to a nested action group or a callable action (value) that forms the group’s children
- Type
Dict[str, Union[ActionGroup, Action]]
-
style
¶ The style string to apply to completion results for the action group
- Type
Optional[
LazyString_T
], optional
-
selected_style
¶ The style string to apply to selected completion results for the action group
- Type
Optional[
LazyString_T
], optional
-
display
¶ The custom display to apply to completion results for the action group
- Type
Optional[
LazyText_T
], optional
-
display_meta
¶ The custom display meta (description) to apply to completion results for the action group
- Type
Optional[
LazyText_T
], optional
-
active
¶ A callable filter that results in a boolean to indicate if the action group should be considred as active and displayed as a completion result
- Type
Optional[Filter], optional
-
action
(name, params=None, style=None, selected_style=None, display=None, display_meta=None, active=None, capture_all=False)[source]¶ Decorate a callable as an action within the current group.
Basic root level actions are easily defined directly off of the completer instance like follows:
from prompt_toolkit.shortcuts import prompt from action_completer import ActionCompleter completer = ActionCompleter() @completer.action("hello") def _hello_action(): print("Hello, World!") completer.run_action(prompt(">>> ", completer=completer)) # available through the following prompt: # >>> hello # Hello, World!
You can nest actions in sub-groups by first calling
group()
to define a new group and base all actions from theaction
decorator provided on that new group.- Parameters
name (str) – The completion name that triggers this action
params (Optional[List[ActionParam]], optional) – The list of action parameters to complete and handle within the action
style (Optional[
LazyString_T
], optional) – The style string to apply to completion results for the actionselected_style (Optional[
LazyString_T
], optional) – The style string to apply to selected completion results for the actiondisplay (Optional[
LazyText_T
], optional) – The custom display to apply to completion results for the actiondisplay_meta (Optional[
LazyText_T
], optional) – The custom display meta (description) to apply to completion results for the actionactive (Optional[Filter], optional) – A callable filter that results in a boolean to indicate if the action group should be considred as active and displayed as a completion result
capture_all (bool, optional) – If there is the option for this action to accept more arguments than defined by the provided parameters, this flag will allow for any number of following arguments (after parameters) as additional positional arguments to the provided
action
callable, defaults to False
- Raises
ValueError – When the given action name contains spaces
ValueError – When the given action name is already present in the group
- Returns
The newly wrapped action callable
- Return type
Callable[.., Any]
-
group
(name, children=None, style=None, selected_style=None, display=None, display_meta=None, active=None)[source]¶ Create a new subgroup for the current group.
By default the
ActionCompleter
comes with aroot
group to extend from. However, if you want to build a set of nested commands, you can use this function to register a new group on the completer.from prompt_toolkit.shortcuts import prompt from action_completer import ActionCompleter completer = ActionCompleter() nested_group = completer.group("hello") @nested_group.action("world") def _hello_world_action(): print("Hello, World!") completer.run_action(prompt(">>> ", completer=completer)) # available through the following prompt: # >>> hello world # Hello, World!
- Parameters
name (str) – The completion text that triggers this group
children (Dict[str, Union[ActionGroup, Action]]) – The dictionary of completion text (keys) to a nested action group or a callable action (value) that forms the group’s children
style (Optional[
LazyString_T
], optional) – The style string to apply to completion results for the action groupselected_style (Optional[
LazyString_T
], optional) – The style string to apply to selected completion results for the action groupdisplay (Optional[
LazyText_T
], optional) – The custom display to apply to completion results for the action groupdisplay_meta (Optional[
LazyText_T
], optional) – The custom display meta (description) to apply to completion results for the action groupactive (Optional[Filter], optional) – A callable filter that results in a boolean to indicate if the action group should be considred as active and displayed as a completion result
- Raises
ValueError – When the provided group name contains spaces
ValueError – When the provided group name is already in the current group
- Returns
The created action group
- Return type
-
-
class
action_completer.types.
ActionParam
(source, cast=None, style=None, selected_style=None, display=None, display_meta=None, validators=None)[source]¶ Defines a completable action parameter.
-
source
¶ The completion source for the parameter
- Type
-
cast
¶ The type to cast the action parameter to during execution of the action tied to this parameter
- Type
Optional[Type], optional
-
style
¶ The style string to apply to completion results for the action parameter
- Type
Optional[
LazyString_T
], optional
-
selected_style
¶ The style string to apply to selected completion results for the action parameter
- Type
Optional[
LazyString_T
], optional
-
display
¶ The custom display to apply to completion results for the action parameter
- Type
Optional[
LazyText_T
], optional
-
display_meta
¶ The custom display meta (description) to apply to completion results for the action parameter
- Type
Optional[
LazyText_T
], optional
-
validators
¶ The list of validators to run in-order against the parameter value during validation
- Type
Optional[List[
ActionParamValidator_T
]], optional
-
-
action_completer.types.
param
(source, cast=None, style=None, selected_style=None, display=None, display_meta=None, validators=None)[source]¶ Create a new action parameter for an action.
Basic parameters can be defined right before defining a method as an action.
from pathlib import Path from prompt_toolkit.shortcuts import prompt from prompt_toolkit.validation import Validator from action_completer import ActionCompleter completer = ActionCompleter() @completer.action("cat") @completer.param( PathCompleter(), cast=Path, validators=[Validator.from_callable(lambda p: Path(p).is_file())] ) def _cat_action(filepath: Path): with filepath.open("r") as file_handle: print(file_handle.read()) completer.run_action(prompt(">>> ", completer=completer)) # available through the following prompt: # # $ echo "my content" > ./my-file.txt # >>> cat ./my-file.txt # my content
Important
The application order of
param
decorators is very important. Since these defined action parameters are applied as positional arguments to the action, we are opinionated on the ordering that decorators should be applied.We purposefully reverse the traditional decorator application order to make the readability of actions created purely through decorators a bit easier. This means that the last parameter should be the first decorator applied to the action callable, and the very last decorator applied to the action callable should be the action decorator. This benefits readability by ordering the defined param decorators top-to-bottom as arguments applied left-to-right in the action callable.
# valid @action("test") @param("source1") @param("source2") def _valid_action(source1: str, source2: str): ... # invalid @param("source2") @param("source1") @action("test") def _invalid_action(source1: str, source2: str): ... # also invalid @action("test") @param("source2") @param("source1") def _also_invalid_action(source1: str, source2: str): ...
We have some checks to raise warnings in case you accidentally use an invalid spec for applying the decorators. Although I’m not 100% sure it will capture all the possible states of defining actions that you might come up with.
If you don’t like this design, I would recommend you instead pass
ActionParam
instances to theparams
keyword argument when using theaction()
decorator.- Parameters
source (
ActionParamSource_T
) – The completion source for the parametercast (Optional[Type], optional) – The type to cast the action parameter to during execution of the action tied to this parameter
style (Optional[
LazyString_T
], optional) – The style string to apply to completion results for the action parameterselected_style (Optional[
LazyString_T
], optional) – The style string to apply to selected completion results for the action parameterdisplay (Optional[
LazyText_T
], optional) – The custom display to apply to completion results for the action parameterdisplay_meta (Optional[
LazyText_T
], optional) – The custom display meta (description) to apply to completion results for the action parametervalidators (Optional[List[
ActionParamValidator_T
]], optional) – The list of validators to run in-order against the parameter value during validation
- Returns
The newly wrapped action with the defined parameters
- Return type
Callable[.., Any]
Completer¶
Contains the completer for a single root ActionGroup
instance.
Registering actions for the completer can be done in several different ways.
The simplest way, is to use the provided action()
decorator:
from prompt_toolkit.shortcuts import prompt
from action_completer import ActionCompleter
completer = ActionCompleter()
@completer.action("hello")
def _hello_world():
print("Hello, World!")
completer.run_action(prompt(">>> ", completer=completer))
Another common way is to build the root ActionGroup
structure yourself:
from prompt_toolkit.shortcuts import prompt
from action_completer import ActionCompleter, ActionGroup, Action
def _hello_world():
print("Hello, World!")
root_group = ActionGroup({"hello": Action(_hello_world)})
completer = ActionCompleter(root_group)
completer.run_action(prompt(">>> ", completer=completer))
Lastly, if you really need it, you can specify the starting structure of the completer through a very specific dictionary structure. I personally needed this in the past and haven’t yet had the chance to remove the need of it.
from prompt_toolkit.shortcuts import prompt
from action_completer import ActionCompleter
def _hello_world():
print("Hello, World!")
completer = ActionCompleter.from_dict({
"root": {
"hello": {
"action": _hello_world
}
},
"fuzzy_tolerance: 75
})
completer.run_action(prompt(">>> ", completer=completer))
-
class
action_completer.completer.
ActionCompleter
(root=None, fuzzy_tolerance=75)[source]¶ Custom completer for actions.
This completer should be relatively easy to consume and provides features for extending completions with custom styles and display properties.
The most straight forward method of defining actions is to use the
action()
decorator right off of the completer:from prompt_toolkit.shortcuts import prompt from action_completer import ActionCompleter completer = ActionCompleter() @completer.action("hello") def _hello_world(): print("Hello, World!") output = prompt(">>> ", completer=completer) completer.run_action(output) # >>> hello # Hello, World!
If you want to go a more declarative route, you can explicitly build the tree structure of
ActionGroup
,Action
, andActionParam
yourself.from prompt_toolkit.shortcuts import prompt from action_completer import ActionCompelter, ActionGroup, Action, ActionParam def _hello_world(): print("Hello, World!") ACTIONS = ActionGroup({ "hello": Action(_hello_world) }) completer = ActionCompleter(ACTIONS) output = prompt(">>> ", completer=completer) completer.run_action(output) # >>> hello # Hello, World!
-
get_completions
(document, complete_event)[source]¶ Generate completions for the given prompt document.
- Parameters
document (Document) – The document directly from the prompt to generate completions for
complete_event (CompleteEvent) – The completion event for the completions
- Yields
prompt_toolkit.completion.Completion – A completion for the given prompt document
- Return type
Generator
[Completion
,None
,None
]
-
get_partial_action
(prompt_result)[source]¶ Get the partial for the action callable with action parameters included.
- Parameters
prompt_result (str) – The result of the completer’s prompt call
- Raises
ValueError – When no actionable action can be determined from the given prompt result
- Returns
A partial callable for the related action including clean parameters
- Return type
Callable[.., Any]
-
Validator¶
Contains the validator used to validate data produced by the action completer.
To retreive this validator, it is highly recommend that you utilize the
get_validator()
method.
If your completer instance is dynamic, you probably want to fetch this validator
instance for every call to prompt()
.
For example:
from prompt_toolkit.shortcuts import prompt
from action_completer import ActionCompleter
completer = ActionCompleter()
# ... register completer actions
while True:
# note the call to `get_validator` for every call to prompt
prompt_result = prompt(
">>> ",
completer=completer,
validator=completer.get_validator()
)
You could also initialize the ActionValidator
yourself by passing
through the root
group of the ActionCompleter
:
from prompt_toolkit.shortcuts import prompt
from action_completer import ActionCompleter, ActionValidator
completer = ActionCompleter()
# ... register completer actions
while True:
validator = ActionValidator(completer.root)
prompt_result = prompt(
">>> ",
completer=completer,
validator=validator
)
-
class
action_completer.validator.
ActionValidator
(root)[source]¶ Custom validator for a
ActionCompleter
.Most of the time you should get this instance from
get_validator()
however if you need to build an instance of it yourself you can use the following logic:from action_completer.completer import ActionCompleter from action_completer.validator import ActionValidator completer = ActionCompleter() validator = ActionValidator(completer.root)
-
validate
(document)[source]¶ Validate the current document from the
ActionCompleter
.- Parameters
document (Document) – The document to validate
- Raises
ValidationError – When validation of the given document fails.
-
Utilities¶
Contains utility functions used throughout various points of the module.
-
action_completer.utils.
decode_completion
(text)[source]¶ Reverse the encoding process for completion text.
-
action_completer.utils.
encode_completion
(text)[source]¶ Encode some completion text for writing to the user’s current prompt buffer.
-
action_completer.utils.
extract_context
(action_group, fragments)[source]¶ Extract the current context for a root action group and buffer fragments.
- Parameters
action_group (ActionGroup) – The root action group to start context extraction
fragments (List[str]) – The text fragments extracted from the current user’s prompt buffer
- Returns
A tuple of (parent ActionGroup, parent name, current ActionGroup/Action, list of remaining fragments [parameters])
- Return type
-
action_completer.utils.
format_dynamic_value
(template, text)[source]¶ Format the given template text for the dynamic value.
-
action_completer.utils.
get_best_choice
(choices, user_value)[source]¶ Guess the best choice from an interable of choice strings given a target value.
This method has a few caveats to make using it with completion a bit easier:
If no choices are given, nothing is returned.
If only 1 choice is given, that choice is always returned.
If the given value (taget) text is not alphanumerical, the first available choice is returned.
-
action_completer.utils.
get_dynamic_value
(source, value, text, default=None)[source]¶ Resolve a lazy/dynamic completion format value.
The given value will be formatted in place of any
{completion}
usage within the dynamic text. The following example will display the description containing the completion value in place of the given value@completer.action("hello-world") @completer.param(["1", "2", "3"], display_meta="Will display {completion}") def _hello_world(number_value: str): print(f"Hello, {number_value!s}!")
- Parameters
source (
ActionCompletable_T
) – The source for the completionvalue (
LazyText_T
) – The dynamic value that needs to be resolved for the sourcetext (str) – The current text fragment that triggered the given source
default (Optional[Union[str, FormattedText]]) – A default if the given value resolves to None. Defaults to None.
- Returns
Either a string or
FormattedText
instance if the value is properly resolved, otherwise defaults to the default- Return type
Optional[Union[str, FormattedText]]
-
action_completer.utils.
get_fragments
(text)[source]¶ Get the properly split fragments from the current user’s prompt buffer.
-
action_completer.utils.
iter_best_choices
(choices, user_value, fuzzy_tolerance=None)[source]¶ Iterate over the sorted closest strings from some choices using fuzzy matching.
This iterator has a few caveats that make using it with completion a bit easier:
If no choices are given, nothing is ever yielded.
If only 1 choice is given, that choice will always be yielded.
Basically no fuzzy matching will occur against to allow for filtering out just a single choice.
If the given value (target) text is empty, all choices will be yielded.
If the given value (target) text is not alphanumerical, all choices are yielded.
- Parameters
- Yields
str – Sorted best matching strings from choices in comparison to
user_value
- Return type