init commit
This commit is contained in:
@@ -0,0 +1,363 @@
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
from talon import Context, Module, actions, settings
|
||||
|
||||
mod = Module()
|
||||
mod.setting(
|
||||
"emacs_meta",
|
||||
type=str,
|
||||
default="esc",
|
||||
desc="""What to use for the meta key in emacs. Defaults to 'esc', since that should work everywhere. Other options are 'alt' and 'cmd'.""",
|
||||
)
|
||||
|
||||
mod.apps.emacs = "app.name: Emacs"
|
||||
mod.apps.emacs = "app.name: emacs"
|
||||
mod.apps.emacs = "app.name: /^GNU Emacs/"
|
||||
mod.apps.emacs = """
|
||||
os: mac
|
||||
app.bundle: org.gnu.Emacs
|
||||
"""
|
||||
mod.apps.emacs = r"""
|
||||
os: windows
|
||||
app.exe: /^emacs\.exe$/i
|
||||
"""
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = "app: emacs"
|
||||
|
||||
|
||||
def meta(keys):
|
||||
m = settings.get("user.emacs_meta")
|
||||
if m == "alt":
|
||||
return " ".join("alt-" + k for k in keys.split())
|
||||
elif m == "cmd":
|
||||
return " ".join("cmd-" + k for k in keys.split())
|
||||
elif m != "esc":
|
||||
logging.error(
|
||||
f"Unrecognized 'emacs_meta' setting: {m!r}. Falling back to 'esc'."
|
||||
)
|
||||
return "esc " + keys
|
||||
|
||||
|
||||
def meta_fixup(k):
|
||||
if k.startswith("meta-"):
|
||||
k = meta(k[len("meta-") :])
|
||||
elif "meta-" in k:
|
||||
raise NotImplementedError("user.emacs_key(): please put meta- first")
|
||||
return k
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def emacs_meta(key: str):
|
||||
"Presses some keys modified by Emacs' meta key."
|
||||
actions.key(meta(key))
|
||||
|
||||
def emacs_key(keys: str):
|
||||
"""
|
||||
Presses some keys, translating 'meta-' prefix to the appropriate keys. For
|
||||
example, if the setting user.emacs_meta = 'esc', user.emacs_key("meta-ctrl-a")
|
||||
becomes key("esc ctrl-a").
|
||||
"""
|
||||
# TODO: handle corner-cases like key(" ") and key("ctrl- "), etc.
|
||||
actions.key(" ".join(meta_fixup(k) for k in keys.split()))
|
||||
|
||||
def emacs_prefix(n: Optional[int] = None):
|
||||
"Inputs a prefix argument."
|
||||
if n is None:
|
||||
# `M-x universal-argument` doesn't have the same effect as pressing the key.
|
||||
prefix_key = actions.user.emacs_command_keybinding("universal-argument")
|
||||
actions.key(prefix_key or "ctrl-u") # default to ctrl-u
|
||||
else:
|
||||
# Applying meta to each key can use fewer keypresses and 'works' in ansi-term
|
||||
# mode.
|
||||
actions.user.emacs_meta(" ".join(str(n)))
|
||||
|
||||
def emacs(command_name: str, prefix: Optional[int] = None):
|
||||
"""
|
||||
Runs the emacs command `command_name`. Defaults to using M-x, but may use
|
||||
a key binding if known or rpc if available. Provides numeric prefix argument
|
||||
`prefix` if specified.
|
||||
"""
|
||||
meta_x = actions.user.emacs_command_keybinding("execute-extended-command")
|
||||
keys = actions.user.emacs_command_keybinding(command_name)
|
||||
short_form = actions.user.emacs_command_short_form(command_name)
|
||||
if prefix is not None:
|
||||
actions.user.emacs_prefix(prefix)
|
||||
if keys is not None:
|
||||
actions.user.emacs_key(keys)
|
||||
else:
|
||||
actions.user.emacs_key(meta_x or "meta-x")
|
||||
actions.insert(short_form or command_name)
|
||||
actions.key("enter")
|
||||
|
||||
def emacs_help(key: str = None):
|
||||
"Runs the emacs help command prefix, optionally followed by some keys."
|
||||
# NB. f1 works in ansi-term mode; C-h doesn't.
|
||||
actions.key("f1")
|
||||
if key is not None:
|
||||
actions.key(key)
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def cut_line():
|
||||
actions.edit.line_start()
|
||||
actions.user.emacs("kill-line", 1)
|
||||
|
||||
def split_window():
|
||||
actions.user.emacs("split-window-below")
|
||||
|
||||
def split_window_vertically():
|
||||
actions.user.emacs("split-window-below")
|
||||
|
||||
def split_window_up():
|
||||
actions.user.emacs("split-window-below")
|
||||
|
||||
def split_window_down():
|
||||
actions.user.emacs("split-window-below")
|
||||
actions.user.emacs("other-window")
|
||||
|
||||
def split_window_horizontally():
|
||||
actions.user.emacs("split-window-right")
|
||||
|
||||
def split_window_left():
|
||||
actions.user.emacs("split-window-right")
|
||||
|
||||
def split_window_right():
|
||||
actions.user.emacs("split-window-right")
|
||||
actions.user.emacs("other-window")
|
||||
|
||||
def split_clear():
|
||||
actions.user.emacs("delete-window")
|
||||
|
||||
def split_clear_all():
|
||||
actions.user.emacs("delete-other-windows")
|
||||
|
||||
def split_reset():
|
||||
actions.user.emacs("balance-windows")
|
||||
|
||||
def split_next():
|
||||
actions.user.emacs("other-window")
|
||||
|
||||
def split_last():
|
||||
actions.user.emacs("other-window", -1)
|
||||
|
||||
def split_flip():
|
||||
# only works reliably if there are only two panes/windows.
|
||||
actions.key("ctrl-x b enter ctrl-x o ctrl-x b enter")
|
||||
actions.user.split_last()
|
||||
actions.key("ctrl-x b enter ctrl-x o")
|
||||
|
||||
def select_range(line_start, line_end):
|
||||
# Assumes transient mark mode.
|
||||
actions.edit.jump_line(line_start)
|
||||
actions.edit.jump_line(line_end + 1)
|
||||
actions.user.emacs("exchange-point-and-mark")
|
||||
|
||||
# # Version that highlights without transient-mark-mode:
|
||||
# def select_range(line_start, line_end):
|
||||
# actions.edit.jump_line(line_end + 1)
|
||||
# actions.key("ctrl-@ ctrl-@")
|
||||
# actions.edit.jump_line(line_start)
|
||||
|
||||
# dictation_peek() probably won't work in a terminal. PRs welcome.
|
||||
def dictation_peek(left, right):
|
||||
# clobber transient selection if it exists
|
||||
actions.key("space backspace")
|
||||
before, after = None, None
|
||||
if left:
|
||||
actions.edit.extend_word_left()
|
||||
before = actions.edit.selected_text()
|
||||
actions.user.emacs("pop-to-mark-command")
|
||||
if right:
|
||||
actions.edit.extend_line_end()
|
||||
after = actions.edit.selected_text()
|
||||
actions.user.emacs("pop-to-mark-command")
|
||||
return (before, after)
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def save():
|
||||
actions.user.emacs("save-buffer")
|
||||
|
||||
def save_all():
|
||||
actions.user.emacs("save-some-buffers")
|
||||
|
||||
def copy():
|
||||
actions.user.emacs("kill-ring-save")
|
||||
|
||||
def cut():
|
||||
actions.user.emacs("kill-region")
|
||||
|
||||
def undo():
|
||||
actions.user.emacs("undo")
|
||||
|
||||
def paste():
|
||||
actions.user.emacs("yank")
|
||||
|
||||
def delete():
|
||||
actions.user.emacs("kill-region")
|
||||
|
||||
def file_start():
|
||||
actions.user.emacs("beginning-of-buffer")
|
||||
|
||||
def file_end():
|
||||
actions.user.emacs("end-of-buffer")
|
||||
|
||||
# works for eg 'select to top', but not if preceded by other selections :(
|
||||
def extend_file_start():
|
||||
actions.user.emacs("beginning-of-buffer")
|
||||
|
||||
def extend_file_end():
|
||||
actions.user.emacs("end-of-buffer")
|
||||
|
||||
def select_none():
|
||||
actions.user.emacs("keyboard-quit")
|
||||
|
||||
def select_all():
|
||||
actions.user.emacs("mark-whole-buffer")
|
||||
# If you don't use transient-mark-mode, maybe do this:
|
||||
# actions.key('ctrl-u ctrl-x ctrl-x')
|
||||
|
||||
def word_left():
|
||||
actions.user.emacs("backward-word")
|
||||
|
||||
def word_right():
|
||||
actions.user.emacs("forward-word")
|
||||
|
||||
def extend_word_left():
|
||||
actions.user.emacs_meta("shift-b")
|
||||
|
||||
def extend_word_right():
|
||||
actions.user.emacs_meta("shift-f")
|
||||
|
||||
def sentence_start():
|
||||
actions.user.emacs("backward-sentence")
|
||||
|
||||
def sentence_end():
|
||||
actions.user.emacs("forward-sentence")
|
||||
|
||||
def extend_sentence_start():
|
||||
actions.user.emacs_meta("shift-a")
|
||||
|
||||
def extend_sentence_end():
|
||||
actions.user.emacs_meta("shift-e")
|
||||
|
||||
def paragraph_start():
|
||||
actions.user.emacs("backward-paragraph")
|
||||
|
||||
def paragraph_end():
|
||||
actions.user.emacs("forward-paragraph")
|
||||
|
||||
def line_start():
|
||||
actions.user.emacs("move-beginning-of-line")
|
||||
|
||||
def line_end():
|
||||
actions.user.emacs("move-end-of-line")
|
||||
|
||||
def extend_line_start():
|
||||
actions.key("shift-ctrl-a")
|
||||
|
||||
def extend_line_end():
|
||||
actions.key("shift-ctrl-e")
|
||||
|
||||
def line_swap_down():
|
||||
actions.key("down ctrl-x ctrl-t up")
|
||||
|
||||
def line_swap_up():
|
||||
actions.key("ctrl-x ctrl-t up:2")
|
||||
|
||||
def delete_line():
|
||||
actions.key("ctrl-a ctrl-k")
|
||||
|
||||
def line_clone():
|
||||
actions.user.emacs_key("ctrl-a meta-1 ctrl-k ctrl-y ctrl-y up meta-m")
|
||||
|
||||
def jump_line(n):
|
||||
actions.user.emacs("goto-line", n)
|
||||
|
||||
def select_line(n: int = None):
|
||||
if n is not None:
|
||||
actions.edit.jump_line(n)
|
||||
else:
|
||||
actions.edit.line_start()
|
||||
actions.edit.extend_line_end()
|
||||
actions.edit.extend_right()
|
||||
# This makes it so the cursor is on the same line, which can make
|
||||
# subsequent commands more convenient.
|
||||
actions.user.emacs("exchange-point-and-mark")
|
||||
|
||||
def indent_more():
|
||||
actions.user.emacs("indent-rigidly", 4)
|
||||
|
||||
def indent_less():
|
||||
actions.user.emacs("indent-rigidly", -4)
|
||||
|
||||
# These all perform text-scale-adjust, which examines the actual key pressed, so can't
|
||||
# be done with actions.user.emacs.
|
||||
def zoom_in():
|
||||
actions.key("ctrl-x ctrl-+")
|
||||
|
||||
def zoom_out():
|
||||
actions.key("ctrl-x ctrl--")
|
||||
|
||||
def zoom_reset():
|
||||
actions.key("ctrl-x ctrl-0")
|
||||
|
||||
# Some modes override ctrl-s/r to do something other than isearch-forward, so we
|
||||
# deliberately don't use actions.user.emacs.
|
||||
def find(text: str = None):
|
||||
actions.key("ctrl-s")
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
def find_next():
|
||||
actions.key("ctrl-s")
|
||||
|
||||
def find_previous():
|
||||
actions.key("ctrl-r")
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
def window_open():
|
||||
actions.user.emacs("make-frame-command")
|
||||
|
||||
def tab_next():
|
||||
actions.user.emacs("tab-next")
|
||||
|
||||
def tab_previous():
|
||||
actions.user.emacs("tab-previous")
|
||||
|
||||
def tab_close():
|
||||
actions.user.emacs("tab-close")
|
||||
|
||||
def tab_reopen():
|
||||
actions.user.emacs("tab-undo")
|
||||
|
||||
def tab_open():
|
||||
actions.user.emacs("tab-new")
|
||||
|
||||
|
||||
@ctx.action_class("code")
|
||||
class CodeActions:
|
||||
def toggle_comment():
|
||||
actions.user.emacs("comment-dwim")
|
||||
|
||||
def language():
|
||||
# Assumes win.filename() gives buffer name.
|
||||
if "*scratch*" == actions.win.filename():
|
||||
return "elisp"
|
||||
return actions.next()
|
||||
|
||||
|
||||
@ctx.action_class("win")
|
||||
class WinActions:
|
||||
# This assumes the title is/contains the filename.
|
||||
# To do this, put this in init.el:
|
||||
# (setq-default frame-title-format '((:eval (buffer-name (window-buffer (minibuffer-selected-window))))))
|
||||
def filename():
|
||||
return actions.win.title()
|
||||
@@ -0,0 +1,367 @@
|
||||
app: emacs
|
||||
-
|
||||
tag(): user.tabs
|
||||
tag(): user.splits
|
||||
tag(): user.line_commands
|
||||
|
||||
# ----- GENERAL ----- #
|
||||
#suplex: key(ctrl-x)
|
||||
cancel: user.emacs("keyboard-quit")
|
||||
exchange: user.emacs("exchange-point-and-mark")
|
||||
execute: user.emacs("execute-extended-command")
|
||||
execute {user.emacs_command}$: user.emacs(emacs_command)
|
||||
execute <user.text>$:
|
||||
user.emacs("execute-extended-command")
|
||||
user.insert_formatted(text, "DASH_SEPARATED")
|
||||
evaluate | (evaluate | eval) (exper | expression): user.emacs("eval-expression")
|
||||
prefix: user.emacs_prefix()
|
||||
prefix <user.number_signed_small>: user.emacs_prefix(number_signed_small)
|
||||
|
||||
abort recursive [edit]: user.emacs("abort-recursive-edit")
|
||||
browse kill ring: user.emacs("browse-kill-ring")
|
||||
fill paragraph: user.emacs("fill-paragraph")
|
||||
insert char: user.emacs("insert-char")
|
||||
occurs: user.emacs("occur")
|
||||
other scroll [down]: user.emacs("scroll-other-window")
|
||||
other scroll up: user.emacs("scroll-other-window-down")
|
||||
package autoremove: user.emacs("package-autoremove")
|
||||
package list | [package] list packages: user.emacs("list-packages")
|
||||
reverse (lines | region): user.emacs("reverse-region")
|
||||
save buffers kill emacs: user.emacs("save-buffers-kill-emacs")
|
||||
save some buffers: user.emacs("save-some-buffers")
|
||||
sort lines: user.emacs("sort-lines")
|
||||
sort words: user.emacs("sort-words")
|
||||
file [loop] continue: user.emacs("fileloop-continue")
|
||||
|
||||
go directory: user.emacs("dired-jump")
|
||||
other go directory: user.emacs("dired-jump-other-window")
|
||||
|
||||
[toggle] debug on error: user.emacs("toggle-debug-on-error")
|
||||
[toggle] debug on quit: user.emacs("toggle-debug-on-quit")
|
||||
[toggle] input method: user.emacs("toggle-input-method")
|
||||
[toggle] truncate lines: user.emacs("toggle-truncate-lines")
|
||||
[toggle] word wrap: user.emacs("toggle-word-wrap")
|
||||
|
||||
manual: user.emacs("man")
|
||||
manual <user.text>:
|
||||
user.emacs("man")
|
||||
user.insert_formatted(text, "DASH_SEPARATED")
|
||||
|
||||
# BUFFER SWITCHING #
|
||||
switch: user.emacs("switch-to-buffer")
|
||||
other switch: user.emacs("switch-to-buffer-other-window")
|
||||
display: user.emacs("display-buffer")
|
||||
|
||||
# SHELL COMMANDS #
|
||||
shell command: user.emacs("shell-command")
|
||||
shell command inserting:
|
||||
user.emacs_prefix()
|
||||
user.emacs("shell-command")
|
||||
shell command on region: user.emacs("shell-command-on-region")
|
||||
shell command on region replacing:
|
||||
user.emacs_prefix()
|
||||
user.emacs("shell-command-on-region")
|
||||
|
||||
# CUSTOMIZE #
|
||||
customize face: user.emacs("customize-face")
|
||||
customize face <user.text>$:
|
||||
user.emacs("customize-face")
|
||||
user.insert_formatted(text, "DASH_SEPARATED")
|
||||
customize group: user.emacs("customize-group")
|
||||
customize variable: user.emacs("customize-variable")
|
||||
(customize | custom) [theme] visit theme: user.emacs("custom-theme-visit-theme")
|
||||
|
||||
# MODE COMMANDS #
|
||||
auto fill mode: user.emacs("auto-fill-mode")
|
||||
dired omit mode: user.emacs("dired-omit-mode")
|
||||
display line numbers mode: user.emacs("display-line-numbers-mode")
|
||||
electric quote local mode: user.emacs("electric-quote-local-mode")
|
||||
emacs lisp mode: user.emacs("emacs-lisp-mode")
|
||||
fundamental mode: user.emacs("fundamental-mode")
|
||||
global display line numbers mode: user.emacs("global-display-line-numbers-mode")
|
||||
global highlight line mode: user.emacs("global-hl-line-mode")
|
||||
global visual line mode: user.emacs("global-visual-line-mode")
|
||||
highlight line mode: user.emacs("hl-line-mode")
|
||||
lisp interaction mode: user.emacs("lisp-interaction-mode")
|
||||
markdown mode: user.emacs("markdown-mode")
|
||||
menu bar mode: user.emacs("menu-bar-mode")
|
||||
overwrite mode: user.emacs("overwrite-mode")
|
||||
paredit mode: user.emacs("paredit-mode")
|
||||
rainbow mode: user.emacs("rainbow-mode")
|
||||
read only mode: user.emacs("read-only-mode")
|
||||
shell script mode: user.emacs("sh-mode")
|
||||
sub word mode: user.emacs("subword-mode")
|
||||
tab bar mode: user.emacs("tab-bar-mode")
|
||||
talon script mode: user.emacs("talonscript-mode")
|
||||
text mode: user.emacs("text-mode")
|
||||
transient mark mode: user.emacs("transient-mark-mode")
|
||||
visual line mode: user.emacs("visual-line-mode")
|
||||
whitespace mode: user.emacs("whitespace-mode")
|
||||
|
||||
# MACROS #
|
||||
emacs record: user.emacs("kmacro-start-macro")
|
||||
emacs stop: user.emacs("kmacro-end-macro")
|
||||
emacs play: user.emacs("kmacro-end-and-call-macro")
|
||||
|
||||
# PROFILER #
|
||||
profiler start: user.emacs("profiler-start")
|
||||
profiler stop: user.emacs("profiler-stop")
|
||||
profiler report: user.emacs("profiler-report")
|
||||
|
||||
# WINDOW/SPLIT MANAGEMENT #
|
||||
# What emacs calls windows, we call splits.
|
||||
split solo: user.emacs("delete-other-windows")
|
||||
[split] rebalance: user.emacs("balance-windows")
|
||||
split shrink: user.emacs("shrink-window-if-larger-than-buffer")
|
||||
other [split] shrink:
|
||||
user.split_next()
|
||||
user.emacs("shrink-window-if-larger-than-buffer")
|
||||
user.split_last()
|
||||
split grow: user.emacs("enlarge-window")
|
||||
split grow <number_small>: user.emacs("enlarge-window", number_small)
|
||||
split shrink <number_small>:
|
||||
amount = number_small or 1
|
||||
user.emacs("enlarge-window", 0 - amount)
|
||||
split widen [<number_small>]:
|
||||
user.emacs("enlarge-window-horizontally", number_small or 1)
|
||||
split narrow [<number_small>]:
|
||||
user.emacs("shrink-window-horizontally", number_small or 1)
|
||||
|
||||
# ----- HELP ----- #
|
||||
apropos: user.emacs_help("a")
|
||||
describe (fun | function): user.emacs_help("f")
|
||||
describe key: user.emacs_help("k")
|
||||
describe key briefly: user.emacs_help("c")
|
||||
describe symbol: user.emacs_help("o")
|
||||
describe variable: user.emacs_help("v")
|
||||
describe mode: user.emacs_help("m")
|
||||
describe bindings: user.emacs_help("b")
|
||||
describe (char | character): user.emacs("describe-character")
|
||||
describe text properties: user.emacs("describe-text-properties")
|
||||
describe face: user.emacs("describe-face")
|
||||
view lossage: user.emacs_help("l")
|
||||
|
||||
apropos <user.text>$:
|
||||
user.emacs_help("a")
|
||||
user.insert_formatted(text, "DASH_SEPARATED")
|
||||
key(enter)
|
||||
describe (fun | function) <user.text>$:
|
||||
user.emacs_help("f")
|
||||
user.insert_formatted(text, "DASH_SEPARATED")
|
||||
key(enter)
|
||||
describe symbol <user.text>$:
|
||||
user.emacs_help("o")
|
||||
user.insert_formatted(text, "DASH_SEPARATED")
|
||||
key(enter)
|
||||
describe variable <user.text>$:
|
||||
user.emacs_help("v")
|
||||
user.insert_formatted(text, "DASH_SEPARATED")
|
||||
key(enter)
|
||||
|
||||
# ----- FILES & BUFFERS -----
|
||||
file open: user.emacs("find-file")
|
||||
file rename: user.emacs("rename-file")
|
||||
(file open | find file) at point: user.emacs("ffap")
|
||||
other file open: user.emacs("find-file-other-window")
|
||||
(file | buffer) close:
|
||||
user.emacs("kill-buffer")
|
||||
key(enter)
|
||||
|
||||
buffer kill: user.emacs("kill-buffer")
|
||||
buffer bury: user.emacs("bury-buffer")
|
||||
buffer revert | revert buffer: user.emacs("revert-buffer")
|
||||
buffer finish:
|
||||
edit.save()
|
||||
user.emacs("server-edit")
|
||||
buffer list: user.emacs("buffer-menu")
|
||||
buffer next: user.emacs("next-buffer")
|
||||
buffer last: user.emacs("previous-buffer")
|
||||
buffer rename: user.emacs("rename-buffer")
|
||||
buffer widen: user.emacs("widen")
|
||||
buffer narrow | [buffer] narrow to region: user.emacs("narrow-to-region")
|
||||
|
||||
diff (buffer | [buffer] with file):
|
||||
user.emacs("diff-buffer-with-file")
|
||||
key(enter)
|
||||
|
||||
# ----- MOTION AND EDITING ----- #
|
||||
mark: user.emacs("set-mark-command")
|
||||
go back: user.emacs("pop-to-mark-command")
|
||||
global [go] back: user.emacs("pop-global-mark")
|
||||
|
||||
auto indent: user.emacs("indent-region")
|
||||
indent <user.number_signed_small>: user.emacs("indent-rigidly", number_signed_small)
|
||||
|
||||
search back: user.emacs("isearch-backward")
|
||||
(search regex | regex search): user.emacs("isearch-forward-regexp")
|
||||
(search regex | regex search) back: user.emacs("isearch-backward-regexp")
|
||||
replace: user.emacs("query-replace")
|
||||
replace regex | regex replace: user.emacs("query-replace-regexp")
|
||||
# These start a word/symbol-search or toggle an existing search's mode.
|
||||
search [toggle] words: user.emacs("isearch-forward-word")
|
||||
search [toggle] symbol: user.emacs("isearch-forward-symbol")
|
||||
# These keybindings are only active in isearch-mode.
|
||||
search edit: user.emacs_meta("e")
|
||||
search toggle case [fold | sensitive]: user.emacs_meta("c")
|
||||
search toggle regex: user.emacs_meta("r")
|
||||
|
||||
highlight lines matching [regex]: user.emacs("highlight-lines-matching-regexp")
|
||||
highlight phrase: user.emacs("highlight-phrase")
|
||||
highlight regex: user.emacs("highlight-regexp")
|
||||
unhighlight (regex | phrase): user.emacs("unhighlight-regexp")
|
||||
unhighlight all:
|
||||
user.emacs_prefix()
|
||||
user.emacs("unhighlight-regexp")
|
||||
|
||||
recenter:
|
||||
user.emacs_prefix()
|
||||
user.emacs("recenter-top-bottom")
|
||||
(center | [center] <number_small> from) top:
|
||||
user.emacs("recenter-top-bottom", number_small or 0)
|
||||
(center | [center] <number_small> from) bottom:
|
||||
number = number_small or 0
|
||||
user.emacs("recenter-top-bottom", -1 - number)
|
||||
go <number> top:
|
||||
edit.jump_line(number)
|
||||
user.emacs("recenter-top-bottom", 0)
|
||||
go <number> bottom:
|
||||
edit.jump_line(number)
|
||||
user.emacs("recenter-top-bottom", -2)
|
||||
|
||||
next error | error next: user.emacs("next-error")
|
||||
last error | error last: user.emacs("previous-error")
|
||||
|
||||
term right: user.emacs("forward-sexp")
|
||||
term left: user.emacs("backward-sexp")
|
||||
term up: user.emacs("backward-up-list")
|
||||
term end: user.emacs("up-list")
|
||||
term down: user.emacs("down-list")
|
||||
term kill: user.emacs("kill-sexp")
|
||||
term wipe: user.emacs("kill-sexp", -1)
|
||||
term (mark | select): user.emacs("mark-sexp")
|
||||
term copy:
|
||||
user.emacs("mark-sexp")
|
||||
edit.copy()
|
||||
term freeze:
|
||||
user.emacs("mark-sexp")
|
||||
user.emacs("comment-region")
|
||||
term [auto] indent:
|
||||
user.emacs("mark-sexp")
|
||||
user.emacs("indent-region")
|
||||
|
||||
(sentence | sent) (right | end): edit.sentence_end()
|
||||
(sentence | sent) (left | start): edit.sentence_start()
|
||||
(sentence | sent) kill: user.emacs("kill-sentence")
|
||||
|
||||
graph kill: user.emacs("kill-paragraph")
|
||||
graph up: edit.paragraph_start()
|
||||
graph down: edit.paragraph_end()
|
||||
graph mark: user.emacs("mark-paragraph")
|
||||
graph copy:
|
||||
user.emacs("mark-paragraph")
|
||||
edit.copy()
|
||||
graph cut:
|
||||
user.emacs("mark-paragraph")
|
||||
edit.cut()
|
||||
|
||||
# NB. can use these to implement "drag <X> left/right/up/down" commands,
|
||||
# but note that 'transpose line' and 'drag line down' are different.
|
||||
transpose [word | words]: user.emacs("transpose-words")
|
||||
transpose (term | terms): user.emacs("transpose-sexps")
|
||||
transpose (char | chars): user.emacs("transpose-chars")
|
||||
transpose (line | lines): user.emacs("transpose-lines")
|
||||
transpose (sentence | sentences): user.emacs("transpose-sentences")
|
||||
transpose (graph | graphs | paragraphs): user.emacs("transpose-paragraphs")
|
||||
|
||||
register (copy | save): user.emacs("copy-to-register")
|
||||
register (paste | insert): user.emacs("insert-register")
|
||||
register jump: user.emacs("jump-to-register")
|
||||
register (copy | save) rectangle: user.emacs("copy-rectangle-to-register")
|
||||
|
||||
rectangle clear: user.emacs("clear-rectangle")
|
||||
rectangle delete: user.emacs("delete-rectangle")
|
||||
rectangle kill: user.emacs("kill-rectangle")
|
||||
rectangle open: user.emacs("open-rectangle")
|
||||
rectangle (copy | save) [to] register: user.emacs("copy-rectangle-to-register")
|
||||
rectangle (yank | paste): user.emacs("yank-rectangle")
|
||||
rectangle copy: user.emacs("copy-rectangle-as-kill")
|
||||
rectangle number lines: user.emacs("rectangle-number-lines")
|
||||
|
||||
# ----- XREF SUPPORT ----- #
|
||||
[xref] find definition: user.emacs("xref-find-definitions")
|
||||
[xref] find definition other window: user.emacs("xref-find-definitions-other-window")
|
||||
[xref] find definition other frame: user.emacs("xref-find-definitions-other-frame")
|
||||
[xref] find references: user.emacs("xref-find-references")
|
||||
[xref] find references [and] replace: user.emacs("xref-find-references-and-replace")
|
||||
xref find apropos: user.emacs("xref-find-apropos")
|
||||
xref go back: user.emacs("xref-go-back")
|
||||
visit tags table: user.emacs("visit-tags-table")
|
||||
|
||||
# ----- PROJECT SUPPORT ----- #
|
||||
project [find] file: user.emacs("project-find-file")
|
||||
project [find] (regex | grep): user.emacs("project-find-regexp")
|
||||
project [query] replace regex: user.emacs("project-query-replace-regexp")
|
||||
project (dired | directory): user.emacs("projectile-dired")
|
||||
project [run] shell: user.emacs("projectile-run-shell")
|
||||
project [run] eshell: user.emacs("projectile-run-eshell")
|
||||
project search: user.emacs("project-search")
|
||||
project vc dir: user.emacs("project-vc-dir")
|
||||
project compile [project]: user.emacs("projectile-compile-project")
|
||||
project [run] shell command: user.emacs("projectile-run-shell-command-in-root")
|
||||
project [run] async shell command:
|
||||
user.emacs("projectile-run-async-shell-command-in-root")
|
||||
project (switch [to buffer] | buffer | buff): user.emacs("projectile-switch-to-buffer")
|
||||
project kill [buffers]: user.emacs("projectile-kill-buffers")
|
||||
project switch [project]: user.emacs("project-switch-project")
|
||||
|
||||
# ----- VC/GIT SUPPORT ----- #
|
||||
vc (annotate | blame): user.emacs("vc-annotate")
|
||||
|
||||
# ----- MAJOR & MINOR MODES ----- #
|
||||
# python-mode #
|
||||
python mode: user.emacs("python-mode")
|
||||
run python: user.emacs("run-python")
|
||||
python [shell] send buffer: user.emacs("python-shell-send-buffer")
|
||||
python [shell] send file: user.emacs("python-shell-send-file")
|
||||
python [shell] send region: user.emacs("python-shell-send-region")
|
||||
python [shell] send (function | defun): user.emacs("python-shell-send-defun")
|
||||
python [shell] send statement: user.emacs("python-shell-send-statement")
|
||||
python (shell switch | switch [to] shell): user.emacs("python-shell-switch-to-shell")
|
||||
|
||||
# smerge-mode #
|
||||
smerge mode: user.emacs("smerge-mode")
|
||||
merge next: user.emacs("smerge-next")
|
||||
merge last: user.emacs("smerge-prev")
|
||||
merge keep upper: user.emacs("smerge-keep-upper")
|
||||
merge keep lower: user.emacs("smerge-keep-lower")
|
||||
merge keep base: user.emacs("smerge-keep-base")
|
||||
merge keep (this | current): user.emacs("smerge-keep-current")
|
||||
merge refine: user.emacs("smerge-refine")
|
||||
merge split: user.emacs("smerge-resolve")
|
||||
|
||||
# outline-minor-mode #
|
||||
# frequent: overview, show, hide, next, last, forward, backward, up
|
||||
outline minor mode: user.emacs("outline-minor-mode")
|
||||
outline show all: user.emacs("outline-show-all")
|
||||
outline show entry: user.emacs("outline-show-entry")
|
||||
outline hide entry: user.emacs("outline-hide-entry")
|
||||
outline show [subtree]: user.emacs("outline-show-subtree")
|
||||
outline hide [subtree]: user.emacs("outline-hide-subtree")
|
||||
outline show children: user.emacs("outline-show-children")
|
||||
outline show branches: user.emacs("outline-show-branches")
|
||||
outline hide leaves: user.emacs("outline-hide-leaves")
|
||||
outline hide sublevels: user.emacs("outline-hide-sublevels")
|
||||
outline (hide body | [show] (overview | outline)): user.emacs("outline-hide-body")
|
||||
outline hide other: user.emacs("outline-hide-other")
|
||||
outline forward [same level]: user.emacs("outline-forward-same-level")
|
||||
outline (backward | back) [same level]: user.emacs("outline-backward-same-level")
|
||||
outline next [visible heading]: user.emacs("outline-next-visible-heading")
|
||||
outline (previous | last) [visible heading]:
|
||||
user.emacs("outline-previous-visible-heading")
|
||||
outline insert [heading]: user.emacs("outline-insert-heading")
|
||||
outline up [heading]: user.emacs("outline-up-heading")
|
||||
outline promote: user.emacs("outline-promote")
|
||||
outline demote: user.emacs("outline-demote")
|
||||
outline move [subtree] down: user.emacs("outline-move-subtree-down")
|
||||
outline move [subtree] up: user.emacs("outline-move-subtree-up")
|
||||
outline mark [subtree]: user.emacs("outline-mark-subtree")
|
||||
@@ -0,0 +1,231 @@
|
||||
Command, Key binding, Short form, Spoken form
|
||||
abort-recursive-edit, ctrl-]
|
||||
auto-fill-mode,, auto-f
|
||||
backward-paragraph, meta-{
|
||||
backward-sentence, meta-a
|
||||
backward-sexp, meta-ctrl-b
|
||||
backward-up-list, meta-ctrl-up
|
||||
backward-word, meta-b
|
||||
balance-windows, ctrl-x +
|
||||
beginning-of-buffer, meta-<
|
||||
browse-kill-ring,, b-k-r
|
||||
buffer-menu, ctrl-x ctrl-b
|
||||
bury-buffer,, bur
|
||||
byte-compile-file,, by-c
|
||||
byte-recompile-directory
|
||||
byte-recompile-file
|
||||
clear-rectangle, ctrl-x r c
|
||||
clone-indirect-buffer,, clo-i
|
||||
comment-dwim, meta-;
|
||||
comment-line,, comment-l
|
||||
comment-region, ctrl-c ;
|
||||
compile
|
||||
compile-defun,, co-def
|
||||
copy-rectangle-as-kill, ctrl-x r meta-w
|
||||
copy-rectangle-to-register, ctrl-x r r
|
||||
copy-to-register, ctrl-x r s
|
||||
custom-theme-visit-theme
|
||||
customize-face
|
||||
customize-group
|
||||
customize-variable
|
||||
delete-other-windows, ctrl-x 1
|
||||
delete-rectangle, ctrl-x r d
|
||||
delete-window, ctrl-x 0
|
||||
describe-character,, desc-char
|
||||
diff-buffer-with-file,, d-b-w-f
|
||||
display-buffer, ctrl-x 4 ctrl-o
|
||||
dired-jump, ctrl-x ctrl-j
|
||||
dired-jump-other-window, ctrl-x 4 ctrl-j
|
||||
display-buffer, ctrl-x 4 ctrl-o
|
||||
display-line-numbers-mode,, dis-num
|
||||
down-list, meta-ctrl-down
|
||||
electric-quote-local-mode
|
||||
electric-quote-mode
|
||||
end-of-buffer, meta->
|
||||
enlarge-window, ctrl-x ^
|
||||
enlarge-window-horizontally, ctrl-x }
|
||||
eval-expression, meta-:
|
||||
eval-print-last-sexp,, ev-p
|
||||
eval-region,, ev-r
|
||||
exchange-point-and-mark, ctrl-x ctrl-x
|
||||
execute-extended-command, meta-x
|
||||
fileloop-continue,, filel
|
||||
fill-paragraph, meta-q
|
||||
find-file, ctrl-x ctrl-f
|
||||
font-lock-update, ctrl-x x f
|
||||
forward-paragraph, meta-}
|
||||
forward-sentence, meta-e
|
||||
forward-sexp, meta-ctrl-f
|
||||
forward-word, meta-f
|
||||
fundamental-mode,, fun-m
|
||||
global-display-line-numbers-mode,, g-d-l-n-m
|
||||
global-hl-line-mode,, g-hl-l-m
|
||||
global-visual-line-mode,, gl-v-l-m
|
||||
goto-line, meta-g meta-g
|
||||
highlight-lines-matching-regexp, meta-s h l
|
||||
highlight-phrase, meta-s h p
|
||||
highlight-regexp, meta-s h r
|
||||
hl-line-mode,, hl-l-m
|
||||
indent-region, meta-ctrl-\
|
||||
indent-rigidly, ctrl-x tab
|
||||
insert-char, ctrl-x 8 enter
|
||||
insert-register, ctrl-x r i
|
||||
isearch-backward, ctrl-r
|
||||
isearch-backward-regexp, meta-ctrl-r
|
||||
isearch-forward, ctrl-s
|
||||
isearch-forward-regexp, meta-ctrl-s
|
||||
isearch-forward-symbol, meta-s _
|
||||
isearch-forward-word, meta-s w
|
||||
jump-to-register, ctrl-x r j
|
||||
keyboard-quit, ctrl-g
|
||||
kill-buffer, ctrl-x k
|
||||
kill-line, ctrl-k
|
||||
kill-paragraph,, kill-par
|
||||
kill-rectangle, ctrl-x r k
|
||||
kill-region, ctrl-w
|
||||
kill-ring-save, meta-w
|
||||
kill-sentence, meta-k
|
||||
kill-sexp, meta-ctrl-k
|
||||
kill-word, meta-d
|
||||
kmacro-end-and-call-macro, ctrl-x e
|
||||
kmacro-end-macro, ctrl-x )
|
||||
kmacro-start-macro, ctrl-x (
|
||||
list-packages
|
||||
make-frame-command, ctrl-x 5 2
|
||||
mark-paragraph, meta-h
|
||||
mark-sexp, meta-ctrl-@
|
||||
mark-whole-buffer, ctrl-x h
|
||||
move-beginning-of-line, ctrl-a
|
||||
move-end-of-line, ctrl-e
|
||||
narrow-to-region, ctrl-x n n
|
||||
next-buffer, ctrl-x right
|
||||
next-error, meta-g n
|
||||
occur, meta-s o
|
||||
open-rectangle, ctrl-x r o
|
||||
other-frame, ctrl-x 5 o
|
||||
other-window, ctrl-x o
|
||||
outline-backward-same-level, ctrl-c @ ctrl-b
|
||||
outline-demote, ctrl-c @ ctrl->
|
||||
outline-forward-same-level, ctrl-c @ ctrl-f
|
||||
outline-hide-body, ctrl-c @ ctrl-t
|
||||
outline-hide-entry, ctrl-c @ ctrl-c
|
||||
outline-hide-leaves, ctrl-c @ ctrl-l
|
||||
outline-hide-other, ctrl-c @ ctrl-o
|
||||
outline-hide-sublevels, ctrl-c @ ctrl-q
|
||||
outline-hide-subtree, ctrl-c @ ctrl-d
|
||||
outline-insert-heading, ctrl-c @ RET
|
||||
outline-mark-subtree, ctrl-c @ @
|
||||
outline-move-subtree-down, ctrl-c @ ctrl-v
|
||||
outline-move-subtree-up, ctrl-c @ ctrl-^
|
||||
outline-next-visible-heading, ctrl-c @ ctrl-n
|
||||
outline-previous-visible-heading, ctrl-c @ ctrl-p
|
||||
outline-promote, ctrl-c @ ctrl-<
|
||||
outline-show-all, ctrl-c @ ctrl-a
|
||||
outline-show-branches, ctrl-c @ ctrl-k
|
||||
outline-show-children, ctrl-c @ tab
|
||||
outline-show-entry, ctrl-c @ ctrl-e
|
||||
outline-show-subtree, ctrl-c @ ctrl-s
|
||||
outline-up-heading, ctrl-c @ ctrl-u
|
||||
overwrite-mode,, overwr
|
||||
package-autoremove
|
||||
pop-global-mark, ctrl-x ctrl-@
|
||||
pop-to-mark-command, ctrl-u ctrl-space
|
||||
previous-buffer, ctrl-x left
|
||||
previous-error, meta-g p
|
||||
project-find-file, ctrl-x p f
|
||||
project-find-regexp, ctrl-x p g
|
||||
project-query-replace-regexp, ctrl-x p r
|
||||
project-search, ctrl-x p ctrl-s
|
||||
project-switch-project
|
||||
project-vc-dir, ctrl-x p v
|
||||
projectile-compile-project, ctrl-x p c
|
||||
projectile-dired, ctrl-x p d
|
||||
projectile-kill-buffers, ctrl-x p k
|
||||
projectile-run-async-shell-command-in-root, ctrl-x p &
|
||||
projectile-run-eshell, ctrl-x p e
|
||||
projectile-run-shell, ctrl-x p s
|
||||
projectile-run-shell-command-in-root, ctrl-x p !
|
||||
projectile-switch-to-buffer, ctrl-x p b
|
||||
query-replace, meta-%
|
||||
query-replace-regexp, meta-ctrl-%
|
||||
read-only-mode, ctrl-x ctrl-q
|
||||
recenter-top-bottom, ctrl-l
|
||||
recenter-top-bottom, ctrl-l
|
||||
rectangle-number-lines, ctrl-x r N
|
||||
rename-buffer, ctrl-x x r, ren-b
|
||||
rename-uniquely, ctrl-x x u
|
||||
reverse-region
|
||||
revert-buffer,, rev-buf
|
||||
revert-buffer-quick, ctrl-x x g
|
||||
save-buffer, ctrl-x ctrl-s
|
||||
save-buffers-kill-emacs,, s-b-k-e
|
||||
save-some-buffers, ctrl-x s
|
||||
scroll-other-window, meta-pagedown
|
||||
scroll-other-window-down, meta-pageup
|
||||
server-edit, ctrl-x #
|
||||
set-mark-command, ctrl-@
|
||||
sh-mode
|
||||
shell-command, meta-!
|
||||
shell-command-on-region, meta-|
|
||||
shell-script-mode
|
||||
shrink-window-horizontally, ctrl-x {
|
||||
shrink-window-if-larger-than-buffer, ctrl-x -
|
||||
smerge-combine-with-next
|
||||
smerge-diff-base-lower
|
||||
smerge-diff-base-upper
|
||||
smerge-diff-upper-lower
|
||||
smerge-ediff
|
||||
smerge-keep-all
|
||||
smerge-keep-base
|
||||
smerge-keep-current, ctrl-c ^ enter
|
||||
smerge-keep-lower, ctrl-c ^ l
|
||||
smerge-keep-upper, ctrl-c ^ u
|
||||
smerge-next, ctrl-c ^ n
|
||||
smerge-prev, ctrl-c ^ p
|
||||
smerge-refine, ctrl-c ^ R
|
||||
smerge-resolve, ctrl-c ^ r
|
||||
sort-lines
|
||||
sort-words
|
||||
split-window-below, ctrl-x 2
|
||||
split-window-right, ctrl-x 3
|
||||
switch-to-buffer, ctrl-x b
|
||||
switch-to-buffer-other-window, ctrl-x 4 b
|
||||
tab-bar-mode
|
||||
tab-close, ctrl-x t 0
|
||||
tab-close-other, ctrl-x t 1
|
||||
tab-new, ctrl-x t 2
|
||||
tab-next, ctrl-x t o
|
||||
tab-previous, ctrl-x t O
|
||||
tab-undo, ctrl-x t u
|
||||
text-mode,, text-m
|
||||
toggle-debug-on-error,, t-d-on-e
|
||||
toggle-debug-on-quit,, t-d-on-q
|
||||
toggle-input-method, ctrl-\
|
||||
toggle-truncate-lines, ctrl-x x t
|
||||
toggle-word-wrap
|
||||
transient-mark-mode,, tr-m-m
|
||||
transpose-chars, ctrl-t
|
||||
transpose-lines, ctrl-x ctrl-t
|
||||
transpose-paragraphs,, tr-par
|
||||
transpose-sentences,, tr-sen
|
||||
transpose-sexps, meta-ctrl-t
|
||||
transpose-words, meta-t
|
||||
undo, ctrl-_
|
||||
unhighlight-regexp, meta-s h u
|
||||
universal-argument, ctrl-u
|
||||
vc-annotate, ctrl-x v g
|
||||
view-lossage, ctrl-h l
|
||||
visit-tags-table,, v-t-t
|
||||
visual-line-mode,, visu-l-m
|
||||
whitespace-cleanup,, wh-cl
|
||||
whitespace-mode,, white-m
|
||||
widen, ctrl-x n w
|
||||
xref-find-apropos, meta-ctrl-.
|
||||
xref-find-definitions, meta-.
|
||||
xref-find-definitions-other-frame, ctrl-x 5 .
|
||||
xref-find-definitions-other-window, ctrl-x 4 .
|
||||
xref-find-references, meta-?
|
||||
xref-find-references-and-replace
|
||||
xref-go-back,"meta-,"
|
||||
yank, ctrl-y
|
||||
yank-rectangle, ctrl-x r y
|
||||
|
@@ -0,0 +1,71 @@
|
||||
import csv
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from typing import NamedTuple, Optional
|
||||
|
||||
from talon import Context, Module, actions, app, resource
|
||||
|
||||
mod = Module()
|
||||
mod.list("emacs_command", desc="Emacs commands")
|
||||
|
||||
ctx = Context()
|
||||
|
||||
|
||||
class Command(NamedTuple):
|
||||
name: str
|
||||
keys: Optional[str] = None
|
||||
short: Optional[str] = None
|
||||
spoken: Optional[str] = None
|
||||
|
||||
|
||||
# Maps command name to Command.
|
||||
emacs_commands = {}
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def emacs_command_keybinding(command_name: str) -> Optional[str]:
|
||||
"Looks up the keybinding for command_name in emacs_commands.csv."
|
||||
return emacs_commands.get(command_name, Command(command_name)).keys
|
||||
|
||||
def emacs_command_short_form(command_name: str) -> Optional[str]:
|
||||
"Looks up the short form for command_name in emacs_commands.csv."
|
||||
return emacs_commands.get(command_name, Command(command_name)).short
|
||||
|
||||
|
||||
@resource.watch("emacs_commands.csv")
|
||||
def load_commands(f):
|
||||
rows = list(csv.reader(f))
|
||||
# Check headers
|
||||
assert rows[0] == ["Command", " Key binding", " Short form", " Spoken form"]
|
||||
|
||||
commands = []
|
||||
for row in rows[1:]:
|
||||
if 0 == len(row):
|
||||
continue
|
||||
if len(row) > 4:
|
||||
print(
|
||||
f"emacs_commands.csv: More than four values in row: {row}. "
|
||||
+ " Ignoring the extras"
|
||||
)
|
||||
name, keys, short, spoken = (
|
||||
[x.strip() or None for x in row] + [None, None, None]
|
||||
)[:4]
|
||||
commands.append(Command(name=name, keys=keys, short=short, spoken=spoken))
|
||||
|
||||
# Update global command info.
|
||||
global emacs_commands
|
||||
emacs_commands = {c.name: c for c in commands}
|
||||
|
||||
# Generate spoken forms and apply overrides.
|
||||
try:
|
||||
command_list = actions.user.create_spoken_forms_from_list(
|
||||
[c.name for c in commands], generate_subsequences=False
|
||||
)
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
for c in commands:
|
||||
if c.spoken:
|
||||
command_list[c.spoken] = c.name
|
||||
ctx.lists["self.emacs_command"] = command_list
|
||||
Reference in New Issue
Block a user