init commit
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
from talon import Module, actions
|
||||
|
||||
mod = Module()
|
||||
|
||||
mod.list("delimiter_pair", "List of matching pair delimiters")
|
||||
|
||||
|
||||
@mod.capture(rule="{user.delimiter_pair}")
|
||||
def delimiter_pair(m) -> list[str]:
|
||||
pair = m.delimiter_pair.split()
|
||||
assert len(pair) == 2
|
||||
# "space" requires a special written form because Talon lists are whitespace insensitive
|
||||
open = pair[0] if pair[0] != "space" else " "
|
||||
close = pair[1] if pair[1] != "space" else " "
|
||||
return [open, close]
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def delimiter_pair_insert(pair: list[str]):
|
||||
"""Insert a delimiter pair <pair> leaving the cursor in the middle"""
|
||||
actions.user.insert_between(pair[0], pair[1])
|
||||
|
||||
def delimiter_pair_wrap_selection(pair: list[str]):
|
||||
"""Wrap selection with delimiter pair <pair>"""
|
||||
selected = actions.edit.selected_text()
|
||||
actions.insert(f"{pair[0]}{selected}{pair[1]}")
|
||||
@@ -0,0 +1,25 @@
|
||||
list: user.delimiter_pair
|
||||
-
|
||||
|
||||
# Format:
|
||||
# SPOKEN_FORM: LEFT_DELIMITER RIGHT_DELIMITER
|
||||
# Use the literal symbols for delimiters (except for whitespace, which is "space")
|
||||
#
|
||||
# Examples:
|
||||
# round: ( )
|
||||
# pad: space space
|
||||
|
||||
round: ( )
|
||||
box: [ ]
|
||||
diamond: < >
|
||||
curly: { }
|
||||
twin: "' '"
|
||||
quad: '" "'
|
||||
skis: ` `
|
||||
percentages: % %
|
||||
pad: space space
|
||||
|
||||
escaped quad: '\\" \\"'
|
||||
escaped twin: "\\' \\'"
|
||||
escaped round: \( \)
|
||||
escaped box: \[ \]
|
||||
@@ -0,0 +1,153 @@
|
||||
from talon import Context, Module, actions, clip, settings
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
mod.setting(
|
||||
"selected_text_timeout",
|
||||
type=float,
|
||||
default=0.25,
|
||||
desc="Time in seconds to wait for the clipboard to change when trying to get selected text",
|
||||
)
|
||||
|
||||
END_OF_WORD_SYMBOLS = ".!?;:—_/\\|@#$%^&*()[]{}<>=+-~`"
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def selected_text() -> str:
|
||||
timeout = settings.get("user.selected_text_timeout")
|
||||
with clip.capture(timeout) as s:
|
||||
actions.edit.copy()
|
||||
try:
|
||||
return s.text()
|
||||
except clip.NoChange:
|
||||
return ""
|
||||
|
||||
def line_insert_down():
|
||||
actions.edit.line_end()
|
||||
actions.key("enter")
|
||||
|
||||
def selection_clone():
|
||||
actions.edit.copy()
|
||||
actions.edit.select_none()
|
||||
actions.edit.paste()
|
||||
|
||||
def line_clone():
|
||||
# This may not work if editor auto-indents. Is there a better way?
|
||||
actions.edit.line_start()
|
||||
actions.edit.extend_line_end()
|
||||
actions.edit.copy()
|
||||
actions.edit.right()
|
||||
actions.key("enter")
|
||||
actions.edit.paste()
|
||||
|
||||
# # This simpler implementation of select_word mostly works, but in some apps it doesn't.
|
||||
# # See https://github.com/talonhub/community/issues/1084.
|
||||
# def select_word():
|
||||
# actions.edit.right()
|
||||
# actions.edit.word_left()
|
||||
# actions.edit.extend_word_right()
|
||||
|
||||
def select_word():
|
||||
actions.edit.extend_right()
|
||||
character_to_right_of_initial_caret_position = actions.edit.selected_text()
|
||||
|
||||
# Occasionally apps won't let you edit.extend_right()
|
||||
# and therefore won't select text if your caret is on the rightmost character
|
||||
# such as in the Chrome URL bar
|
||||
did_select_text = character_to_right_of_initial_caret_position != ""
|
||||
|
||||
if did_select_text:
|
||||
# .strip() turns newline & space characters into empty string; the empty
|
||||
# string is in any other string, so this works.
|
||||
if (
|
||||
character_to_right_of_initial_caret_position.strip()
|
||||
in END_OF_WORD_SYMBOLS
|
||||
):
|
||||
# Come out of the highlight in the initial position.
|
||||
actions.edit.left()
|
||||
else:
|
||||
# Come out of the highlight one character
|
||||
# to the right of the initial position.
|
||||
actions.edit.right()
|
||||
|
||||
actions.edit.word_left()
|
||||
actions.edit.extend_word_right()
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def paste(text: str):
|
||||
"""Pastes text and preserves clipboard"""
|
||||
|
||||
with clip.revert():
|
||||
clip.set_text(text)
|
||||
actions.edit.paste()
|
||||
# sleep here so that clip.revert doesn't revert the clipboard too soon
|
||||
actions.sleep("150ms")
|
||||
|
||||
def delete_right():
|
||||
"""Delete character to the right"""
|
||||
actions.key("delete")
|
||||
|
||||
def delete_all():
|
||||
"""Delete all text in the current document"""
|
||||
actions.edit.select_all()
|
||||
actions.edit.delete()
|
||||
|
||||
def words_left(n: int):
|
||||
"""Moves left by n words."""
|
||||
for _ in range(n):
|
||||
actions.edit.word_left()
|
||||
|
||||
def words_right(n: int):
|
||||
"""Moves right by n words."""
|
||||
for _ in range(n):
|
||||
actions.edit.word_right()
|
||||
|
||||
def cut_word_left():
|
||||
"""Cuts the word to the left."""
|
||||
actions.edit.extend_word_left()
|
||||
actions.edit.cut()
|
||||
|
||||
def cut_word_right():
|
||||
"""Cuts the word to the right."""
|
||||
actions.edit.extend_word_right()
|
||||
actions.edit.cut()
|
||||
|
||||
def copy_word_left():
|
||||
"""Copies the word to the left."""
|
||||
actions.edit.extend_word_left()
|
||||
actions.edit.copy()
|
||||
|
||||
def copy_word_right():
|
||||
"""Copies the word to the right."""
|
||||
actions.edit.extend_word_right()
|
||||
actions.edit.copy()
|
||||
|
||||
# ----- Start / End of line -----
|
||||
def select_line_start():
|
||||
"""Select to start of current line"""
|
||||
if actions.edit.selected_text():
|
||||
actions.edit.left()
|
||||
actions.edit.extend_line_start()
|
||||
|
||||
def select_line_end():
|
||||
"""Select to end of current line"""
|
||||
if actions.edit.selected_text():
|
||||
actions.edit.right()
|
||||
actions.edit.extend_line_end()
|
||||
|
||||
def line_middle():
|
||||
"""Go to the middle of the line"""
|
||||
actions.edit.select_line()
|
||||
half_line_length = int(len(actions.edit.selected_text()) / 2)
|
||||
actions.edit.left()
|
||||
for i in range(0, half_line_length):
|
||||
actions.edit.right()
|
||||
|
||||
def cut_line():
|
||||
"""Cut current line"""
|
||||
actions.edit.select_line()
|
||||
actions.edit.cut()
|
||||
@@ -0,0 +1,85 @@
|
||||
# Compound of action(select, clear, copy, cut, paste, etc.) and modifier(word,
|
||||
# line, etc.) commands for editing text.
|
||||
# eg: "select line", "clear all"
|
||||
# For overriding or creating aliases for specific actions, this function will
|
||||
# also accept strings, e.g. `user.edit_command("delete", "wordLeft")`.
|
||||
# See edit_command_modifiers.py to discover the correct string for the modify argument,
|
||||
# and `edit_command_actions.py` `simple_action_callbacks` to find strings for the action argument.
|
||||
<user.edit_action> <user.edit_modifier>: user.edit_command(edit_action, edit_modifier)
|
||||
|
||||
# Zoom
|
||||
zoom in: edit.zoom_in()
|
||||
zoom out: edit.zoom_out()
|
||||
zoom reset: edit.zoom_reset()
|
||||
|
||||
# Searching
|
||||
find it: edit.find()
|
||||
next one: edit.find_next()
|
||||
|
||||
# Navigation
|
||||
|
||||
# The reason for these spoken forms is that "page up" and "page down" are globally defined as keys.
|
||||
scroll up: edit.page_up()
|
||||
scroll down: edit.page_down()
|
||||
|
||||
# go left, go left left down, go 5 left 2 down
|
||||
# go word left, go 2 words right
|
||||
go <user.navigation_step>+: user.perform_navigation_steps(navigation_step_list)
|
||||
|
||||
go line start | head: edit.line_start()
|
||||
go line end | tail: edit.line_end()
|
||||
|
||||
go way left:
|
||||
edit.line_start()
|
||||
edit.line_start()
|
||||
go way right: edit.line_end()
|
||||
go way up: edit.file_start()
|
||||
go way down: edit.file_end()
|
||||
|
||||
go top: edit.file_start()
|
||||
go bottom: edit.file_end()
|
||||
|
||||
go page up: edit.page_up()
|
||||
go page down: edit.page_down()
|
||||
|
||||
# Indentation
|
||||
indent [more]: edit.indent_more()
|
||||
(indent less | out dent): edit.indent_less()
|
||||
|
||||
# Copy
|
||||
copy that: edit.copy()
|
||||
|
||||
# Cut
|
||||
cut that: edit.cut()
|
||||
|
||||
# Paste
|
||||
(pace | paste) (that | it): edit.paste()
|
||||
(pace | paste) enter:
|
||||
edit.paste()
|
||||
key(enter)
|
||||
paste match: edit.paste_match_style()
|
||||
|
||||
# Duplication
|
||||
clone that: edit.selection_clone()
|
||||
clone line: edit.line_clone()
|
||||
|
||||
# Insert new line
|
||||
new line above: edit.line_insert_up()
|
||||
new line below | slap: edit.line_insert_down()
|
||||
|
||||
# Insert padding with optional symbols
|
||||
padding: user.insert_between(" ", " ")
|
||||
(pad | padding) <user.symbol_key>+:
|
||||
insert(" ")
|
||||
user.insert_many(symbol_key_list)
|
||||
insert(" ")
|
||||
|
||||
# Undo/redo
|
||||
undo that: edit.undo()
|
||||
redo that: edit.redo()
|
||||
|
||||
# Save
|
||||
file save: edit.save()
|
||||
file save all: edit.save_all()
|
||||
|
||||
[go] line mid: user.line_middle()
|
||||
@@ -0,0 +1,191 @@
|
||||
from talon import Module, actions, settings
|
||||
|
||||
from .edit_command_actions import EditAction, EditSimpleAction, run_action_callback
|
||||
from .edit_command_modifiers import EditModifier, run_modifier_callback
|
||||
|
||||
mod = Module()
|
||||
|
||||
# providing some settings for customizing the word and line selection delay
|
||||
# talon can execute selections must faster than a human
|
||||
# resulting in unexpected or inconsistent results in applications such as visual studio code
|
||||
mod.setting(
|
||||
"edit_command_word_selection_delay",
|
||||
type=int,
|
||||
default=75,
|
||||
desc="Sleep required between word selections",
|
||||
)
|
||||
|
||||
mod.setting(
|
||||
"edit_command_line_selection_delay",
|
||||
type=int,
|
||||
default=75,
|
||||
desc="Sleep required between line selections",
|
||||
)
|
||||
|
||||
|
||||
def before_line_up():
|
||||
actions.edit.up()
|
||||
actions.edit.line_start()
|
||||
|
||||
|
||||
def after_line_up():
|
||||
actions.edit.up()
|
||||
actions.edit.line_end()
|
||||
|
||||
|
||||
def before_line_down():
|
||||
actions.edit.down()
|
||||
actions.edit.line_start()
|
||||
|
||||
|
||||
def after_line_down():
|
||||
actions.edit.down()
|
||||
actions.edit.line_end()
|
||||
|
||||
|
||||
def select_lines(action, direction, count):
|
||||
if direction == "lineUp":
|
||||
selection_callback = actions.edit.extend_line_up
|
||||
extend_line_callback = actions.edit.extend_line_start
|
||||
else:
|
||||
selection_callback = actions.edit.extend_line_down
|
||||
extend_line_callback = actions.edit.extend_line_end
|
||||
|
||||
selection_delay = f"{settings.get('user.edit_command_line_selection_delay')}ms"
|
||||
|
||||
for i in range(1, count + 1):
|
||||
selection_callback()
|
||||
actions.sleep(selection_delay)
|
||||
|
||||
# ensure we take the start/end of the line too!
|
||||
extend_line_callback()
|
||||
actions.sleep(selection_delay)
|
||||
run_action_callback(action)
|
||||
|
||||
|
||||
def select_words(action, direction, count):
|
||||
if direction == "wordLeft":
|
||||
selection_callback = actions.edit.extend_word_left
|
||||
else:
|
||||
selection_callback = actions.edit.extend_word_right
|
||||
|
||||
selection_delay = f"{settings.get('user.edit_command_word_selection_delay')}ms"
|
||||
for i in range(1, count + 1):
|
||||
selection_callback()
|
||||
actions.sleep(selection_delay)
|
||||
|
||||
run_action_callback(action)
|
||||
|
||||
|
||||
def word_movement_handler(action, direction, count):
|
||||
if direction == "wordLeft":
|
||||
movement_callback = actions.edit.word_left
|
||||
else:
|
||||
movement_callback = actions.edit.word_right
|
||||
|
||||
selection_delay = f"{settings.get('user.edit_command_word_selection_delay')}ms"
|
||||
for i in range(1, count + 1):
|
||||
movement_callback()
|
||||
actions.sleep(selection_delay)
|
||||
|
||||
|
||||
# in some cases, it is necessary to have some custom handling for timing reasons
|
||||
custom_callbacks = {
|
||||
("goAfter", "wordLeft"): word_movement_handler,
|
||||
("goAfter", "wordRight"): word_movement_handler,
|
||||
("goBefore", "wordLeft"): word_movement_handler,
|
||||
("goBefore", "wordRight"): word_movement_handler,
|
||||
# delete
|
||||
("delete", "word"): select_words,
|
||||
("delete", "wordLeft"): select_words,
|
||||
("delete", "wordRight"): select_words,
|
||||
("delete", "lineUp"): select_lines,
|
||||
("delete", "lineDown"): select_lines,
|
||||
# cut
|
||||
("cutToClipboard", "word"): select_words,
|
||||
("cutToClipboard", "wordLeft"): select_words,
|
||||
("cutToClipboard", "wordRight"): select_words,
|
||||
("cutToClipboard", "lineUp"): select_lines,
|
||||
("cutToClipboard", "lineDown"): select_lines,
|
||||
# copy
|
||||
("copyToClipboard", "word"): select_words,
|
||||
("copyToClipboard", "wordLeft"): select_words,
|
||||
("copyToClipboard", "wordRight"): select_words,
|
||||
("copyToClipboard", "lineUp"): select_lines,
|
||||
("copyToClipboard", "lineDown"): select_lines,
|
||||
# select
|
||||
("select", "lineUp"): select_lines,
|
||||
("select", "lineDown"): select_lines,
|
||||
}
|
||||
|
||||
# In other cases there already is a "compound" talon action for a given action and modifier
|
||||
compound_actions = {
|
||||
# select
|
||||
("select", "wordLeft"): actions.edit.extend_word_left,
|
||||
("select", "wordRight"): actions.edit.extend_word_right,
|
||||
("select", "left"): actions.edit.extend_left,
|
||||
("select", "right"): actions.edit.extend_right,
|
||||
("select", "word"): actions.edit.extend_word_right,
|
||||
# Go before
|
||||
("goBefore", "line"): actions.edit.line_start,
|
||||
("goBefore", "lineUp"): before_line_up,
|
||||
("goBefore", "lineDown"): before_line_down,
|
||||
("goBefore", "paragraph"): actions.edit.paragraph_start,
|
||||
("goBefore", "document"): actions.edit.file_start,
|
||||
("goBefore", "fileStart"): actions.edit.file_start,
|
||||
("goBefore", "selection"): actions.edit.left,
|
||||
("goBefore", "wordLeft"): actions.edit.word_left,
|
||||
("goBefore", "word"): actions.edit.word_left,
|
||||
# Go after
|
||||
("goAfter", "line"): actions.edit.line_end,
|
||||
("goAfter", "lineUp"): after_line_up,
|
||||
("goAfter", "lineDown"): after_line_down,
|
||||
("goAfter", "paragraph"): actions.edit.paragraph_end,
|
||||
("goAfter", "document"): actions.edit.file_end,
|
||||
("goAfter", "fileEnd"): actions.edit.file_end,
|
||||
("goAfter", "selection"): actions.edit.right,
|
||||
("goAfter", "wordRight"): actions.edit.word_right,
|
||||
("goAfter", "wordLeft"): actions.edit.word_left,
|
||||
("goAfter", "word"): actions.edit.word_right,
|
||||
# Delete
|
||||
("delete", "left"): actions.edit.delete,
|
||||
("delete", "right"): actions.user.delete_right,
|
||||
("delete", "line"): actions.edit.delete_line,
|
||||
("delete", "paragraph"): actions.edit.delete_paragraph,
|
||||
# ("delete", "document"): actions.edit.delete_all, # Beta only
|
||||
("delete", "document"): actions.user.delete_all,
|
||||
("delete", "selection"): actions.edit.delete,
|
||||
# Cut to clipboard
|
||||
("cutToClipboard", "line"): actions.user.cut_line,
|
||||
("cutToClipboard", "selection"): actions.edit.cut,
|
||||
# copy
|
||||
("copyToClipboard", "selection"): actions.edit.copy,
|
||||
}
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def edit_command(action: EditAction | str, modifier: EditModifier | str):
|
||||
"""Perform edit command with associated modifier.
|
||||
Action and modifier can be dataclasses (formed from utterances via
|
||||
capture) or str, for use in scripts. Strings should match the action or
|
||||
modifier types declared here or in edit_command_modifiers.py or
|
||||
edit_command_actions.py"""
|
||||
if isinstance(modifier, str):
|
||||
modifier = EditModifier(modifier)
|
||||
if isinstance(action, str):
|
||||
action = EditSimpleAction(action)
|
||||
key = (action.type, modifier.type)
|
||||
count = modifier.count
|
||||
|
||||
if key in custom_callbacks:
|
||||
custom_callbacks[key](action, modifier.type, count)
|
||||
return
|
||||
|
||||
elif key in compound_actions:
|
||||
for i in range(1, count + 1):
|
||||
compound_actions[key]()
|
||||
return
|
||||
|
||||
run_modifier_callback(modifier)
|
||||
run_action_callback(action)
|
||||
@@ -0,0 +1,113 @@
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, Union
|
||||
|
||||
from talon import Module, actions
|
||||
|
||||
|
||||
@dataclass
|
||||
class EditSimpleAction:
|
||||
""" "Simple" actions are actions that don't require any arguments, only a type (select, copy, delete, etc.)"""
|
||||
|
||||
type: str
|
||||
|
||||
def __str__(self):
|
||||
return self.type
|
||||
|
||||
|
||||
@dataclass
|
||||
class EditInsertAction:
|
||||
type = "insert"
|
||||
text: str
|
||||
|
||||
def __str__(self):
|
||||
return self.type
|
||||
|
||||
|
||||
@dataclass
|
||||
class EditWrapAction:
|
||||
type = "wrapWithDelimiterPair"
|
||||
pair: list[str]
|
||||
|
||||
def __str__(self):
|
||||
return self.type
|
||||
|
||||
|
||||
@dataclass
|
||||
class EditFormatAction:
|
||||
type = "applyFormatter"
|
||||
formatters: str
|
||||
|
||||
def __str__(self):
|
||||
return self.type
|
||||
|
||||
|
||||
EditAction = Union[
|
||||
EditSimpleAction,
|
||||
EditInsertAction,
|
||||
EditWrapAction,
|
||||
EditFormatAction,
|
||||
]
|
||||
|
||||
mod = Module()
|
||||
mod.list("edit_action", desc="Actions for the edit command")
|
||||
|
||||
|
||||
@mod.capture(rule="{user.edit_action}")
|
||||
def edit_simple_action(m) -> EditSimpleAction:
|
||||
return EditSimpleAction(m.edit_action)
|
||||
|
||||
|
||||
@mod.capture(rule="<user.delimiter_pair> wrap")
|
||||
def edit_wrap_action(m) -> EditWrapAction:
|
||||
return EditWrapAction(m.delimiter_pair)
|
||||
|
||||
|
||||
@mod.capture(rule="<user.formatters> format")
|
||||
def edit_format_action(m) -> EditFormatAction:
|
||||
return EditFormatAction(m.formatters)
|
||||
|
||||
|
||||
@mod.capture(
|
||||
rule="<user.edit_simple_action> | <user.edit_wrap_action> | <user.edit_format_action>"
|
||||
)
|
||||
def edit_action(m) -> EditAction:
|
||||
return m[0]
|
||||
|
||||
|
||||
simple_action_callbacks: dict[str, Callable] = {
|
||||
"select": actions.skip,
|
||||
"goBefore": actions.edit.left,
|
||||
"goAfter": actions.edit.right,
|
||||
"copyToClipboard": actions.edit.copy,
|
||||
"cutToClipboard": actions.edit.cut,
|
||||
"pasteFromClipboard": actions.edit.paste,
|
||||
"insertLineAbove": actions.edit.line_insert_up,
|
||||
"insertLineBelow": actions.edit.line_insert_down,
|
||||
"insertCopyAfter": actions.edit.selection_clone,
|
||||
"delete": actions.edit.delete,
|
||||
}
|
||||
|
||||
|
||||
def run_action_callback(action: EditAction):
|
||||
action_type = action.type
|
||||
|
||||
if action_type in simple_action_callbacks:
|
||||
callback = simple_action_callbacks[action_type]
|
||||
callback()
|
||||
return
|
||||
|
||||
match action_type:
|
||||
case "insert":
|
||||
assert isinstance(action, EditInsertAction)
|
||||
actions.insert(action.text)
|
||||
|
||||
case "wrapWithDelimiterPair":
|
||||
assert isinstance(action, EditWrapAction)
|
||||
return lambda: actions.user.delimiter_pair_wrap_selection(action.pair)
|
||||
|
||||
case "applyFormatter":
|
||||
assert isinstance(action, EditFormatAction)
|
||||
actions.user.formatters_reformat_selection(action.formatters)
|
||||
|
||||
case _:
|
||||
raise ValueError(f"Unknown edit action: {action_type}")
|
||||
@@ -0,0 +1,13 @@
|
||||
list: user.edit_action
|
||||
-
|
||||
|
||||
select: select
|
||||
go before: goBefore
|
||||
go after: goAfter
|
||||
|
||||
copy: copyToClipboard
|
||||
cut: cutToClipboard
|
||||
paste: pasteFromClipboard
|
||||
paste to: pasteFromClipboard
|
||||
|
||||
clear: delete
|
||||
@@ -0,0 +1,75 @@
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable
|
||||
|
||||
from talon import Module, actions
|
||||
|
||||
mod = Module()
|
||||
mod.list("edit_modifier", desc="Modifiers for the edit command")
|
||||
mod.list(
|
||||
"edit_modifier_repeatable",
|
||||
desc="Modifiers for the edit command that are repeatable",
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class EditModifier:
|
||||
type: str
|
||||
count: int = 1
|
||||
|
||||
|
||||
@dataclass
|
||||
class EditModifierCallback:
|
||||
modifier: str
|
||||
callback: Callable
|
||||
|
||||
|
||||
@mod.capture(
|
||||
rule="({user.edit_modifier}) | ([<number_small>] {user.edit_modifier_repeatable})"
|
||||
)
|
||||
def edit_modifier(m) -> EditModifier:
|
||||
count = 1
|
||||
with suppress(AttributeError):
|
||||
count = m.number_small
|
||||
|
||||
with suppress(AttributeError):
|
||||
type = m.edit_modifier
|
||||
|
||||
with suppress(AttributeError):
|
||||
type = m.edit_modifier_repeatable
|
||||
|
||||
return EditModifier(type, count=count)
|
||||
|
||||
|
||||
modifiers = [
|
||||
EditModifierCallback("document", actions.edit.select_all),
|
||||
EditModifierCallback("paragraph", actions.edit.select_paragraph),
|
||||
EditModifierCallback("word", actions.edit.extend_word_right),
|
||||
EditModifierCallback("wordLeft", actions.edit.extend_word_left),
|
||||
EditModifierCallback("wordRight", actions.edit.extend_word_right),
|
||||
EditModifierCallback("left", actions.edit.extend_left),
|
||||
EditModifierCallback("right", actions.edit.extend_right),
|
||||
EditModifierCallback("lineUp", actions.edit.extend_line_up),
|
||||
EditModifierCallback("lineDown", actions.edit.extend_line_down),
|
||||
EditModifierCallback("line", actions.edit.select_line),
|
||||
EditModifierCallback("lineEnd", actions.edit.extend_line_end),
|
||||
EditModifierCallback("lineStart", actions.edit.extend_line_start),
|
||||
EditModifierCallback("fileStart", actions.edit.extend_file_start),
|
||||
EditModifierCallback("fileEnd", actions.edit.extend_file_end),
|
||||
EditModifierCallback("selection", actions.skip),
|
||||
]
|
||||
|
||||
modifier_dictionary: dict[str, EditModifierCallback] = {
|
||||
item.modifier: item for item in modifiers
|
||||
}
|
||||
|
||||
|
||||
def run_modifier_callback(modifier: EditModifier):
|
||||
modifier_type = modifier.type
|
||||
if modifier_type not in modifier_dictionary:
|
||||
raise ValueError(f"Unknown edit modifier: {modifier_type}")
|
||||
|
||||
count = modifier.count
|
||||
modifier = modifier_dictionary[modifier_type]
|
||||
for i in range(1, count + 1):
|
||||
modifier.callback()
|
||||
@@ -0,0 +1,13 @@
|
||||
list: user.edit_modifier
|
||||
-
|
||||
all: document
|
||||
paragraph: paragraph
|
||||
line: line
|
||||
line start: lineStart
|
||||
way left: lineStart
|
||||
line end: lineEnd
|
||||
way right: lineEnd
|
||||
file start: fileStart
|
||||
way up: fileStart
|
||||
file end: fileEnd
|
||||
way down: fileEnd
|
||||
@@ -0,0 +1,9 @@
|
||||
list: user.edit_modifier_repeatable
|
||||
-
|
||||
word: word
|
||||
word left: wordLeft
|
||||
word right: wordRight
|
||||
up: lineUp
|
||||
down: lineDown
|
||||
left: left
|
||||
right: right
|
||||
@@ -0,0 +1,194 @@
|
||||
# defines the default edit actions for linux
|
||||
|
||||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
os: linux
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def copy():
|
||||
actions.key("ctrl-c")
|
||||
|
||||
def cut():
|
||||
actions.key("ctrl-x")
|
||||
|
||||
def delete():
|
||||
actions.key("backspace")
|
||||
|
||||
def delete_line():
|
||||
actions.edit.select_line()
|
||||
actions.edit.delete()
|
||||
# action(edit.delete_paragraph):
|
||||
# action(edit.delete_sentence):
|
||||
|
||||
def delete_word():
|
||||
actions.edit.select_word()
|
||||
actions.edit.delete()
|
||||
|
||||
def down():
|
||||
actions.key("down")
|
||||
# action(edit.extend_again):
|
||||
# action(edit.extend_column):
|
||||
|
||||
def extend_down():
|
||||
actions.key("shift-down")
|
||||
|
||||
def extend_file_end():
|
||||
actions.key("shift-ctrl-end")
|
||||
|
||||
def extend_file_start():
|
||||
actions.key("shift-ctrl-home")
|
||||
|
||||
def extend_left():
|
||||
actions.key("shift-left")
|
||||
# action(edit.extend_line):
|
||||
|
||||
def extend_line_down():
|
||||
actions.key("shift-down")
|
||||
|
||||
def extend_line_end():
|
||||
actions.key("shift-end")
|
||||
|
||||
def extend_line_start():
|
||||
actions.key("shift-home")
|
||||
|
||||
def extend_line_up():
|
||||
actions.key("shift-up")
|
||||
|
||||
def extend_page_down():
|
||||
actions.key("shift-pagedown")
|
||||
|
||||
def extend_page_up():
|
||||
actions.key("shift-pageup")
|
||||
# action(edit.extend_paragraph_end):
|
||||
# action(edit.extend_paragraph_next()):
|
||||
# action(edit.extend_paragraph_previous()):
|
||||
# action(edit.extend_paragraph_start()):
|
||||
|
||||
def extend_right():
|
||||
actions.key("shift-right")
|
||||
# action(edit.extend_sentence_end):
|
||||
# action(edit.extend_sentence_next):
|
||||
# action(edit.extend_sentence_previous):
|
||||
# action(edit.extend_sentence_start):
|
||||
|
||||
def extend_up():
|
||||
actions.key("shift-up")
|
||||
|
||||
def extend_word_left():
|
||||
actions.key("ctrl-shift-left")
|
||||
|
||||
def extend_word_right():
|
||||
actions.key("ctrl-shift-right")
|
||||
|
||||
def file_end():
|
||||
actions.key("ctrl-end")
|
||||
|
||||
def file_start():
|
||||
actions.key("ctrl-home")
|
||||
|
||||
def find(text: str = None):
|
||||
actions.key("ctrl-f")
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
def find_previous():
|
||||
actions.key("shift-f3")
|
||||
|
||||
def find_next():
|
||||
actions.key("f3")
|
||||
|
||||
def indent_less():
|
||||
actions.key("home delete")
|
||||
|
||||
def indent_more():
|
||||
actions.key("home tab")
|
||||
# action(edit.jump_column(n: int)
|
||||
# action(edit.jump_line(n: int)
|
||||
|
||||
def left():
|
||||
actions.key("left")
|
||||
|
||||
def line_down():
|
||||
actions.key("down home")
|
||||
|
||||
def line_end():
|
||||
actions.key("end")
|
||||
|
||||
def line_insert_up():
|
||||
actions.key("home enter up")
|
||||
|
||||
def line_start():
|
||||
actions.key("home")
|
||||
|
||||
def line_up():
|
||||
actions.key("up home")
|
||||
# action(edit.move_again):
|
||||
|
||||
def page_down():
|
||||
actions.key("pagedown")
|
||||
|
||||
def page_up():
|
||||
actions.key("pageup")
|
||||
# action(edit.paragraph_end):
|
||||
# action(edit.paragraph_next):
|
||||
# action(edit.paragraph_previous):
|
||||
# action(edit.paragraph_start):
|
||||
|
||||
def paste():
|
||||
actions.key("ctrl-v")
|
||||
# action(paste_match_style):
|
||||
|
||||
def print():
|
||||
actions.key("ctrl-p")
|
||||
|
||||
def redo():
|
||||
actions.key("ctrl-y")
|
||||
|
||||
def right():
|
||||
actions.key("right")
|
||||
|
||||
def save():
|
||||
actions.key("ctrl-s")
|
||||
|
||||
def save_all():
|
||||
actions.key("ctrl-shift-s")
|
||||
|
||||
def select_all():
|
||||
actions.key("ctrl-a")
|
||||
|
||||
def select_line(n: int = None):
|
||||
if n is not None:
|
||||
actions.edit.jump_line(n)
|
||||
actions.key("end shift-home")
|
||||
# action(edit.select_lines(a: int, b: int)):
|
||||
|
||||
def select_none():
|
||||
actions.key("right")
|
||||
# action(edit.select_paragraph):
|
||||
# action(edit.select_sentence):
|
||||
|
||||
def undo():
|
||||
actions.key("ctrl-z")
|
||||
|
||||
def up():
|
||||
actions.key("up")
|
||||
|
||||
def word_left():
|
||||
actions.key("ctrl-left")
|
||||
|
||||
def word_right():
|
||||
actions.key("ctrl-right")
|
||||
|
||||
def zoom_in():
|
||||
actions.key("ctrl-+")
|
||||
|
||||
def zoom_out():
|
||||
actions.key("ctrl--")
|
||||
|
||||
def zoom_reset():
|
||||
actions.key("ctrl-0")
|
||||
@@ -0,0 +1,194 @@
|
||||
from talon import Context, actions, clip
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
os: mac
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def copy():
|
||||
actions.key("cmd-c")
|
||||
|
||||
def cut():
|
||||
actions.key("cmd-x")
|
||||
|
||||
def delete():
|
||||
actions.key("backspace")
|
||||
|
||||
def delete_line():
|
||||
actions.edit.select_line()
|
||||
actions.edit.delete()
|
||||
# action(edit.delete_paragraph):
|
||||
# action(edit.delete_sentence):
|
||||
|
||||
def delete_word():
|
||||
actions.edit.select_word()
|
||||
actions.edit.delete()
|
||||
|
||||
def down():
|
||||
actions.key("down")
|
||||
# action(edit.extend_again):
|
||||
# action(edit.extend_column):
|
||||
|
||||
def extend_down():
|
||||
actions.key("shift-down")
|
||||
|
||||
def extend_file_end():
|
||||
actions.key("cmd-shift-down")
|
||||
|
||||
def extend_file_start():
|
||||
actions.key("cmd-shift-up")
|
||||
|
||||
def extend_left():
|
||||
actions.key("shift-left")
|
||||
# action(edit.extend_line):
|
||||
|
||||
def extend_line_down():
|
||||
actions.key("shift-down")
|
||||
|
||||
def extend_line_end():
|
||||
actions.key("cmd-shift-right")
|
||||
|
||||
def extend_line_start():
|
||||
actions.key("cmd-shift-left")
|
||||
|
||||
def extend_line_up():
|
||||
actions.key("shift-up")
|
||||
|
||||
def extend_page_down():
|
||||
actions.key("cmd-shift-pagedown")
|
||||
|
||||
def extend_page_up():
|
||||
actions.key("cmd-shift-pageup")
|
||||
# action(edit.extend_paragraph_end):
|
||||
# action(edit.extend_paragraph_next()):
|
||||
# action(edit.extend_paragraph_previous()):
|
||||
# action(edit.extend_paragraph_start()):
|
||||
|
||||
def extend_right():
|
||||
actions.key("shift-right")
|
||||
# action(edit.extend_sentence_end):
|
||||
# action(edit.extend_sentence_next):
|
||||
# action(edit.extend_sentence_previous):
|
||||
# action(edit.extend_sentence_start):
|
||||
|
||||
def extend_up():
|
||||
actions.key("shift-up")
|
||||
|
||||
def extend_word_left():
|
||||
actions.key("shift-alt-left")
|
||||
|
||||
def extend_word_right():
|
||||
actions.key("shift-alt-right")
|
||||
|
||||
def file_end():
|
||||
actions.key("cmd-down")
|
||||
|
||||
def file_start():
|
||||
actions.key("cmd-up")
|
||||
|
||||
def find(text: str = None):
|
||||
if text is not None:
|
||||
clip.set_text(text, mode="find")
|
||||
actions.key("cmd-f")
|
||||
|
||||
def find_next():
|
||||
actions.key("cmd-g")
|
||||
|
||||
def find_previous():
|
||||
actions.key("cmd-shift-g")
|
||||
|
||||
def indent_less():
|
||||
actions.key("cmd-left delete")
|
||||
|
||||
def indent_more():
|
||||
actions.key("cmd-left tab")
|
||||
# action(edit.jump_column(n: int)
|
||||
# action(edit.jump_line(n: int)
|
||||
|
||||
def left():
|
||||
actions.key("left")
|
||||
|
||||
def line_down():
|
||||
actions.key("down home")
|
||||
|
||||
def line_end():
|
||||
actions.key("cmd-right")
|
||||
|
||||
def line_insert_up():
|
||||
actions.key("cmd-left enter up")
|
||||
|
||||
def line_start():
|
||||
actions.key("cmd-left")
|
||||
|
||||
def line_up():
|
||||
actions.key("up cmd-left")
|
||||
# action(edit.move_again):
|
||||
|
||||
def page_down():
|
||||
actions.key("pagedown")
|
||||
|
||||
def page_up():
|
||||
actions.key("pageup")
|
||||
# action(edit.paragraph_end):
|
||||
# action(edit.paragraph_next):
|
||||
# action(edit.paragraph_previous):
|
||||
# action(edit.paragraph_start):
|
||||
|
||||
def paste():
|
||||
actions.key("cmd-v")
|
||||
|
||||
def paste_match_style():
|
||||
actions.key("cmd-alt-shift-v")
|
||||
|
||||
def print():
|
||||
actions.key("cmd-p")
|
||||
|
||||
def redo():
|
||||
actions.key("cmd-shift-z")
|
||||
|
||||
def right():
|
||||
actions.key("right")
|
||||
|
||||
def save():
|
||||
actions.key("cmd-s")
|
||||
|
||||
def save_all():
|
||||
actions.key("cmd-alt-s")
|
||||
|
||||
def select_all():
|
||||
actions.key("cmd-a")
|
||||
|
||||
def select_line(n: int = None):
|
||||
if n is not None:
|
||||
actions.edit.jump_line(n)
|
||||
actions.key("cmd-right cmd-shift-left")
|
||||
# action(edit.select_lines(a: int, b: int)):
|
||||
|
||||
def select_none():
|
||||
actions.key("right")
|
||||
# action(edit.select_paragraph):
|
||||
# action(edit.select_sentence):
|
||||
|
||||
def undo():
|
||||
actions.key("cmd-z")
|
||||
|
||||
def up():
|
||||
actions.key("up")
|
||||
|
||||
def word_left():
|
||||
actions.key("alt-left")
|
||||
|
||||
def word_right():
|
||||
actions.key("alt-right")
|
||||
|
||||
def zoom_in():
|
||||
actions.key("cmd-=")
|
||||
|
||||
def zoom_out():
|
||||
actions.key("cmd--")
|
||||
|
||||
def zoom_reset():
|
||||
actions.key("cmd-0")
|
||||
@@ -0,0 +1,65 @@
|
||||
from contextlib import suppress
|
||||
from dataclasses import dataclass
|
||||
from typing import Callable, Literal
|
||||
|
||||
from talon import Module, actions, settings
|
||||
|
||||
|
||||
@dataclass
|
||||
class NavigationStep:
|
||||
modifier: Literal[
|
||||
"wordLeft", "wordRight", "word", "left", "right", "lineUp", "lineDown"
|
||||
]
|
||||
count: int
|
||||
|
||||
|
||||
mod = Module()
|
||||
|
||||
|
||||
@mod.capture(rule="[<number_small>] {user.edit_modifier_repeatable}")
|
||||
def navigation_step(m) -> NavigationStep:
|
||||
count = 1
|
||||
modifier = m.edit_modifier_repeatable
|
||||
|
||||
with suppress(AttributeError):
|
||||
count = m.number_small
|
||||
|
||||
return NavigationStep(
|
||||
modifier=modifier,
|
||||
count=count,
|
||||
)
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def perform_navigation_steps(steps: list[NavigationStep]):
|
||||
"""Navigate by a series of steps"""
|
||||
for step in steps:
|
||||
match step.modifier:
|
||||
case "wordLeft":
|
||||
repeat_action(actions.edit.word_left, step.count, True)
|
||||
case "wordRight":
|
||||
repeat_action(actions.edit.word_right, step.count, True)
|
||||
case "word":
|
||||
repeat_action(actions.edit.word_right, step.count, True)
|
||||
case "left":
|
||||
repeat_action(actions.edit.left, step.count)
|
||||
case "right":
|
||||
repeat_action(actions.edit.right, step.count)
|
||||
case "lineUp":
|
||||
repeat_action(actions.edit.up, step.count)
|
||||
case "lineDown":
|
||||
repeat_action(actions.edit.down, step.count)
|
||||
|
||||
|
||||
def repeat_action(action: Callable, count: int, delay: bool = False):
|
||||
delay_string = None
|
||||
|
||||
if delay:
|
||||
delay_string = f"{settings.get('user.edit_command_word_selection_delay')}ms"
|
||||
|
||||
for _ in range(count):
|
||||
action()
|
||||
|
||||
if delay_string:
|
||||
actions.sleep(delay_string)
|
||||
@@ -0,0 +1,115 @@
|
||||
from talon import Context, Module, actions
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def paragraph_start():
|
||||
if extend_paragraph_start_with_success():
|
||||
actions.edit.left()
|
||||
|
||||
def paragraph_end():
|
||||
if extend_paragraph_end_with_success():
|
||||
actions.edit.right()
|
||||
|
||||
def select_paragraph():
|
||||
if is_line_empty():
|
||||
return
|
||||
# Search for start of paragraph
|
||||
actions.edit.extend_paragraph_start()
|
||||
actions.edit.left()
|
||||
# Extend to end of paragraph
|
||||
actions.edit.extend_paragraph_end()
|
||||
|
||||
def extend_paragraph_start():
|
||||
# The reason for the wrapper function is a difference in function signature.
|
||||
# The Talon action has no return value and the below function returns a boolean with success state.
|
||||
extend_paragraph_start_with_success()
|
||||
|
||||
def extend_paragraph_end():
|
||||
extend_paragraph_end_with_success()
|
||||
|
||||
def delete_paragraph():
|
||||
actions.edit.select_paragraph()
|
||||
# Remove selection
|
||||
actions.edit.delete()
|
||||
# Remove the empty line containing the cursor
|
||||
actions.edit.delete()
|
||||
# Remove leading or trailing empty line
|
||||
actions.edit.delete_line()
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def cut_paragraph():
|
||||
"""Cut paragraph under the cursor"""
|
||||
actions.edit.select_paragraph()
|
||||
actions.edit.cut()
|
||||
|
||||
def copy_paragraph():
|
||||
"""Copy paragraph under the cursor"""
|
||||
actions.edit.select_paragraph()
|
||||
actions.edit.copy()
|
||||
|
||||
def paste_paragraph():
|
||||
"""Paste to paragraph under the cursor"""
|
||||
actions.edit.select_paragraph()
|
||||
actions.edit.paste()
|
||||
|
||||
|
||||
def is_line_empty() -> bool:
|
||||
"""Check if the current line is empty. Return True if empty."""
|
||||
actions.edit.extend_line_start()
|
||||
text = actions.edit.selected_text().strip()
|
||||
if text:
|
||||
actions.edit.right()
|
||||
return False
|
||||
actions.edit.extend_line_end()
|
||||
text = actions.edit.selected_text().strip()
|
||||
if text:
|
||||
actions.edit.left()
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def extend_paragraph_start_with_success() -> bool:
|
||||
"""Extend selection to the start of the paragraph. Return True if successful."""
|
||||
actions.edit.extend_line_start()
|
||||
text = actions.edit.selected_text()
|
||||
length = len(text)
|
||||
while True:
|
||||
actions.edit.extend_up()
|
||||
actions.edit.extend_line_start()
|
||||
text = actions.edit.selected_text()
|
||||
new_length = len(text)
|
||||
if new_length == length:
|
||||
break
|
||||
line = text[: new_length - length].strip()
|
||||
if not line:
|
||||
actions.edit.extend_down()
|
||||
break
|
||||
length = new_length
|
||||
return text.strip() != ""
|
||||
|
||||
|
||||
def extend_paragraph_end_with_success() -> bool:
|
||||
"""Extend selection to the end of the paragraph. Return True if successful."""
|
||||
actions.edit.extend_line_end()
|
||||
text = actions.edit.selected_text()
|
||||
length = len(text)
|
||||
while True:
|
||||
actions.edit.extend_down()
|
||||
actions.edit.extend_line_end()
|
||||
text = actions.edit.selected_text()
|
||||
new_length = len(text)
|
||||
if new_length == length:
|
||||
break
|
||||
line = text[length:].strip()
|
||||
if not line:
|
||||
actions.edit.extend_line_start()
|
||||
actions.edit.extend_left()
|
||||
break
|
||||
length = new_length
|
||||
return text.strip() != ""
|
||||
@@ -0,0 +1,194 @@
|
||||
# defines the default edit actions for windows
|
||||
|
||||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
os: windows
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def copy():
|
||||
actions.key("ctrl-c")
|
||||
|
||||
def cut():
|
||||
actions.key("ctrl-x")
|
||||
|
||||
def delete():
|
||||
actions.key("backspace")
|
||||
|
||||
def delete_line():
|
||||
actions.edit.select_line()
|
||||
actions.edit.delete()
|
||||
# action(edit.delete_paragraph):
|
||||
# action(edit.delete_sentence):
|
||||
|
||||
def delete_word():
|
||||
actions.edit.select_word()
|
||||
actions.edit.delete()
|
||||
|
||||
def down():
|
||||
actions.key("down")
|
||||
# action(edit.extend_again):
|
||||
# action(edit.extend_column):
|
||||
|
||||
def extend_down():
|
||||
actions.key("shift-down")
|
||||
|
||||
def extend_file_end():
|
||||
actions.key("shift-ctrl-end")
|
||||
|
||||
def extend_file_start():
|
||||
actions.key("shift-ctrl-home")
|
||||
|
||||
def extend_left():
|
||||
actions.key("shift-left")
|
||||
# action(edit.extend_line):
|
||||
|
||||
def extend_line_down():
|
||||
actions.key("shift-down")
|
||||
|
||||
def extend_line_end():
|
||||
actions.key("shift-end")
|
||||
|
||||
def extend_line_start():
|
||||
actions.key("shift-home")
|
||||
|
||||
def extend_line_up():
|
||||
actions.key("shift-up")
|
||||
|
||||
def extend_page_down():
|
||||
actions.key("shift-pagedown")
|
||||
|
||||
def extend_page_up():
|
||||
actions.key("shift-pageup")
|
||||
# action(edit.extend_paragraph_end):
|
||||
# action(edit.extend_paragraph_next()):
|
||||
# action(edit.extend_paragraph_previous()):
|
||||
# action(edit.extend_paragraph_start()):
|
||||
|
||||
def extend_right():
|
||||
actions.key("shift-right")
|
||||
# action(edit.extend_sentence_end):
|
||||
# action(edit.extend_sentence_next):
|
||||
# action(edit.extend_sentence_previous):
|
||||
# action(edit.extend_sentence_start):
|
||||
|
||||
def extend_up():
|
||||
actions.key("shift-up")
|
||||
|
||||
def extend_word_left():
|
||||
actions.key("ctrl-shift-left")
|
||||
|
||||
def extend_word_right():
|
||||
actions.key("ctrl-shift-right")
|
||||
|
||||
def file_end():
|
||||
actions.key("ctrl-end")
|
||||
|
||||
def file_start():
|
||||
actions.key("ctrl-home")
|
||||
|
||||
def find(text: str = None):
|
||||
actions.key("ctrl-f")
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
def find_previous():
|
||||
actions.key("shift-f3")
|
||||
|
||||
def find_next():
|
||||
actions.key("f3")
|
||||
|
||||
def indent_less():
|
||||
actions.key("home delete")
|
||||
|
||||
def indent_more():
|
||||
actions.key("home tab")
|
||||
# action(edit.jump_column(n: int)
|
||||
# action(edit.jump_line(n: int)
|
||||
|
||||
def left():
|
||||
actions.key("left")
|
||||
|
||||
def line_down():
|
||||
actions.key("down home")
|
||||
|
||||
def line_end():
|
||||
actions.key("end")
|
||||
|
||||
def line_insert_up():
|
||||
actions.key("home enter up")
|
||||
|
||||
def line_start():
|
||||
actions.key("home")
|
||||
|
||||
def line_up():
|
||||
actions.key("up home")
|
||||
# action(edit.move_again):
|
||||
|
||||
def page_down():
|
||||
actions.key("pagedown")
|
||||
|
||||
def page_up():
|
||||
actions.key("pageup")
|
||||
# action(edit.paragraph_end):
|
||||
# action(edit.paragraph_next):
|
||||
# action(edit.paragraph_previous):
|
||||
# action(edit.paragraph_start):
|
||||
|
||||
def paste():
|
||||
actions.key("ctrl-v")
|
||||
# action(paste_match_style):
|
||||
|
||||
def print():
|
||||
actions.key("ctrl-p")
|
||||
|
||||
def redo():
|
||||
actions.key("ctrl-y")
|
||||
|
||||
def right():
|
||||
actions.key("right")
|
||||
|
||||
def save():
|
||||
actions.key("ctrl-s")
|
||||
|
||||
def save_all():
|
||||
actions.key("ctrl-shift-s")
|
||||
|
||||
def select_all():
|
||||
actions.key("ctrl-a")
|
||||
|
||||
def select_line(n: int = None):
|
||||
if n is not None:
|
||||
actions.edit.jump_line(n)
|
||||
actions.key("end shift-home")
|
||||
# action(edit.select_lines(a: int, b: int)):
|
||||
|
||||
def select_none():
|
||||
actions.key("right")
|
||||
# action(edit.select_paragraph):
|
||||
# action(edit.select_sentence):
|
||||
|
||||
def undo():
|
||||
actions.key("ctrl-z")
|
||||
|
||||
def up():
|
||||
actions.key("up")
|
||||
|
||||
def word_left():
|
||||
actions.key("ctrl-left")
|
||||
|
||||
def word_right():
|
||||
actions.key("ctrl-right")
|
||||
|
||||
def zoom_in():
|
||||
actions.key("ctrl-+")
|
||||
|
||||
def zoom_out():
|
||||
actions.key("ctrl--")
|
||||
|
||||
def zoom_reset():
|
||||
actions.key("ctrl-0")
|
||||
@@ -0,0 +1,12 @@
|
||||
from talon import Module, actions
|
||||
|
||||
mod = Module()
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class module_actions:
|
||||
def insert_between(before: str, after: str):
|
||||
"""Insert `before + after`, leaving cursor between `before` and `after`. Not entirely reliable if `after` contains newlines."""
|
||||
actions.insert(f"{before}{after}")
|
||||
for _ in after:
|
||||
actions.edit.left()
|
||||
Reference in New Issue
Block a user