TODO: Audit on Linux """ import time from talon import Context, Module, actions key = actions.key user = actions.user browser = actions.browser module = Module() module.tag("browser", desc="Active when one of the major browsers is active.") context = Context() context.matches = r""" os: windows os: linux app: /firefox/ app: /chrome/ # NOTE: Doesn't work properly with Internet Explorer. Will need its own module. app: /iexplore/ app: /opera/ # TODO: Compatibility with Edge? # title: /- Microsoft Edge/ """ context.tags = ["user.browser"]
from talon import Context, actions ctx = Context() ctx.matches = r""" app: safari """ ctx.tags = ['browser', 'user.tabs'] @ctx.action_class('browser') class BrowserActions: #action(browser.address): def bookmark(): actions.key('cmd-d') def bookmark_tabs(): actions.key('cmd-shift-d') def bookmarks(): actions.key('cmd-alt-b') #action(browser.bookmarks_bar): # key(ctrl-shift-b) def focus_address(): actions.key('cmd-l') #action(browser.focus_page): def focus_search(): actions.browser.focus_address() def go_blank(): actions.key('cmd-n')
from talon import Context, Module, actions, imgui, settings, ui import os import subprocess mod = Module() mod.apps.mintty = """ os: windows and app.name: Terminal os: windows and app.name: mintty.exe """ ctx = Context() ctx.matches = r""" app: mintty """ ctx.tags = [ "terminal", "user.file_manager", "user.generic_terminal", "user.git", "user.kubectl", ] directories_to_remap = {} directories_to_exclude = {} setting_cyg_path = mod.setting( "cygpath", type=str, default="C:\\cygwin64\\bin\\cygpath.exe",
if app: app = app[0] app.focus() # TODO: replace sleep with a registered callback for i in range(25): if ui.active_app().bundle == bundle: break time.sleep(0.01) time.sleep(0.05) def launch_app(path: str): """Launch a new application by path""" ui.launch(path=path) ctx = Context() ctx.commands = { 'focus {self.running}': lambda m: actions.self.focus(m.running), 'launch {self.launch}': lambda m: actions.selef.launch(m.launch), } def update_lists(): new = {} for app in ui.apps(): if app.background and not app.windows(): continue words = app.name.lower().split(' ') for word in words: if word and not word in new: new[word] = app.bundle
from talon import Context hiss_context = Context() hiss_context.matches = r""" tag: user.emacs # Currently, the way Talon parses contexts means the basic context would # override hiss-to-cancel too, so we manually exclude it. user.zoom_mouse_zooming: False """ # Scrolling in Emacs is invasive - it doesn't just scroll, it moves the cursor. # Hisses will misfire while speaking, so we add a deadzone to ignore short # hisses. hiss_context.settings["user.hiss_start_deadzone"] = 300
from talon import Context, Module mod = Module() ctx = Context() symbols = { # operators "fraction": "frac", "summation": "sum", "product": "prod", "product": "lim", "[square] root": "sqrt", "generic root": "root", "integral": "int", "double integral": "iint", "triple integral": "iiint", "times": "times", "divide": "div", "C dot": "cdot", "plus or minus": "pm", "partial": "partial", "infinity": "infty", "(nice frack | nice fraction)": "nicefrac", "binomial": "binom", "vector nabla": "nabla", # accents "accent hat": "hat", "accent tilde": "tilde", "accent dot": "dot", "accent double dot": "ddot", "accent bar": "bar",
return "-".join(mods + [m.unmodified_key]) @mod.capture(rule="<self.key>+") def keys(m) -> str: "A sequence of one or more keys with optional modifiers" return " ".join(m.key_list) @mod.capture(rule="{self.letter}+") def letters(m) -> str: "Multiple letter keys" return "".join(m.letter_list) ctx = Context() modifier_keys = { # If you find 'alt' is often misrecognized, try using 'alter'. "alter": "alt", 'troll': 'ctrl', 'sky': 'shift', "super": "super", #'alter': 'alt', #"command": "cmd", #"control": "ctrl", #"option": "alt", #"shift": "shift", } if app.platform == "mac": modifier_keys["command"] = "cmd" modifier_keys["option"] = "alt"
from talon import Context, actions import os context = Context() context.matches = "title: /VIM/i" vim_normal_mode = actions.user.vim_normal_mode # # Provide simple vim_normal_mode if the user does not already use vim # try: # actions.user.vim_normal_mode() # except KeyError: # print("VIM: using simple insert command") # def vim_normal_mode(cmd: str): # actions.key("escape") # actions.sleep(0.2) # actions.insert(cmd) # except Exception: # print("VIM: using fidget") # vim_normal_mode = actions.user.vim_normal_mode @context.action_class("user") class editor_actions: def editor_get_cursor_position(): title = actions.win.title() return eval(title.split(" | ")[-2]) def editor_go_to_position(row: int, column: int): horizontal_movement = f"{column}l" if column > 0 else "" vim_normal_mode(f"{row}G0{horizontal_movement}")
from talon import Context, Module, actions, imgui, settings, ui, app import os ctx = Context() mod = Module() ctx.matches = r""" app: windows_power_shell app: windows_terminal and win.title: /PowerShell/ """ ctx.tags = [ 'user.file_manager', 'user.generic_terminal', 'user.git', 'user.kubectl', 'terminal' ] user_path = os.path.expanduser("~") directories_to_remap = {} directories_to_exclude = {} @ctx.action_class('edit') class EditActions: def delete_line(): actions.key('esc') @ctx.action_class('user') class UserActions: def file_manager_refresh_title():
actions.mouse_move(*click_info.position_at) click_info.function(click_info.modifiers) # Sleep for enough time for the click to complete. time.sleep(0.1) def click_current(click_info: Click): """Click where the mouse is currently.""" click_info.function() @module.capture def click(m) -> Click: """Get click info from a phrase.""" context = Context() context.lists["self.clicks"] = CLICKS_MAP.keys() @context.capture(rule="<user.modifiers> {self.clicks}") def click(m) -> Click: click_command = m["clicks"] click_function = CLICKS_MAP[click_command] # TODO: Cover no backdated position # # NOTE: This has quirks. If you say "shift click", it will backdate to the # start of "click", not "shift". position = backdated_position(m[-1]) modifiers = m["modifiers"] return Click(click_function, position, modifiers)
) @module.capture def emacs_snippet(m) -> str: """A single Emacs snippet, without prefix.""" @module.action_class class Actions: def emacs_insert_yasnippet(snippet_name: str) -> None: """Insert a yasnippet by name.""" rpc.call("voicemacs-insert-snippet", [snippet_name]) context = Context() context.matches = r""" app: /emacs/ user.emacs-minor-mode: yas-global-mode user.emacs-minor-mode: yas-minor-mode """ context.lists[SNIPPET_LIST_PATH] = {} @context.capture(rule="{" + SNIPPET_LIST_PATH + "}") def emacs_snippet(m) -> str: return getattr(m, SNIPPET_LIST_NAME) def _speech_snippet_list(state):
from talon import Context, Module from user.utils import utilities BRING = utilities.load_toml_relative("config/bringme.toml") mod = Module() ctx = Context() mod.list("websites", desc="Websites") ctx.lists['websites'] = BRING["website"] @mod.capture def websites(m) -> str: "Websites I use often" @ctx.capture(rule="{websites}") def websites(m): return m["websites"]
path = os.path.dirname(os.path.abspath(__file__)) with open(path + "/dictionary/german.dic", encoding='ISO-8859-1') as f: list_of_words = f.read().split("\n") dict_of_words = {} for word in list_of_words: if word.lower() in dict_of_words: # multiple entries, use lower dict_of_words[word.lower()] = word.lower() else: dict_of_words[word.lower()] = word mod = Module() mod.mode('german') ctx = Context() ctx.matches = 'mode: user.german' ctx.settings = { 'speech.engine': 'vosk', # 'speech.language': 'de_DE', 'speech.timeout': 0.3 } mod.setting("german_unicode", type=int, default=1, desc="Enable proper unicode punctuation") mod.list("buchstabe", desc="The spoken phonetic alphabet") ctx.lists["self.buchstabe"] = { "alpha": "a",
from talon import Module, Context, actions, ui, imgui, clip, settings, registry, app mod = Module() ctx = Context() ctx_talon_lists = Context() # restrict all the talon_* lists to when the user.talon_populate_lists tag # is active to prevent them from being active in contexts where they are not wanted. # Do not enable this tag with dragon, as it will be unusable. # with conformer, the latency increase may also be unacceptable depending on your cpu # see https://github.com/knausj85/knausj_talon/issues/600 ctx_talon_lists.matches = r""" tag: user.talon_populate_lists """ mod.tag("talon_python", "Tag to activate talon-specific python commands") mod.tag( "talon_populate_lists", "Tag to activate talon-specific lists of actions, scopes, modes etcetera. Do not use this tag with dragon" ) mod.list("talon_actions") mod.list("talon_lists") mod.list("talon_captures") mod.list("talon_apps") mod.list("talon_tags") mod.list("talon_modes") mod.list("talon_settings") mod.list("talon_scopes") mod.list("talon_modes")
from talon import Context, actions, ui, Module, app is_mac = app.platform == 'mac' ctx = Context() mod = Module() ctx.matches = r''' app: Microsoft Visual Studio 2019 app: devenv.exe ''' @ctx.action_class('win') class win_actions: def filename(): title = actions.win.title() #this doesn't seem to be necessary on VSCode for Mac #if title == "": # title = ui.active_window().doc if is_mac: result = title.split(" — ")[0] else: result = title.split(" - ")[0] if "." in result: return result return "" def file_ext(): return actions.win.filename().split(".")[-1]
from talon import Context, Module, actions # How old a request file needs to be before we declare it stale and are willing # to remove it STALE_TIMEOUT_MS = 60_000 # The amount of time to wait for VSCode to perform a command, in seconds VSCODE_COMMAND_TIMEOUT_SECONDS = 3.0 # When doing exponential back off waiting for vscode to perform a command, how # long to sleep the first time MINIMUM_SLEEP_TIME_SECONDS = 0.0005 mod = Module() ctx = Context() mac_ctx = Context() ctx.matches = r""" app: vscode """ mac_ctx.matches = r""" os: mac app: vscode """ class NotSet: def __repr__(self): return "<argument not set>"
from talon import Context, actions, ui, Module mod = Module() ctx = Context() apps = mod.apps apps.notepad_plus_plus = """ os: windows and app.name: Notepad++ : a free (GNU) source code editor os: windows and app.name: notepad++.exe """ ctx.matches = r""" app: notepad_plus_plus """ ctx.tags = ['user.find_and_replace', 'user.line_commands', 'user.tabs'] @ctx.action_class('app') class AppActions: def tab_previous(): actions.key('ctrl-pageup') def tab_next(): actions.key('ctrl-pagedown') @ctx.action_class('code') class CodeActions:
from talon import Context, Module fractions = { "half": "2", "halves": "2", "quarter": "4", "fourth": "4", "fifth": "5", "sixth": "6", "seventh": "7", "eighth": "8", "ninth": "9", "tenth": "10", } mod = Module() ctx = Context() mod.list("mathfly_fractions", "Fractions") ctx.lists["mathfly_fractions"] = { **fractions, **{f"{k}s": v for k, v in fractions.items()}, }
from talon import Context, actions ctx = Context() ctx.matches = r""" # Its note that this is not actual EMACS itself, but refers to the default # command line editing mode enabled in most common linux shells like bash, zsh, # is also used by lots of command line tools/interfaces, for example gdb # command line interface. # # It more information about the commands can be found here: # https://www.gnu.org/software/bash/manual/html_node/Command-Line-Editing.html # # The idea is that certain shell tools can assert the tag to ensure that the # generic talon line editing commands will still work. Is also allows for # things like zsh being configured in vi mode, but then using gdb with the more # traditional emacs-style keyboard shortcuts tag: user.readline """ @ctx.action_class('edit') class EditActions: def undo(): actions.key('ctrl-x ctrl-u') def up(): actions.key('up') def down(): actions.key('down')
from typing import Optional, Tuple, Literal, Callable import re mod = Module() setting_context_sensitive_dictation = mod.setting( "context_sensitive_dictation", type=bool, default=False, desc= "Look at surrounding text to improve auto-capitalization/spacing in dictation mode. By default, this works by selecting that text & copying it to the clipboard, so it may be slow or fail in some applications.", ) mod.list("prose_modifiers", desc="Modifiers that can be used within prose") mod.list("prose_snippets", desc="Snippets that can be used within prose") ctx = Context() # Maps spoken forms to DictationFormat method names (see DictationFormat below). ctx.lists["user.prose_modifiers"] = { "cap": "cap", "no cap": "no_cap", "no caps": "no_cap", # "no caps" variant for Dragon "no space": "no_space", } ctx.lists["user.prose_snippets"] = { "spacebar": " ", "new line": "\n", "new paragraph": "\n\n", # Curly quotes are used to obtain proper spacing for left and right quotes, but will later be straightened. "open quote": "“", "close quote": "”", "smiley": ":-)",
from talon import Context, Module, actions from talon import ui key = actions.key ctx = Context() ctx.on({'app.bundle': 'com.google.Chrome'}) @ctx.action_class('app') class AppActions: def window_close(): key('cmd-shift-w') def tab_reopen(): key('cmd-shift-t') @ctx.action_class('browser') class BrowserActions: def focus_address(): key('cmd-l') def reload(): key('cmd-r') def reload_hard(): key('cmd-shift-r') def open_private_window(): key('cmd-shift-n')
from talon import Context from user.misc.chunked_phrase import chainable_formatters context = Context() context.matches = """ tag: user.emacs user.emacs-major-mode: cmake-mode """ context.lists["user.chainable_formatters"] = { **chainable_formatters, # TODO: easy way to type vars in cmake # "var": "format_cmake_var", }