**Talon Abstractions Overview**  
You can define and override behavior in Python files. You use Module objects to define things like actions and settings, and you use Context objects to override stuff builtin to Talon or defined by a Module in specific contexts, such as overriding an action when a specific application is focused or on a specific operating system.

Talon provides abstractions for defining flexible command spoken forms. A list maps spoken forms to corresponding values. A capture can use combinations of lists, other captures, and explicit spoken forms to map what the user says to values. As an example, a list can map the names of numbers to their numeric values to allow defining voice commands that take a number as an argument, such as allowing saying "delete twenty five" to press the delete key 25 times or "delete thirty" to press the delete key 30 times. Captures allow for complex combinations of spoken forms to allow for flexible commands.

Talon provides constructs for understanding context. A Tag is either active or not. Tags can be activated and deactivated through commands or as a consequence of other context information. A Scope can have arbitrary values. This can allow matching on properties of a scope or specific scope values. A Mode defines a set of commands users can chain together. Users typically define a mode if they only want commands from that mode active in specific contexts, such as an exam mode limiting the available commands to a small, approved subset.

Context is important. A lot of functionality needs to be overridden based on the nature of the current operating system or application to work correctly.

**Declarations**  
How to create a Module:

\`\`\`  
from talon import Module

mod \= Module()  
\`\`\`

This defines a Module named mod that you can use to define things. The following code examples will assume that a Module named mod is defined.

There are 2 ways to declare an action on a Module. The first is writing @mod.action and then a function definition. 

\`\`\`  
@mod.action  
def action\_name():  
    "Description of the action"  
\`\`\`

The second is writing @mod.action\_class and then a class providing the action declarations in its methods. This is just a more convenient way to declare multiple actions.

\`\`\`  
@mod.action\_class  
class Actions:  
    def action\_name():  
        "Description of the action"

    def second\_action(arg1: int, arg2: str='') \-\> str:  
        "Action with arguments, return type, and body"  
        return 'test'  
\`\`\`

Note that each action needs a documentation string and type annotations for its parameters and return type. You may write a default implementation for actions declared on a Module.

You can declare a capture on a Module by writing @mod.capture(rule=rule), where rule is the capture rule, and then a function for the capture that has a documentation string. If you want to provide an implementation for a capture, provide a function definition deciding what to convert the spoken input to. The spoken input can be parsed as a list of words, but you can also use the names of lists and captures used as attributes on the input. You define the rule using the same syntax that you use for command spoken forms in a .talon file. 

\`\`\`  
from contextlib import suppress

\# \<\> denotes a capture  
\# \[\] is for an optional part  
\# | means or  
@mod.capture(rule="\[minus\] \<number\_small\> \[(point | dot) \<number\_small\>\]")  
def user\_file\_set\_small\_float(m) \-\> float:  
    """A floating point number"""  
    is\_negative \= m\[0\] \== "minus"  
    number \= m.number\_small\_1  
    with suppress(AttributeError):  
        decimal\_part \= m.number\_small\_2  
        if decimal\_part \> 9:  
            decimal\_part /= 100  
        else:  
            decimal\_part /= 10  
        number \+= decimal\_part  
    if is\_negative:  
        number \*= \-1  
    return number

@mod.capture(rule="\<user.user\_file\_set\_small\_float\>")  
def user\_file\_set\_small\_float\_string(m) \-\> str:  
    """A string representation of a floating point number"""  
    return str(m.user\_file\_set\_small\_float)  
\`\`\`

A scope is a highly flexible abstraction for context matching. You declare a scope on a Module by writing @mod.scope followed by a function that returns a dictionary mapping the name of the scope to its value. You then call .update() on that function to update the value of the scope.

\`\`\`  
from talon import Module, ui

from pathlib import Path

mod \= Module()  
previous\_app\_name: str \= ""

@mod.scope  
def scope\_updater():  
    return {"user\_file\_set\_previous\_app": previous\_app\_name}

\# when a new window is focused, update the previous app  
def update\_previous\_app(\*args):  
    global previous\_app\_name  
    app \= ui.active\_app()  
    app\_name \= Path(app.path).stem  
    if app\_name \== previous\_app\_name:  
        return   
    scope\_updater.update()  
    previous\_app\_name \= app\_name

ui.register("win\_focus", update\_previous\_app)  
\`\`\`

This scope can then be used from a .talon file like this:

\`\`\`  
user.user\_file\_set\_previous\_app: Microsoft Word  
mode: sleep  
\-  
\# when Microsoft Word was the previous app and Talon is not listening for regular commands,  
\# pause the current video and switch back to Word so I can take notes  
pause:  
    key('space')  
    apps.focus("Microsoft Word")  
\`\`\`

You declare a setting on a module by calling mod.setting(). You can access a setting value in Python code by calling settings.get() with the setting name. Example:

\`\`\`  
from talon import actions, settings

mod.setting(  
    "user\_file\_set\_spaces\_per\_tab",  
    type=int,  
    default=4,  
    desc="The number of spaces to use per tab"  
)

@mod.action\_class  
class Actions:  
    def user\_file\_set\_insert\_tab\_spaces(number\_of\_tabs: int=1):  
        """Insert the specified number of tabs as spaces"""  
        spaces\_per\_tab \= settings.get("user.user\_file\_set\_spaces\_per\_tab")  
        actions.insert(spaces\_per\_tab\*number\_of\_tabs\*" ")  
\`\`\`

Note that top level Python code (code with no indentation or invoked by code with no indentation) should not access settings or use other Talon constructs because they are not defined until the file finishes loading. This sometimes makes the code seem to work until you restart Talon\!

You declare a list on a Module by calling mod.list() with the name of the list and a description. Example:

\`\`\`  
mod.list("list\_name", desc="list description")  
\`\`\`

You declare a mode on a Module by calling mod.mode() with the name of the mode and a description. Example:

\`\`\`  
mod.mode("user\_file\_set\_video\_mode", desc="Watching a video")  
\`\`\`

The following example .talon files are for activating the mode and then using it

\`\`\`  
video mode:  
    \# save the current modes  
    mode.save()  
    mode.disable("command")  
    mode.disable("dictation")  
    mode.enable("user.user\_file\_set\_video\_mode")  
\`\`\`

\`\`\`  
mode: user.user\_file\_set\_video\_mode  
\-  
video (pause | play): key('space')  
video backup: key('left')  
mode restore:  
    mode.disable("user.user\_file\_set\_video\_mode")  
    \# restore the saved modes  
    mode.restore()  
\`\`\`

You can define a tag on a Module by calling mod.tag() with the name of the tag and a description. Example:

\`\`\`  
mod.tag("tag\_name", desc="tag description")  
\`\`\`

Anything declared by a user script on a Module is in the user. namespace and must therefore be referenced using the user. prefix. For instance, the above action\_name action example would be called by writing user.action\_name() in a .talon file.

**Implementations**  
How to create a Context object:

\`\`\`  
from talon import Context

ctx \= Context()  
\`\`\`

This creates a context matching the default context. You can make it match a specific context by setting the .matches attribute to a string defining what to match using the same syntax as the context header of a .talon file.

Context matching example:

\`\`\`  
chrome\_ctx \= Context()  
chrome\_ctx.matches \= "app.name: Google Chrome"  
\`\`\`

You can use a Context object to override something when the context it matches is active.

The following example shows how to override an action on a Context. To overwrite an action on a context object named ctx using an action class, write @ctx.action\_class(prefix), where prefix is the prefix for the current namespace, such as “user” for the user. namespace.

\`\`\`  
\#Define an action  
@mod.action\_class  
class Actions:  
    def user\_file\_set\_insert\_reversed(text: str):  
        """Insert the text reversed"""  
        reversed\_list \= \[text\[i\] for i in range(len(text)-1, \-1, \-1)\]  
        reversed\_text \= "".join(reversed\_list)  
        actions.insert(reversed\_text)

\#Override the action when using Google Chrome  
chrome\_ctx \= Context()  
chrome\_ctx.matches \= "app.name: Google Chrome"  
@chrome\_ctx.action\_class("user")  
class ChromeActions:  
    def user\_file\_set\_insert\_reversed(text: str):  
        \#print in the log  
        print('text', text)  
        \#actions.next calls the overridden action, which is sometimes desired  
        actions.next(text)  
\`\`\`

To override a capture on a Context named ctx, write @ctx.capture(capture\_name, rule=rule) where capture\_name is the name of the capture to override and rule is the new capture rule. Example:

\`\`\`  
\# {} denotes a list  
\# \+ means that part of the rule can be repeated  
@mod.capture(rule="{user.letter}+")  
def user\_file\_set\_letters(m) \-\> str:  
    """A series of letters"""  
    return "".join(m.letter\_list)

\# override the letter capture for Google Chrome  
chrome\_context \= Context()  
chrome\_context.matches \= "app.name: Google Chrome"

@chrome\_context.capture("user.user\_file\_set\_letters", rule="\[capital\] {user.letter}+")  
def user\_file\_set\_letters(m) \-\> str:  
    should\_capitalize \= m\[0\] \== "capital"  
    text \= "".join(m.letter\_list)  
    if should\_capitalize:  
        text \= text.upper()  
    return text  
\`\`\`

You can set a setting on a Context called ctx by writing ctx.settings\[setting\_name\] \= new\_value, where setting\_name is the name of the setting and new\_value is the value to store in the setting.

\`\`\`  
mod.setting(  
    "user\_file\_set\_spaces\_per\_tab",  
    type=int,  
    default=4,  
    desc="The number of spaces to use per tab"  
)

@mod.action\_class  
class Actions:  
    def user\_file\_set\_insert\_tab\_spaces(number\_of\_tabs: int=1):  
        """Insert the specified number of tabs as spaces"""  
        spaces\_per\_tab \= settings.get("user.user\_file\_set\_spaces\_per\_tab")  
        actions.insert(spaces\_per\_tab\*number\_of\_tabs\*" ")

\# setting the setting in a context  
text\_edit\_context \= Context()  
text\_edit\_context.matches \= "app.name: TextEdit"

text\_edit\_context.settings\["user.user\_file\_set\_spaces\_per\_tab"\] \= 2  
\`\`\`

You can set a Talon list’s contents when a Context named ctx is active by assigning a dictionary mapping spoken forms to values to ctx.lists\[list\_name\], where list\_name is the name of the list. Example:

\`\`\`  
mod.list("code\_data\_type", desc="Refers to a data type for a programming language")

\# defining the list for python  
python\_context \= Context()  
python\_context.matches \= "code.language: python"

python\_context.lists\["user.code\_data\_type"\] \= {  
    "list": "list",  
    "dictionary": "dict",  
    "integer": "int",  
    "int": "int",  
    "float": "float",  
    "string": "str",  
    "tuple": "tuple",  
    "none": "None"  
}  
\`\`\`

You can activate tags when a Context named ctx is active by assigning a list of tag names to @ctx.tags. Example:

\`\`\`  
mod.tag("user\_file\_set\_command\_activated\_tag", desc="A tag intended to be activated and deactivated by actions")  
mod.tag("user\_file\_set\_context\_activated\_tag", desc="A tag intended to be activated automatically in specific contexts")

\# standard name for a context that does not match anything  
ctx \= Context()

@mod.action\_class  
class Actions:  
    def user\_file\_set\_activate\_tag():  
        """Activate the tag"""  
        ctx.tags \= \["user.user\_file\_set\_command\_activated\_tag"\]

    def user\_file\_set\_deactivate\_tag():  
        """Deactivate the tag"""  
        ctx.tags \= \[\]

\# automatically activate the context activated tag when Google Chrome is focussed  
chrome\_context \= Context()  
chrome\_context.matches \= "app.name: Google Chrome"  
chrome\_context.tags \= \["user.user\_file\_set\_context\_activated\_tag"\]  
\`\`\`