add talon as an option; yet unconfigured
This commit is contained in:
parent
857666f226
commit
065a7d1e6f
552 changed files with 36089 additions and 0 deletions
44
flake.lock
generated
44
flake.lock
generated
|
@ -611,6 +611,27 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-github-actions_2": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"talon",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1693660503,
|
||||
"narHash": "sha256-B/g2V4v6gjirFmy+I5mwB2bCYc0l3j5scVfwgl6WOl8=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"rev": "bd5bdbb52350e145c526108f4ef192eb8e554fa0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-github-actions",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix-on-droid": {
|
||||
"inputs": {
|
||||
"home-manager": [
|
||||
|
@ -963,6 +984,7 @@
|
|||
"nixpkgs": "nixpkgs_6",
|
||||
"openxc7": "openxc7",
|
||||
"stylix": "stylix",
|
||||
"talon": "talon",
|
||||
"waveforms": "waveforms"
|
||||
}
|
||||
},
|
||||
|
@ -1125,6 +1147,28 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"talon": {
|
||||
"inputs": {
|
||||
"nix-github-actions": "nix-github-actions_2",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1720064283,
|
||||
"narHash": "sha256-/C+A08rgPQ+R2SJwaGNpt/rQ0xa6cbyWHqw3nB1caxI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "talon-nix",
|
||||
"rev": "718a82d3f45fa875f00f61867d6ed9285e40ce59",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "master",
|
||||
"repo": "talon-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"tinted-foot": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
|
|
|
@ -34,6 +34,12 @@
|
|||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# Talon voice.
|
||||
talon = {
|
||||
url = "github:nix-community/talon-nix/master";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
|
||||
# For our phone.
|
||||
nix-on-droid = {
|
||||
url = "github:nix-community/nix-on-droid/release-24.05";
|
||||
|
@ -83,6 +89,7 @@
|
|||
attic,
|
||||
nix-flatpak,
|
||||
nix-on-droid,
|
||||
talon,
|
||||
...
|
||||
}:
|
||||
|
||||
|
@ -200,6 +207,7 @@
|
|||
stylix
|
||||
is-hm-standalone
|
||||
is-droid
|
||||
talon
|
||||
;
|
||||
|
||||
niri = niri.outputs;
|
||||
|
@ -275,6 +283,7 @@
|
|||
./nixos/hosts/valere.nix
|
||||
./nixos/configs/steam.nix
|
||||
./nixos/configs/vmware.nix
|
||||
./nixos/configs/talon-voice.nix
|
||||
./nixos/configs/power-saving.nix
|
||||
];
|
||||
};
|
||||
|
|
11
nixos/configs/talon-voice.nix
Normal file
11
nixos/configs/talon-voice.nix
Normal file
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Configuration that adds talon-voice.
|
||||
#
|
||||
{ talon, ... }:
|
||||
{
|
||||
imports = [
|
||||
talon.nixosModules.talon
|
||||
];
|
||||
|
||||
programs.talon.enable = true;
|
||||
}
|
17
talon/user/community/.editorconfig
Normal file
17
talon/user/community/.editorconfig
Normal file
|
@ -0,0 +1,17 @@
|
|||
# See https://EditorConfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
max_line_length = 88
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{md,yaml,yml}]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
3
talon/user/community/.git-blame-ignore-revs
Normal file
3
talon/user/community/.git-blame-ignore-revs
Normal file
|
@ -0,0 +1,3 @@
|
|||
2877a6849d75e5fa78c9453991a9235b4f6d9dcf
|
||||
3bf4882fa0a05b22171e59118bd7c9640aae753a
|
||||
446ec764c9caa98973eacd7f792b6a087a1b635f
|
7
talon/user/community/.github/dependabot.yml
vendored
Normal file
7
talon/user/community/.github/dependabot.yml
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
version: 2
|
||||
updates:
|
||||
# Maintain dependencies for GitHub Actions
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
25
talon/user/community/.github/workflows/ci.yml
vendored
Normal file
25
talon/user/community/.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.9"
|
||||
cache: "pip"
|
||||
cache-dependency-path: |
|
||||
requirements-dev.txt
|
||||
- run: pip install -r requirements-dev.txt
|
||||
- run: pytest
|
9
talon/user/community/.gitignore
vendored
Normal file
9
talon/user/community/.gitignore
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
# Dev stuff
|
||||
__pycache__
|
||||
*.sw?
|
||||
.idea/
|
||||
# Locally generated
|
||||
/settings
|
||||
.vscode/settings.json
|
||||
.DS_Store
|
||||
.bak
|
52
talon/user/community/.pre-commit-config.yaml
Normal file
52
talon/user/community/.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,52 @@
|
|||
minimum_pre_commit_version: "3.2.0"
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
- id: check-case-conflict
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-merge-conflict
|
||||
- id: check-shebang-scripts-are-executable
|
||||
- id: check-symlinks
|
||||
- id: destroyed-symlinks
|
||||
- id: detect-private-key
|
||||
- id: fix-byte-order-marker
|
||||
# NB. To avoid sometimes needing multiple runs, we need:
|
||||
# - trailing-whitespace BEFORE end-of-file-fixer,
|
||||
# otherwise trailing newline followed by whitespace, "\n ",
|
||||
# will need multiple runs.
|
||||
# - end-of-file-fixer BEFORE mixed-line-ending,
|
||||
# otherwise a file with CRLF line endings but missing a trailing
|
||||
# newline will need multiple runs.
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: mixed-line-ending
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: "v4.0.0-alpha.8"
|
||||
hooks:
|
||||
- id: prettier
|
||||
- repo: https://github.com/ikamensh/flynt/
|
||||
rev: "1.0.1"
|
||||
hooks:
|
||||
- id: flynt
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.13.2
|
||||
hooks:
|
||||
- id: isort
|
||||
- repo: https://github.com/psf/black-pre-commit-mirror
|
||||
rev: 24.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.5.5
|
||||
hooks:
|
||||
- id: remove-tabs
|
||||
types: [file]
|
||||
files: \.talon$
|
||||
args: ["--whitespaces-count=4"]
|
||||
- repo: https://github.com/wenkokke/talonfmt
|
||||
rev: 1.10.2
|
||||
hooks:
|
||||
- id: talonfmt
|
||||
args: ["--in-place"]
|
44
talon/user/community/BREAKING_CHANGES.txt
Normal file
44
talon/user/community/BREAKING_CHANGES.txt
Normal file
|
@ -0,0 +1,44 @@
|
|||
This file lists known changes to `community` that are likely to have
|
||||
broken existing functionality. The file is sorted by date with the
|
||||
newest entries up the top.
|
||||
|
||||
Be aware there may be some difference between the date in this file
|
||||
and when the change was applied given the delay between changes being
|
||||
submitted and the time they were reviewed and merged.
|
||||
|
||||
---
|
||||
* 2024-09-07 Removed `get_list_from_csv` from `user_settings.py`. Please
|
||||
use the new `track_csv_list` decorator, which leverages Talon's
|
||||
`talon.watch` API for robustness on Talon launch.
|
||||
* 2024-09-07 If you've updated `community` since 2024-08-31, you may
|
||||
need to replace `host:` with `hostname:` in the header of
|
||||
`core/system_paths-<hostname>.talon-list` due to an issue with
|
||||
automatic conversion from CSV (#1268).
|
||||
* 2024-07-31 Remove commands `"command mode"`, `"dictation mode"` from
|
||||
custom user modes. Note that if you have any custom modes where you
|
||||
want these commands you could add that mode to the context of
|
||||
`command_and_dictation_mode.talon` or copying the command to one of
|
||||
your custom files.
|
||||
* 2024-07-30 Deprecate `lend` and `bend` commands in favor of `go line
|
||||
end | tail` and `go line start | head`.
|
||||
* 2024-07-28 Removed the following user namespace actions in favor of
|
||||
the new action/modifier grammar.
|
||||
https://github.com/talonhub/community/blob/37a8ebde90c8120a0b52555030988d4f54e65159/core/edit/edit.talon#L3
|
||||
cut_word, copy_word, paste_word
|
||||
cut_all, copy_all, paste_all, delete_all
|
||||
copy_line, paste_line
|
||||
cut_line_start, copy_line_start, paste_line_start, delete_line_start
|
||||
cut_line_end, copy_line_end, paste_line_end, delete_line_end
|
||||
* 2024-05-30 Deprecate 'drop down <user.number_small>' in favor of
|
||||
overridable 'choose' helper
|
||||
* 2024-01-27 Deprecate '<user.number_string>' command without a spoken
|
||||
prefix like `numb`. See `numbers.talon` and
|
||||
`numbers_unprefixed.talon.` If in the future you want to still use
|
||||
unprefixed numbers, you will need to comment out the
|
||||
`tag(): user.prefixed_numbers` line in your `settings.talon` file.
|
||||
* 2023-06-06 Deprecate `go` command for VSCode. Use 'bar marks' instead.
|
||||
* 2023-02-04 Deprecate `murder` command for i3wm. Use 'win kill' instead.
|
||||
* 2022-12-11 Deprecate user.insert_with_history. Just use
|
||||
`user.add_phrase_to_history(text); insert(text)` instead. See #939.
|
||||
* 2022-10-01 Large refactoring of code base that moves many files into
|
||||
new locations. No other backwards-incompatible changes included.
|
13
talon/user/community/CONTRIBUTING.md
Normal file
13
talon/user/community/CONTRIBUTING.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
This document attempts to list a set of principles for contributors to the `community` repository to consider. The idea is to document some agreed upon approaches toward reviewing and including code so we can all more easily make consistent decisions.
|
||||
|
||||
Each of the principles is numbered for easy referencing. The body is formatted as a short single-line summary of the principle followed by elaboration and discussion links.
|
||||
|
||||
# Voice command principles
|
||||
|
||||
- P01 - Prefer [object][verb] rather than [verb][object] for new commands. For example 'file save' is better than 'save file'. It may not sound as natural, but it helps for grouping related commands in lists and avoiding conflicting names.
|
||||
- P02 - Use `browser.host` matcher for web apps. Though this matcher requires a [browser extension](https://github.com/talonhub/community/blob/main/apps/README.md) on some operating systems it is the only unambiguous way of referring to a web app.
|
||||
|
||||
# Coding principles
|
||||
|
||||
- P03 - Use the `app.bundle` matcher for apps on OSX. This is the least ambiguous way of referring to a particular program.
|
||||
- P04 - Use both `app.name` and `app.exe` matchers for apps on Windows. That is the context should OR together one matcher of each type. Apparently the [MUICache](https://www.magnetforensics.com/blog/forensic-analysis-of-muicache-files-in-windows/) can break, perhaps making one of these matchers stop working.
|
21
talon/user/community/LICENSE
Normal file
21
talon/user/community/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2021 Jeff Knaus, Ryan Hileman, Zach Dwiel, Michael Arntzenius, and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
382
talon/user/community/README.md
Normal file
382
talon/user/community/README.md
Normal file
|
@ -0,0 +1,382 @@
|
|||
# community
|
||||
|
||||
Voice command set for [Talon](https://talonvoice.com/), community-supported.
|
||||
|
||||
_(Originally called `knausj_talon`, after [its original creator :superhero:](https://github.com/knausj85))_
|
||||
|
||||
Can be used on its own, but shines when combined with:
|
||||
|
||||
- [Cursorless](https://www.cursorless.org/) for programming and text editing
|
||||
- [Rango](https://github.com/david-tejada/rango) for browser navigation
|
||||
- [gaze-ocr](https://github.com/wolfmanstout/talon-gaze-ocr) for advanced cursor control using eye tracking and text recognition (OCR)
|
||||
- [AXKit](https://github.com/phillco/talon-axkit) (macOS only) to enhance Talon with native OS accessibility integrations
|
||||
- [Other user file sets](https://talon.wiki/talon_user_file_sets/)
|
||||
|
||||
## Installation
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [Talon](https://talonvoice.com/)
|
||||
- Mac, Windows, or Linux
|
||||
- Talon's built-in Conformer (wav2letter) speech recognition engine (recommended), or Dragon NaturallySpeaking (Windows) / Dragon for Mac (although beware that Dragon for Mac is discontinued and its use deprecated).
|
||||
|
||||
Includes commands for working with an eye tracker; an [eye tracker](https://talon.wiki/Quickstart/Hardware/#eye-trackers) is not required.
|
||||
|
||||
### Linux & Mac
|
||||
|
||||
It is recommended to install `community` using [`git`](https://git-scm.com/).
|
||||
|
||||
1. Install [`git`](https://git-scm.com/)
|
||||
2. Open a terminal ([Mac](https://support.apple.com/en-gb/guide/terminal/apd5265185d-f365-44cb-8b09-71a064a42125/mac) / [Ubuntu](https://ubuntu.com/tutorials/command-line-for-beginners#3-opening-a-terminal))
|
||||
3. Paste the following into the terminal window then press Enter/Return:
|
||||
|
||||
```bash
|
||||
cd ~/.talon/user
|
||||
git clone https://github.com/talonhub/community community
|
||||
```
|
||||
|
||||
Note that it is also possible to install `community` by [downloading and extracting a zip file](#alternate-installation-method-zip-file), but this approach is discouraged because it makes it more difficult to keep track of any changes you may make to your copy of the files.
|
||||
|
||||
### Windows
|
||||
|
||||
It is recommended to install `community` using [`git`](https://git-scm.com/).
|
||||
|
||||
1. Install [`git`](https://git-scm.com/)
|
||||
2. Open a [command prompt](https://www.wikihow.com/Open-the-Command-Prompt-in-Windows)
|
||||
3. Paste the following into the command prompt window then press Enter:
|
||||
|
||||
```
|
||||
cd %AppData%\Talon\user
|
||||
git clone https://github.com/talonhub/community community
|
||||
```
|
||||
|
||||
Note that it is also possible to install `community` by [downloading and extracting a zip file](#alternate-installation-method-zip-file), but this approach is discouraged because it makes it more difficult to keep track of any changes you may make to your copy of the files.
|
||||
|
||||
## Getting started with Talon
|
||||
|
||||
1. `help active` displays commands available in the active (frontmost) application.
|
||||
- Available commands can change by application, or even the window title.
|
||||
- Navigate help by voice using the displayed numbers (e.g., `help one one` or `help eleven` to open the item numbered 11), or by speaking button titles that don't start with numbers (e.g., `help next` to see the next page of contexts).
|
||||
- Help-related commands are defined in [help.talon](core/help/help.talon) and [help_open.talon](core/help/help_open.talon).
|
||||
2. Search for commands by saying `help search <phrase>`. For example, `help search tab` displays all tab-related commands, and `help search help` displays all help-related commands.
|
||||
3. Jump immediately to help for a particular help context with the name displayed the in help window (based on the name of the .talon file), e.g. `help context symbols` or `help context visual studio`
|
||||
4. `help alphabet` displays words for letters of the alphabet; `help symbols` displays words for symbols.
|
||||
5. `command history` toggles display of recent voice commands.
|
||||
6. `help format` displays available [formatters](#formatters) with examples.
|
||||
7. Many useful, basic commands are defined in [edit.talon](core/edit/edit.talon).
|
||||
- `undo that` and `redo that` are the default undo/redo commands.
|
||||
- `paste that`, `copy that`, and `cut that` for pasting/copy/cutting, respectively.
|
||||
8. For community-generated documentation on Talon itself, please visit https://talon.wiki/.
|
||||
|
||||
It's recommended to learn the alphabet first, then get familiar with the keys, symbols, formatters, mouse, and generic_editor commands.
|
||||
|
||||
Once you have the basics of text input down, try copying some code from one window to another.
|
||||
|
||||
After that, explore using ordinal repetition for easily repeating a command without pausing (e.g., saying `go up fifth` will go up five lines), window switching (`focus chrome`), and moving around in your text editor of choice.
|
||||
|
||||
If you use vim, just start with the numbers and alphabet, otherwise look at generic_editor.talon as well at jetbrains, vscode, and any other integrations.
|
||||
|
||||
### Alphabet
|
||||
|
||||
The alphabet is defined in
|
||||
[this Talon list file](core/keys/letter.talon-list).
|
||||
|
||||
Say `help alphabet` to open a window displaying the alphabet. `help close` closes the window.
|
||||
|
||||
Try saying e.g. `air bat cap` to insert abc.
|
||||
|
||||
### Keys
|
||||
|
||||
All key commands are defined in [keys.talon](core/keys/keys.talon). Say letters of the [Talon alphabet](#alphabet) for A–Z.
|
||||
|
||||
For modifier keys, say `help modifiers`. For example, say `shift air` to press `shift-a`, which types a capital `A`.
|
||||
|
||||
For symbols, say `help symbols`. These are defined in keys.py;
|
||||
search for `modifier_keys` and then keep scrolling — roughly starting [here](core/keys/keys.py#L124).
|
||||
|
||||
On Windows, try commands such as:
|
||||
|
||||
- `control air` to press Control+A and select all.
|
||||
|
||||
- `super-shift-sun` to press Win+Shift+S, triggering the screenshot application (Windows 10). Then try `escape` to exit.
|
||||
|
||||
On Mac, try commands such as:
|
||||
|
||||
- `command air` to press ⌘A and select all.
|
||||
|
||||
- `control shift command 4` to press ⌃⇧⌘4, copying a screenshot of the selected area to the clipboard. Then try `escape` to exit. Please note the order of the modifiers doesn't matter.
|
||||
|
||||
Say any combination of modifiers, symbols, alphabet, numbers and function keys to execute keyboard shortcuts. Modifier keys can be tapped using `press`, for example `press control` taps the Control (⌃) key by itself.
|
||||
|
||||
### Symbols
|
||||
|
||||
Some symbols are defined in [keys.py](core/keys/keys.py#L144), so you can say, e.g. `control colon` to press those keys.
|
||||
|
||||
Multi-character punctuation (e.g., ellipses) is defined in [symbols.talon](plugin/symbols/symbols.talon).
|
||||
|
||||
### Formatters
|
||||
|
||||
Formatters allow you to insert words with consistent capitalization and punctuation. `help format` displays available formatters with examples of their output when followed by `one two three`.
|
||||
|
||||
Try using a formatter by saying `snake hello world`. This inserts "hello_world".
|
||||
|
||||
Multiple formatters can be chained together — for example, `dubstring snake hello world` inserts "hello_world".
|
||||
|
||||
Prose formatters (marked with \* in the help window) preserve hyphens and apostrophes. Non-prose (code) formatters strip punctuation instead, for example to generate a valid variable name. `title how's it going` inserts "How's It Going"; `hammer how's it going` inserts "HowsItGoing".
|
||||
|
||||
Reformat existing text with one or more formatters by selecting it, then saying the formatter name(s) followed by `that`. Say `help reformat` to display how each formatter reformats `one_two_three`.
|
||||
|
||||
Formatter names (snake, dubstring) are defined [here](core/text/formatters.py#L245). Formatter-related commands are defined in [text.talon](core/text/text.talon#L8).
|
||||
|
||||
### Mouse commands
|
||||
|
||||
See [mouse.talon](plugin/mouse/mouse.talon) for commands to click, drag, scroll, and use an eye tracker. To use a grid to click at a certain location on the screen, see [mouse_grid](core/mouse_grid).
|
||||
|
||||
### Generic editing commands
|
||||
|
||||
Editing commands in [edit.talon](core/edit/edit.talon) are global. Commands such as `go word left` will work in any text box that uses standard platform text navigation conventions.
|
||||
|
||||
### Repeating commands
|
||||
|
||||
Voice commands for repeating commands are defined in [repeater.talon](plugin/repeater/repeater.talon).
|
||||
|
||||
Say `go up fifth` or `go up five times` to go up five lines. `select up third` will press Shift+Up three times to select several lines of text.
|
||||
|
||||
### Window management
|
||||
|
||||
Global window managment commands are defined in [window_management.talon](core/windows_and_tabs/window_management.talon).
|
||||
|
||||
- `running list` toggles a window displaying words you can say to switch to running applications. To customize the spoken forms for an app (or hide an app entirely from the list), edit the `app_name_overrides_<platform>.csv` files in the [core/app_switcher](core/app_switcher) directory.
|
||||
- `focus chrome` will focus the Chrome application.
|
||||
- `launch music` will launch the music application. Note this is currently only implemented on macOS.
|
||||
|
||||
### Screenshot commands
|
||||
|
||||
See [screenshot.talon](plugin/screenshot/screenshot.talon).
|
||||
|
||||
### Programming languages
|
||||
|
||||
Specific programming languages may be activated by voice commands, or via title tracking.
|
||||
|
||||
Activating languages via commands will enable the commands globally, e.g. they'll work in any application. This will also disable the title tracking method (code.language in .talon files) until the "clear language modes" voice command is used.
|
||||
|
||||
Commands for enabling languages are defined in [language_modes.talon](core/modes/language_modes.talon).
|
||||
|
||||
By default, title tracking activates languages in supported applications such as VSCode, Visual Studio (requires plugin), and Notepad++.
|
||||
|
||||
To enable title tracking for your application:
|
||||
|
||||
1. Ensure the active filename (including extension) is included in the window title.
|
||||
2. Implement the required Talon-defined `filename` action to correctly extract the filename from the window title. See the [Visual Studio Code implementation](apps/vscode/vscode.py#L137-L153) for an example.
|
||||
|
||||
Python, C#, Talon and JavaScript language support is broken up into multiple tags in an attempt to standardize common voice commands for features available across languages. Each tag is defined in a .talon file named after a `user.code_` tag (e.g., `user.code_functions` → `functions.talon`) containing voice commands and a Python file declaring the actions that should be implemented by each concrete language implementation to support the voice commands. These files include:
|
||||
|
||||
- `lang/tags/comment_block.{talon,py}` - block comments (e.g., C++'s `/* */`)
|
||||
- `lang/tags/comment_documentation.{talon,py}` - documentation comments (e.g., Java's `/** */`)
|
||||
- `lang/tags/comment_line.{talon,py}` - line comments (e.g., Python's `#`)
|
||||
- `lang/tags/data_null.{talon,py}` - null & null checks (e.g., Python's `None`)
|
||||
- `lang/tags/data_bool.{talon,py}` - booleans (e.g., Haskell's `True`)
|
||||
- `lang/tags/functions.{talon,py}` - functions and definitions
|
||||
- `lang/tags/functions_common.{talon,py}` - common functions (also includes a GUI for picking functions)
|
||||
- `lang/tags/imperative.{talon,py}` - statements (e.g., `if`, `while`, `switch`)
|
||||
- `lang/tags/libraries.{talon,py}` - libraries and imports
|
||||
- `lang/tags/libraries_gui.{talon,py}` - graphical helper for common libraries
|
||||
- `lang/tags/object_oriented.{talon,py}` - objects and classes (e.g., `this`)
|
||||
- `lang/tags/operators_array.{talon,py}` - array operators (e.g., Ruby's `x[0]`)
|
||||
- `lang/tags/operators_assignment.{talon,py}` - assignment operators (e.g., C++'s `x += 5`)
|
||||
- `lang/tags/operators_bitwise.{talon,py}` - bitwise operators (e.g., C's `x >> 1`)
|
||||
- `lang/tags/operators_lambda.{talon,py}` - anonymous functions (e.g., JavaScript's `x => x + 1`)
|
||||
- `lang/tags/operators_math.{talon,py}` - numeric, comparison, and logical operators
|
||||
- `lang/tags/operators_pointer.{talon,py}` - pointer operators (e.g., C's `&x`)
|
||||
|
||||
Language-specific implementations of the above features are in files named `lang/{your-language}/{your-language}.py`.
|
||||
|
||||
To add support for a new language, ensure appropriate extension is added/uncommented in the [`language_extensions` dictionary in language_modes.py](core/modes/language_modes.py#L9). Then create the following files:
|
||||
|
||||
- `lang/{your-language}/{your-language}.py`
|
||||
- `lang/{your-language}/{your-language}.talon`
|
||||
|
||||
Activate the appropriate tags in `{your-language}.talon` and implement the corresponding actions in `{your-language}.py`, following existing language implementations. Put additional voice commands for your language (not shared with other languages) in `{your-language}.talon`.
|
||||
|
||||
## File manager commands
|
||||
|
||||
For the following file manager commands to work, your file manager must display the full folder path in the title bar. tags/file_manager/file_manager.talon
|
||||
|
||||
For the Mac Finder, run this command in Terminal to display the full path in the window title:
|
||||
|
||||
```
|
||||
defaults write com.apple.finder _FXShowPosixPathInTitle -bool YES
|
||||
```
|
||||
|
||||
For Windows Explorer, [follow these directions](https://www.howtogeek.com/121218/beginner-how-to-make-explorer-always-show-the-full-path-in-windows-8/).
|
||||
|
||||
For the Windows command line, the `refresh title` command will force the title to the current directory, and all directory commands (`follow 1`) will automatically update the title.
|
||||
|
||||
Notes:
|
||||
|
||||
- Both Windows Explorer and Finder hide certain files and folders by default, so it's often best to use the imgui to list the options before issuing commands.
|
||||
|
||||
- If there no hidden files or folders, and the items are displayed in alphabetical order, you can typically issue the `follow <number>`, `file <number>` and `open <number>` commands based on the displayed order.
|
||||
|
||||
To implement support for a new program, implement the relevant file manager actions for your application and assert the `user.file_manager` tag. There are a number of example implementations in the repository. [Finder](apps/finder/finder.py) is a good example to copy and mdoify.
|
||||
|
||||
## Terminal commands
|
||||
|
||||
Many terminal applications are supported out of the box, but you may not want all the commands enabled.
|
||||
|
||||
To use command sets in your terminal applications, enable/disable the corresponding tags in the terminal application-specific .talon file.
|
||||
|
||||
```
|
||||
tag(): user.file_manager
|
||||
tag(): user.git
|
||||
tag(): user.kubectl
|
||||
tag(): user.tabs
|
||||
```
|
||||
|
||||
For instance, kubectl commands (kubernetes) aren't relevant to everyone.
|
||||
|
||||
Note also that while some of the command sets associated with these tags are defined in talon files within [tags](tags), others, like git, are defined within [apps](apps). Commands for tabs are defined in [tabs.talon](core/windows_and_tabs/tabs.talon).
|
||||
|
||||
### Unix utilities
|
||||
|
||||
If you have a Unix (e.g. macOS) or Linux computer, you can enable support for a number of
|
||||
common terminal utilities like `cat`, `tail`, or `grep` by uncommenting the following
|
||||
line in [unix_shell.py](tags/terminal/unix_shell.py):
|
||||
|
||||
```
|
||||
# ctx.tags = ["user.unix_utilities"]
|
||||
```
|
||||
|
||||
Once you have uncommented the line, you can customize your utility commands by editing
|
||||
`tags/terminal/unix_utility.talon-list`.
|
||||
|
||||
## Jetbrains commands
|
||||
|
||||
For Jetbrains commands to work you must install https://plugins.jetbrains.com/plugin/10504-voice-code-idea
|
||||
into each editor.
|
||||
|
||||
## Additional commands
|
||||
|
||||
There are other commands not described fully within this file. As an overview:
|
||||
|
||||
- The apps folder has command sets for use within different applications
|
||||
- The core folder has various commands described [here](core/README.md)
|
||||
- The lang folder has commands for writing [programming languages](#programming-languages)
|
||||
- The plugin folder has various commands described [here](plugin/README.md)
|
||||
- The tags folder has various other commands, such as using a browser, navigating a filesystem in terminal, and managing multiple cursors
|
||||
|
||||
## Settings
|
||||
|
||||
Several options are configurable via a [single settings file](settings.talon) out of the box. Any setting can be made context specific as needed (e.g., per-OS, per-app, etc).
|
||||
|
||||
The most commonly adjusted settings are probably
|
||||
|
||||
- `imgui.scale` to improve the visibility of all imgui-based windows (help, history, etc). This is simply a scale factor, 1.3 = 130%.
|
||||
|
||||
- `user.help_max_command_lines_per_page` and `user.help_max_contexts_per_page` to ensure all help information is visible.
|
||||
|
||||
- `user.mouse_wheel_down_amount` and `user.mouse_continuous_scroll_amount` for adjusting the scroll amounts for the various scroll commands.
|
||||
|
||||
## Customizing words and lists
|
||||
|
||||
Most lists of words are provided as Talon list files, with an extension of `.talon-list`. Read about the syntax of these files [on the Talon wiki](https://talon.wiki/Customization/talon_lists).
|
||||
|
||||
Some lists with multiple spoken forms/alternatives are instead provided as CSV files. Some are in the `settings` folder and are not created until you launch Talon with `community` installed.
|
||||
|
||||
You can customize common Talon list and CSV files with voice commands: say the word `customize` followed by `abbreviations`, `additional words`, `alphabet`, `homophones`, `search engines`, `Unix utilities`, `websites` or `words to replace`. These open the file in a text editor and move the insertion point to the bottom of the file so you can add to it.
|
||||
|
||||
You can also add words to the vocabulary or replacements (words_to_replace) by using the commands in [edit_vocabulary.talon](core/vocabulary/edit_vocabulary.talon).
|
||||
|
||||
## 💡 Tip: Overriding cleanly
|
||||
|
||||
You can override Talon lists by creating a new `.talon-list` file of your own, rather than changing the existing list in the repository.
|
||||
This reduces how much manual `git merge`-ing you'll have to do in the future, when you go to merge new versions of this repository (colloquially called "upstream") with your local changes. This is because _new_ files you create will almost never conflict with upstream changes, whereas changing an existing file (especially hot spots, like commonly-customized lists) frequently do.
|
||||
Your override files can even live outside of the `community` repository (anywhere in the Talon user directory), if you prefer, further simplifying merging.
|
||||
To do so, simply create a `.talon-list` file with a more specific [context header](https://talon.wiki/Customization/talon-files#context-header) than the default. (For example, `lang: en` or `os: mac` main). Talon ensures that the most specific header (your override file) wins.
|
||||
|
||||
For example, to override `user.modifier_key`, you could create `modifier_keys_MYNAME.talon`:
|
||||
|
||||
```talon
|
||||
list: user.modifier_key
|
||||
language: en
|
||||
-
|
||||
|
||||
# My preferred modifier keys
|
||||
rose: cmd
|
||||
troll: control
|
||||
shift: shift
|
||||
alt: alt
|
||||
```
|
||||
|
||||
## Other Talon user file sets
|
||||
|
||||
In addition to this repo, there are [other Talon user file sets](https://talon.wiki/talon_user_file_sets/) containing additional commands that you may want to experiment with if you're feeling adventurous 😊. Many of them are meant to be used alongside `community`, but a few of them are designed as replacements. If it's not clear which, please file an issue against the given GitHub repository for that user file set!
|
||||
|
||||
# Collaborators
|
||||
|
||||
This repository is now officially a team effort. The following contributors have direct access:
|
||||
|
||||
- @dwiel
|
||||
- @fidgetingbits
|
||||
- @knausj85
|
||||
- @rntz
|
||||
- @splondike
|
||||
- @pokey
|
||||
|
||||
Collaborators will reply to issues and pull requests as time and health permits. Please be patient.
|
||||
|
||||
## Guidelines for collaborators
|
||||
|
||||
1. Collaborators prioritize their health and their personal/professional needs first. Their time commitment to this effort is limited.
|
||||
2. For "minor" fixes and improvements/bugs/new apps, collaborators are free to contribute without any review
|
||||
3. For "significant" new development and refactors, collaborators should seek appropriate input and reviews from each-other. Collaborators are encouraged to open a discussion before committing their time to any major effort.
|
||||
|
||||
# Contributing
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for our guidelines for contributors
|
||||
|
||||
## Automatic formatting/linters
|
||||
|
||||
This repository uses [`pre-commit`](https://pre-commit.com/) to run and manage its formatters/linters. Running these yourself is optional. If you wish to do so, first [install](https://pre-commit.com/#install) `pre-commit`:
|
||||
|
||||
```bash
|
||||
$ pip install pre-commit
|
||||
```
|
||||
|
||||
You then have a few options as to when to run it:
|
||||
|
||||
- Run yourself at any time on your locally changed files: `pre-commit run`
|
||||
- Run yourself on all files in the repository: `pre-commit run --all-files`
|
||||
- Run automatically on your PRs (fixes will be pushed automatically to your branch):
|
||||
- Visit https://pre-commit.ci/ and authorize the app to connect to your `community` fork.
|
||||
- Set up an editor hook to run on save:
|
||||
- You could follow the instructions for [Black](https://black.readthedocs.io/en/stable/integrations/editors.html), which are well written; simply replace `black <path>` with `pre-commit run --files <file>`.
|
||||
- It's more performant to only reformat the specific file you're editing, rather than all changed files.
|
||||
- Install a git pre-commit hook with `pre-commit install` (optional)
|
||||
- This essentially runs `pre-commit run` automatically before creating local commits, applying formatters/linters on all changed files. If it "fails", the commit will be blocked.
|
||||
- Note that because many of the rules automatically apply fixes, typically you just need to stage the changes that they made, then reattempt your commit.
|
||||
- Whether to use the hook comes down to personal taste. If you like to make many small incremental "work" commits developing a feature, it may be too much overhead.
|
||||
|
||||
If you run into setup difficulty with `pre-commit`, you might want to ensure that you have a modern Python 3 local environment first. [pyenv](https://github.com/pyenv/pyenv) is good way to install such Python versions without affecting your system Python (recommend installing 3.9 to match Talon's current version). On macOS you can also `brew install pre-commit`.
|
||||
|
||||
## Automated tests
|
||||
|
||||
There are a number of automated unit tests in the repository. These are all run _outside_ of the Talon environment (e.g. we don't have access to Talon's window management APIs). These make use of a set of stubbed out Talon APIs in `test/stubs/` and a bit of class loader trickery in `conftest.py`.
|
||||
|
||||
To run the test suite you just need to install the `pytest` python package in to a non-Talon Python runtime you want to use for tests (i.e. don't install in the `~/.talon/.venv directory`). You can then just run the `pytest` command from the repository root to execute all the tests.
|
||||
|
||||
## Talon documentation
|
||||
|
||||
For official documentation on Talon's API and features, please visit https://talonvoice.com/docs/.
|
||||
|
||||
For community-generated documentation on Talon, please visit https://talon.wiki/.
|
||||
|
||||
## Alternate installation method: Zip file
|
||||
|
||||
It is possible to install `community` by downloading and extracting a zip file instead of using `git`. Note that this approach is discouraged, because it makes it more difficult to keep track of any changes you may make to your copy of the files.
|
||||
|
||||
If you wish to install `community` by downloading and extracting a zip file, proceed as follows:
|
||||
|
||||
1. Download the [zip archive of community](https://github.com/talonhub/community/archive/refs/heads/main.zip).
|
||||
1. Extract the files. If you don’t know how to extract zip files, a quick google search for "extract zip files" may be helpful.
|
||||
1. Place these extracted files inside the `user` folder of the Talon Home directory. You can find this folder by right-clicking the Talon icon in the taskbar (Windows) or clicking the Talon icon in the menu bar (Mac), clicking Scripting > Open ~/talon, and navigating to `user`.
|
6
talon/user/community/apps/1password/1password.talon
Normal file
6
talon/user/community/apps/1password/1password.talon
Normal file
|
@ -0,0 +1,6 @@
|
|||
app: one_password
|
||||
-
|
||||
password new: user.password_new()
|
||||
password dup: user.password_duplicate()
|
||||
password edit: user.password_edit()
|
||||
password delete: user.password_delete()
|
|
@ -0,0 +1,4 @@
|
|||
#todo: tags
|
||||
-
|
||||
password fill: user.password_fill()
|
||||
password show: user.password_show()
|
31
talon/user/community/apps/1password/1password_mac.py
Normal file
31
talon/user/community/apps/1password/1password_mac.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
|
||||
# i don't see a need to restrict the app here, this just defines the actions
|
||||
# each app can support appropriate voice commands as needed
|
||||
# the below are for 1password, redefine as needed
|
||||
ctx.matches = r"""
|
||||
os: mac
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def password_fill():
|
||||
actions.key("cmd-\\")
|
||||
|
||||
def password_show():
|
||||
actions.key("cmd-alt-\\")
|
||||
|
||||
def password_new():
|
||||
actions.key("cmd-i")
|
||||
|
||||
def password_duplicate():
|
||||
actions.key("cmd-d")
|
||||
|
||||
def password_edit():
|
||||
actions.key("cmd-e")
|
||||
|
||||
def password_delete():
|
||||
actions.key("cmd-backspace")
|
31
talon/user/community/apps/1password/1password_win.py
Normal file
31
talon/user/community/apps/1password/1password_win.py
Normal file
|
@ -0,0 +1,31 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
|
||||
# i don't see a need to restrict the app here, this just defines the actions
|
||||
# each app can support appropriate voice commands as needed
|
||||
# the below are for 1password, redefine as needed
|
||||
ctx.matches = r"""
|
||||
os: windows
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def password_fill():
|
||||
actions.key("ctrl-\\\\")
|
||||
|
||||
def password_show():
|
||||
actions.key("alt-ctrl-\\\\")
|
||||
|
||||
def password_new():
|
||||
actions.key("ctrl-n")
|
||||
|
||||
def password_duplicate():
|
||||
actions.key("ctrl-d")
|
||||
|
||||
def password_edit():
|
||||
actions.key("ctrl-e")
|
||||
|
||||
def password_delete():
|
||||
actions.key("ctrl-delete")
|
29
talon/user/community/apps/1password/password_manager.py
Normal file
29
talon/user/community/apps/1password/password_manager.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
from talon import Module
|
||||
|
||||
mod = Module()
|
||||
|
||||
# 1password
|
||||
mod.apps.one_password = "app.bundle: com.agilebits.onepassword7"
|
||||
mod.apps.one_password = "app.name: 1Password for Windows desktop"
|
||||
mod.apps.one_password = "app.name: 1Password.exe"
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def password_fill():
|
||||
"""fill the password"""
|
||||
|
||||
def password_show():
|
||||
"""show the password"""
|
||||
|
||||
def password_new():
|
||||
"""New password"""
|
||||
|
||||
def password_duplicate():
|
||||
"""Duplicate password"""
|
||||
|
||||
def password_edit():
|
||||
"""Edit password"""
|
||||
|
||||
def password_delete():
|
||||
"""Delete password"""
|
15
talon/user/community/apps/README.md
Normal file
15
talon/user/community/apps/README.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Web apps and browser extensions
|
||||
|
||||
Some of the Talon files for web apps (e.g. `apps/github/github_web.talon`) use a `browser.host` matcher. These talon files should work out of the box for Safari, Chrome, Brave, on Mac, but require additional configuration on other browsers/operating systems.
|
||||
|
||||
`community` is set up so that if a URL is found in the titlebar of an application matching the 'browser' tag it will be used to populate the browser.host matcher (see `code/browser.py`). This probably means that you will need an extension to make the browser.host based scripts work.
|
||||
|
||||
Browser extensions that can add the protocol and hostname or even the entire URL to the window title:
|
||||
|
||||
Firefox:
|
||||
|
||||
- https://addons.mozilla.org/en-US/firefox/addon/keepass-helper-url-in-title/
|
||||
|
||||
Chrome:
|
||||
|
||||
- https://chrome.google.com/webstore/detail/url-in-title/ignpacbgnbnkaiooknalneoeladjnfgb
|
15
talon/user/community/apps/adobe/adobe_acrobat_reader_dc.py
Normal file
15
talon/user/community/apps/adobe/adobe_acrobat_reader_dc.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
from talon import Module
|
||||
|
||||
# --- App definition ---
|
||||
mod = Module()
|
||||
mod.apps.adobe_acrobat_reader_dc = r"""
|
||||
os: windows
|
||||
and app.name: Adobe Acrobat DC
|
||||
os: windows
|
||||
and app.exe: /^acrobat\.exe$/i
|
||||
os: windows
|
||||
and app.name: Adobe Acrobat Reader DC
|
||||
os: windows
|
||||
and app.exe: /^acrord32\.exe$/i
|
||||
"""
|
||||
# TODO: mac context and implementation
|
|
@ -0,0 +1,5 @@
|
|||
app: adobe_acrobat_reader_dc
|
||||
-
|
||||
# Set tags
|
||||
tag(): user.tabs
|
||||
tag(): user.pages
|
|
@ -0,0 +1,61 @@
|
|||
from talon import Context, actions
|
||||
|
||||
# Context matching
|
||||
ctx = Context()
|
||||
ctx.matches = """
|
||||
os: windows
|
||||
app: adobe_acrobat_reader_dc
|
||||
"""
|
||||
|
||||
|
||||
# --- Implement actions ---
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
# app.tabs
|
||||
def tab_next():
|
||||
actions.key("ctrl-tab")
|
||||
|
||||
def tab_previous():
|
||||
actions.key("ctrl-shift-tab")
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def zoom_in():
|
||||
actions.key("ctrl-0") # in german version
|
||||
|
||||
def zoom_out():
|
||||
actions.key("ctrl-1") # in german version TODO: differentiate languages
|
||||
|
||||
def zoom_reset():
|
||||
actions.key("ctrl-2")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# user.pages
|
||||
def page_current():
|
||||
actions.key("ctrl-shift-n")
|
||||
page = actions.edit.selected_text()
|
||||
actions.key("tab:2 enter")
|
||||
return int(page)
|
||||
|
||||
def page_next():
|
||||
actions.key("ctrl-pagedown")
|
||||
|
||||
def page_previous():
|
||||
actions.key("ctrl-pageup")
|
||||
|
||||
def page_jump(number: int):
|
||||
actions.key("ctrl-shift-n")
|
||||
actions.insert(str(number))
|
||||
actions.key("enter")
|
||||
|
||||
def page_final():
|
||||
actions.key("end")
|
||||
|
||||
def page_rotate_right():
|
||||
actions.key("shift-ctrl-0")
|
||||
|
||||
def page_rotate_left():
|
||||
actions.key("shift-ctrl-1")
|
13
talon/user/community/apps/amethyst/amethyst.talon
Normal file
13
talon/user/community/apps/amethyst/amethyst.talon
Normal file
|
@ -0,0 +1,13 @@
|
|||
user.running: amethyst
|
||||
-
|
||||
window next: key("alt-shift-j")
|
||||
window previous: key("alt-shift-k")
|
||||
# window move desk: key("ctrl-alt-shift-h")
|
||||
window full: key("alt-shift-d")
|
||||
window float: key(alt-shift-t)
|
||||
window tall: key("alt-shift-a")
|
||||
window middle: key("alt-shift-`")
|
||||
window move main: key("alt-shift-enter")
|
||||
window grow: key("alt-shift-l")
|
||||
window shrink: key("alt-shift-h")
|
||||
window reevaluate: key("alt-shift-z")
|
9
talon/user/community/apps/anaconda/anaconda.py
Normal file
9
talon/user/community/apps/anaconda/anaconda.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from talon import Context, Module
|
||||
|
||||
mod = Module()
|
||||
mod.tag("anaconda", desc="tag for enabling anaconda commands in your terminal")
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
tag: user.anaconda
|
||||
"""
|
40
talon/user/community/apps/anaconda/anaconda.talon
Normal file
40
talon/user/community/apps/anaconda/anaconda.talon
Normal file
|
@ -0,0 +1,40 @@
|
|||
tag: terminal
|
||||
and tag: user.anaconda
|
||||
-
|
||||
anaconda: "conda "
|
||||
anaconda help: "conda --help\n"
|
||||
anaconda version: "conda --version\n"
|
||||
|
||||
anaconda environment list: "conda env list\n"
|
||||
anaconda environment create: "conda env create -f "
|
||||
anaconda environment remove: "conda env remove -n "
|
||||
|
||||
anaconda activate: "conda activate "
|
||||
anaconda clean: "conda clean "
|
||||
anaconda compare: "conda compare "
|
||||
anaconda config: "conda config "
|
||||
anaconda create: "conda create "
|
||||
anaconda info: "conda info "
|
||||
anaconda init: "conda init "
|
||||
anaconda install: "conda install "
|
||||
anaconda list: "conda list "
|
||||
anaconda package: "conda package "
|
||||
anaconda remove: "conda remove "
|
||||
anaconda uninstall: "conda uninstall "
|
||||
anaconda run: "conda run "
|
||||
anaconda search: "conda search "
|
||||
anaconda update: "conda update "
|
||||
anaconda upgrade: "conda upgrade "
|
||||
|
||||
anaconda build: "conda build "
|
||||
anaconda convert: "conda convert "
|
||||
anaconda debug: "conda debug "
|
||||
anaconda develop: "conda develop "
|
||||
anaconda environment: "conda env "
|
||||
anaconda index: "conda index "
|
||||
anaconda inspect: "conda inspect "
|
||||
anaconda metapackage: "conda metapackage "
|
||||
anaconda render: "conda render "
|
||||
anaconda server: "conda server "
|
||||
anaconda skeleton: "conda skeleton "
|
||||
anaconda verify: "conda verify "
|
21
talon/user/community/apps/apple_notes/apple_notes.py
Normal file
21
talon/user/community/apps/apple_notes/apple_notes.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: notes
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def zoom_in():
|
||||
actions.key("shift-cmd->")
|
||||
|
||||
def zoom_out():
|
||||
actions.key("shift-cmd-<")
|
||||
|
||||
def zoom_reset():
|
||||
actions.key("shift-cmd-0")
|
||||
|
||||
def indent_less():
|
||||
actions.key("cmd-[")
|
32
talon/user/community/apps/apple_notes/apple_notes.talon
Normal file
32
talon/user/community/apps/apple_notes/apple_notes.talon
Normal file
|
@ -0,0 +1,32 @@
|
|||
os: mac
|
||||
and app: notes
|
||||
-
|
||||
|
||||
new note: key(cmd-n)
|
||||
duplicate note: key(cmd-d)
|
||||
new folder: key(shift-cmd-n)
|
||||
toggle folders: key(alt-cmd-s)
|
||||
show main: key(cmd-0)
|
||||
list view: key(cmd-1)
|
||||
gallery view: key(cmd-2)
|
||||
toggle attachments: key(cmd-3)
|
||||
find all: key(alt-cmd-f)
|
||||
print note: key(cmd-p)
|
||||
attach file: key(shift-cmd-a)
|
||||
create link: key(cmd-k)
|
||||
insert table: key(alt-cmd-t)
|
||||
apply title: key(shift-cmd-t)
|
||||
apply heading: key(shift-cmd-h)
|
||||
apply subheading: key(shift-cmd-j)
|
||||
apply body: key(shift-cmd-b)
|
||||
apply mono: key(shift-cmd-m)
|
||||
apply bullet: key(shift-cmd-7)
|
||||
apply dash: key(shift-cmd-8)
|
||||
apply number: key(shift-cmd-9)
|
||||
apply checklist: key(shift-cmd-l)
|
||||
increase font: key(cmd-+)
|
||||
decrease font: key(cmd--)
|
||||
line break: key(ctrl-enter)
|
||||
mark: key(shift-cmd-u)
|
||||
drag [line] down: key('ctrl-cmd-down')
|
||||
drag [line] up: key('ctrl-cmd-up')
|
90
talon/user/community/apps/apple_terminal/apple_terminal.py
Normal file
90
talon/user/community/apps/apple_terminal/apple_terminal.py
Normal file
|
@ -0,0 +1,90 @@
|
|||
import os
|
||||
|
||||
from talon import Context, actions, ui
|
||||
|
||||
# TODO: fit this to terminal.py
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: apple_terminal
|
||||
"""
|
||||
directories_to_remap = {}
|
||||
directories_to_exclude = {}
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def delete_line():
|
||||
actions.key("ctrl-u")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def file_manager_current_path():
|
||||
title = ui.active_window().title
|
||||
|
||||
# take the first split for the zsh-based terminal
|
||||
if " — " in title:
|
||||
title = title.split(" — ")[0]
|
||||
|
||||
if "~" in title:
|
||||
title = os.path.expanduser(title)
|
||||
|
||||
if title in directories_to_remap:
|
||||
title = directories_to_remap[title]
|
||||
|
||||
if title in directories_to_exclude:
|
||||
title = None
|
||||
|
||||
return title
|
||||
|
||||
def file_manager_show_properties():
|
||||
"""Shows the properties for the file"""
|
||||
|
||||
def file_manager_open_directory(path: str):
|
||||
"""opens the directory that's already visible in the view"""
|
||||
actions.insert("cd ")
|
||||
path = f'"{path}"'
|
||||
actions.insert(path)
|
||||
actions.key("enter")
|
||||
|
||||
# jtk - refresh title isn't necessary since the apple terminal does it for us
|
||||
# actions.user.file_manager_refresh_title()
|
||||
|
||||
def file_manager_open_parent():
|
||||
actions.insert("cd ..")
|
||||
actions.key("enter")
|
||||
|
||||
def file_manager_select_directory(path: str):
|
||||
"""selects the directory"""
|
||||
actions.insert(path)
|
||||
|
||||
def file_manager_new_folder(name: str):
|
||||
"""Creates a new folder in a gui filemanager or inserts the command to do so for terminals"""
|
||||
name = f'"{name}"'
|
||||
|
||||
actions.insert("mkdir " + name)
|
||||
|
||||
def file_manager_open_file(path: str):
|
||||
"""opens the file"""
|
||||
actions.insert(path)
|
||||
actions.key("enter")
|
||||
|
||||
def file_manager_select_file(path: str):
|
||||
"""selects the file"""
|
||||
actions.insert(path)
|
||||
|
||||
def file_manager_refresh_title():
|
||||
return
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class app_actions:
|
||||
# other tab functions should already be implemented in
|
||||
# code/platforms/mac/app.py
|
||||
|
||||
def tab_previous():
|
||||
actions.key("ctrl-shift-tab")
|
||||
|
||||
def tab_next():
|
||||
actions.key("ctrl-tab")
|
|
@ -0,0 +1,25 @@
|
|||
app: apple_terminal
|
||||
-
|
||||
# makes the commands in terminal.talon available
|
||||
tag(): terminal
|
||||
|
||||
# use readline keybindings for various editing commands
|
||||
tag(): user.readline
|
||||
|
||||
# activates the implementation of the commands/functions in terminal.talon
|
||||
tag(): user.generic_unix_shell
|
||||
|
||||
# makes commands for certain applications available
|
||||
# you can deactivate them if you do not use the application
|
||||
tag(): user.git
|
||||
tag(): user.anaconda
|
||||
tag(): user.kubectl
|
||||
|
||||
# TODO: explain
|
||||
tag(): user.tabs
|
||||
tag(): user.file_manager
|
||||
|
||||
suspend: key(ctrl-z)
|
||||
resume:
|
||||
insert("fg")
|
||||
key(enter)
|
34
talon/user/community/apps/arc/arc.py
Normal file
34
talon/user/community/apps/arc/arc.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
from talon import Context, Module, actions, app
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
mod.apps.arc = "app.name: Arc"
|
||||
mod.apps.arc = """
|
||||
os: mac
|
||||
app.bundle: company.thebrowser.Browser
|
||||
|
||||
"""
|
||||
ctx.matches = r"""
|
||||
app: arc
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def tab_close_wrapper():
|
||||
actions.sleep("180ms")
|
||||
actions.app.tab_close()
|
||||
|
||||
def command_search(command: str = ""):
|
||||
actions.key("cmd-l")
|
||||
if command != "":
|
||||
actions.sleep("200ms")
|
||||
actions.insert(command)
|
||||
|
||||
|
||||
@ctx.action_class("browser")
|
||||
class BrowserActions:
|
||||
def show_extensions():
|
||||
actions.app.tab_open()
|
||||
actions.browser.go("arc://extensions")
|
6
talon/user/community/apps/arc/arc_mac.talon
Normal file
6
talon/user/community/apps/arc/arc_mac.talon
Normal file
|
@ -0,0 +1,6 @@
|
|||
app: arc
|
||||
os: mac
|
||||
-
|
||||
tag(): browser
|
||||
tag(): user.tabs
|
||||
tag(): user.command_search
|
8
talon/user/community/apps/arc/little-arc_mac.talon
Normal file
8
talon/user/community/apps/arc/little-arc_mac.talon
Normal file
|
@ -0,0 +1,8 @@
|
|||
user.running: arc
|
||||
os: mac
|
||||
-
|
||||
# This assumes that you have not disabled Little Arc
|
||||
little arc [<user.text>]:
|
||||
key("cmd-alt-n")
|
||||
sleep(200ms)
|
||||
insert(user.text or "")
|
39
talon/user/community/apps/atril/atril.py
Normal file
39
talon/user/community/apps/atril/atril.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
# --- App definition ---
|
||||
mod = Module()
|
||||
mod.apps.atril = """
|
||||
os: linux
|
||||
and app.name: Atril
|
||||
"""
|
||||
|
||||
# Context matching
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: atril
|
||||
"""
|
||||
|
||||
|
||||
# --- Implement actions ---
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# user.pages
|
||||
def page_current():
|
||||
actions.key("ctrl-l")
|
||||
page = actions.edit.selected_text()
|
||||
actions.key("right escape")
|
||||
return int(page)
|
||||
|
||||
def page_next():
|
||||
actions.key("ctrl-pagedown")
|
||||
|
||||
def page_previous():
|
||||
actions.key("ctrl-pageup")
|
||||
|
||||
def page_jump(number: int):
|
||||
actions.key("ctrl-l")
|
||||
actions.insert(str(number))
|
||||
actions.key("enter")
|
||||
|
||||
def page_final():
|
||||
actions.key("ctrl-end")
|
4
talon/user/community/apps/atril/atril.talon
Normal file
4
talon/user/community/apps/atril/atril.talon
Normal file
|
@ -0,0 +1,4 @@
|
|||
app: atril
|
||||
-
|
||||
# Set tags
|
||||
tag(): user.pages
|
32
talon/user/community/apps/brave/brave.py
Normal file
32
talon/user/community/apps/brave/brave.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
from talon import Context, Module, actions, app
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
mod.apps.brave = "app.name: Brave Browser"
|
||||
mod.apps.brave = "app.name: Brave-browser"
|
||||
mod.apps.brave = r"""
|
||||
os: windows
|
||||
and app.exe: /^brave\.exe$/i
|
||||
os: linux
|
||||
and app.exe: brave
|
||||
os: mac
|
||||
and app.bundle: com.brave.Browser
|
||||
"""
|
||||
ctx.matches = r"""
|
||||
app: brave
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def tab_close_wrapper():
|
||||
actions.sleep("180ms")
|
||||
actions.app.tab_close()
|
||||
|
||||
|
||||
@ctx.action_class("browser")
|
||||
class BrowserActions:
|
||||
def show_extensions():
|
||||
actions.app.tab_open()
|
||||
actions.browser.go("brave://extensions")
|
4
talon/user/community/apps/brave/brave.talon
Normal file
4
talon/user/community/apps/brave/brave.talon
Normal file
|
@ -0,0 +1,4 @@
|
|||
app: brave
|
||||
-
|
||||
tag(): browser
|
||||
tag(): user.tabs
|
19
talon/user/community/apps/calibre/calibre.py
Normal file
19
talon/user/community/apps/calibre/calibre.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from talon import Module
|
||||
|
||||
# --- App definition ---
|
||||
mod = Module()
|
||||
mod.apps.calibre = r"""
|
||||
os: windows
|
||||
and app.name: calibre.exe
|
||||
os: windows
|
||||
and app.exe: /^calibre\.exe$/i
|
||||
os: windows
|
||||
and app.name: calibre-parallel.exe
|
||||
os: windows
|
||||
and app.exe: /^calibre-parallel\.exe$/i
|
||||
"""
|
||||
mod.apps.calibre = """
|
||||
os: linux
|
||||
app.name: calibre
|
||||
"""
|
||||
# TODO: mac context
|
39
talon/user/community/apps/calibre/calibre_viewer.py
Normal file
39
talon/user/community/apps/calibre/calibre_viewer.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
# --- App definition ---
|
||||
mod = Module()
|
||||
mod.apps.calibre_viewer = """
|
||||
app: calibre
|
||||
title: /E-book viewer$/
|
||||
title: /eBook-Betrachter$/
|
||||
"""
|
||||
|
||||
# Context matching
|
||||
ctx = Context()
|
||||
ctx.matches = """
|
||||
os: windows
|
||||
os: linux
|
||||
app: calibre_viewer
|
||||
"""
|
||||
# TODO: mac implementation
|
||||
|
||||
|
||||
# --- Implement actions ---
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# user.pages
|
||||
def page_next():
|
||||
actions.key("pagedown")
|
||||
|
||||
def page_previous():
|
||||
actions.key("pageup")
|
||||
|
||||
def page_final():
|
||||
actions.key("ctrl-end")
|
||||
|
||||
# user.chapters
|
||||
def chapter_next():
|
||||
actions.key("ctrl-pagedown")
|
||||
|
||||
def chapter_previous():
|
||||
actions.key("ctrl-pageup")
|
5
talon/user/community/apps/calibre/calibre_viewer.talon
Normal file
5
talon/user/community/apps/calibre/calibre_viewer.talon
Normal file
|
@ -0,0 +1,5 @@
|
|||
app: calibre_viewer
|
||||
-
|
||||
# Set tags
|
||||
tag(): user.pages
|
||||
tag(): user.chapters
|
54
talon/user/community/apps/chrome/chrome.py
Normal file
54
talon/user/community/apps/chrome/chrome.py
Normal file
|
@ -0,0 +1,54 @@
|
|||
from talon import Context, Module, actions, app
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
mod.apps.chrome = "app.name: Google Chrome"
|
||||
mod.apps.chrome = r"""
|
||||
os: windows
|
||||
and app.exe: /^chrome\.exe$/i
|
||||
"""
|
||||
mod.apps.chrome = """
|
||||
os: mac
|
||||
app.bundle: com.google.Chrome
|
||||
app.bundle: com.google.Chrome.canary
|
||||
app.bundle: org.chromium.Chromium
|
||||
"""
|
||||
mod.apps.chrome = """
|
||||
os: linux
|
||||
app.exe: chrome
|
||||
app.exe: chromium-browser
|
||||
app.exe: chromium
|
||||
"""
|
||||
mod.apps.chrome = """
|
||||
os: linux
|
||||
and app.name: Google-chrome
|
||||
"""
|
||||
|
||||
ctx.matches = r"""
|
||||
app: chrome
|
||||
"""
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def chrome_mod(key: str):
|
||||
"""Press the specified key with the correct modifier key for the OS"""
|
||||
if app.platform == "mac":
|
||||
actions.key(f"cmd-{key}")
|
||||
else:
|
||||
actions.key(f"ctrl-{key}")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def tab_close_wrapper():
|
||||
actions.sleep("180ms")
|
||||
actions.app.tab_close()
|
||||
|
||||
|
||||
@ctx.action_class("browser")
|
||||
class BrowserActions:
|
||||
def show_extensions():
|
||||
actions.app.tab_open()
|
||||
actions.browser.go("chrome://extensions")
|
14
talon/user/community/apps/chrome/chrome.talon
Normal file
14
talon/user/community/apps/chrome/chrome.talon
Normal file
|
@ -0,0 +1,14 @@
|
|||
app: chrome
|
||||
-
|
||||
tag(): browser
|
||||
tag(): user.tabs
|
||||
|
||||
profile switch: user.chrome_mod("shift-m")
|
||||
|
||||
tab search: user.chrome_mod("shift-a")
|
||||
|
||||
tab search <user.text>$:
|
||||
user.chrome_mod("shift-a")
|
||||
sleep(200ms)
|
||||
insert("{text}")
|
||||
key(down)
|
6
talon/user/community/apps/conemu/conemu.talon
Normal file
6
talon/user/community/apps/conemu/conemu.talon
Normal file
|
@ -0,0 +1,6 @@
|
|||
os: windows
|
||||
app.exe: /^conemu64\.exe$/i
|
||||
-
|
||||
|
||||
tag(): terminal
|
||||
tag(): user.git
|
85
talon/user/community/apps/discord/discord.py
Normal file
85
talon/user/community/apps/discord/discord.py
Normal file
|
@ -0,0 +1,85 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
mod = Module()
|
||||
apps = mod.apps
|
||||
apps.discord = "app.bundle: com.hnc.Discord"
|
||||
apps.discord = "app.name: Discord"
|
||||
apps.discord = "app.name: Discord.exe"
|
||||
apps.discord = """
|
||||
tag: browser
|
||||
browser.host: discord.com
|
||||
"""
|
||||
|
||||
mod.list("discord_destination", desc="discord destination")
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: discord
|
||||
"""
|
||||
|
||||
ctx.lists["user.discord_destination"] = {
|
||||
"user": "@",
|
||||
"voice": "!",
|
||||
"server": "*",
|
||||
}
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class discord_actions:
|
||||
def discord_mentions_last():
|
||||
"""Go up to channel with unread mentions"""
|
||||
|
||||
def discord_mentions_next():
|
||||
"""Go down to channel with unread mentions"""
|
||||
|
||||
def discord_oldest_unread():
|
||||
"""Go to oldest unread message"""
|
||||
|
||||
def discord_toggle_pins():
|
||||
"""Toggle pins popout"""
|
||||
|
||||
def discord_toggle_inbox():
|
||||
"""Toggle inbox popout"""
|
||||
|
||||
def discord_toggle_members():
|
||||
"""Toggle channel member list"""
|
||||
|
||||
def discord_emoji_picker():
|
||||
"""Toggle emoji picker"""
|
||||
|
||||
def discord_gif_picker():
|
||||
"""Toggle gif picker"""
|
||||
|
||||
def discord_sticker_picker():
|
||||
"""Toggle sticker picker"""
|
||||
|
||||
def discord_mark_inbox_read():
|
||||
"""Mark top inbox channel read"""
|
||||
|
||||
def discord_mute():
|
||||
"""Toggle mute"""
|
||||
|
||||
def discord_deafen():
|
||||
"""Toggle deafen"""
|
||||
|
||||
def discord_answer_call():
|
||||
"""Answer incoming call"""
|
||||
|
||||
def discord_decline_call():
|
||||
"""Decline incoming call"""
|
||||
|
||||
def discord_quick_switcher(dest_type: str, dest_search: str):
|
||||
"""Open up the quick switcher, optionally specifying a type of destination"""
|
||||
|
||||
def discord_go_current_call():
|
||||
"""Go to current call"""
|
||||
|
||||
def discord_toggle_dms():
|
||||
"""Toggle between dms and your most recent server"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# Navigation: Channels
|
||||
def messaging_open_channel_picker():
|
||||
actions.user.discord_quick_switcher("#", "")
|
34
talon/user/community/apps/discord/discord.talon
Normal file
34
talon/user/community/apps/discord/discord.talon
Normal file
|
@ -0,0 +1,34 @@
|
|||
app: discord
|
||||
-
|
||||
tag(): user.messaging
|
||||
tag(): user.emoji
|
||||
|
||||
# Navigation: QuickSwitcher
|
||||
{user.discord_destination} [<user.text>]:
|
||||
user.discord_quick_switcher(user.discord_destination, user.text or "")
|
||||
switcher: user.discord_quick_switcher("", "")
|
||||
|
||||
# Navigation: Channels
|
||||
[channel] mentions last: user.discord_mentions_last()
|
||||
[channel] mentions next: user.discord_mentions_next()
|
||||
oldest unread: user.discord_oldest_unread()
|
||||
current call: user.discord_go_current_call()
|
||||
|
||||
# UI
|
||||
toggle pins: user.discord_toggle_pins()
|
||||
toggle inbox: user.discord_toggle_inbox()
|
||||
toggle (members | member list): user.discord_toggle_members()
|
||||
toggle (dee ems | dims): user.discord_toggle_dms()
|
||||
pick emoji: user.discord_emoji_picker()
|
||||
pick (jif | gif | gift): user.discord_gif_picker()
|
||||
pick sticker: user.discord_sticker_picker()
|
||||
|
||||
# Misc
|
||||
mark inbox channel read: user.discord_mark_inbox_read()
|
||||
[toggle] (mute | unmute): user.discord_mute()
|
||||
(mute | unmute) and sleep:
|
||||
user.discord_mute()
|
||||
speech.disable()
|
||||
[toggle] (deafen | undeafen): user.discord_deafen()
|
||||
answer call: user.discord_answer_call()
|
||||
decline call: user.discord_decline_call()
|
96
talon/user/community/apps/discord/discord_mac.py
Normal file
96
talon/user/community/apps/discord/discord_mac.py
Normal file
|
@ -0,0 +1,96 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
os: mac
|
||||
app: discord
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# Navigation: QuickSwitcher
|
||||
def discord_quick_switcher(dest_type: str, dest_search: str):
|
||||
actions.key("cmd-k")
|
||||
actions.insert(dest_type)
|
||||
if dest_search:
|
||||
actions.insert(dest_search)
|
||||
|
||||
# Navigation: Servers
|
||||
def messaging_workspace_previous():
|
||||
actions.key("cmd-alt-up")
|
||||
|
||||
def messaging_workspace_next():
|
||||
actions.key("cmd-alt-down")
|
||||
|
||||
# Navigation: Channels
|
||||
def messaging_channel_previous():
|
||||
actions.key("alt-up")
|
||||
|
||||
def messaging_channel_next():
|
||||
actions.key("alt-down")
|
||||
|
||||
def messaging_unread_previous():
|
||||
actions.key("alt-shift-up")
|
||||
|
||||
def messaging_unread_next():
|
||||
actions.key("alt-shift-down")
|
||||
|
||||
def discord_mentions_last():
|
||||
actions.key("cmd-alt-shift-up")
|
||||
|
||||
def discord_mentions_next():
|
||||
actions.key("cmd-alt-shift-down")
|
||||
|
||||
def discord_oldest_unread():
|
||||
actions.key("shift-pageup")
|
||||
|
||||
# UI
|
||||
def discord_toggle_pins():
|
||||
actions.key("cmd-p")
|
||||
|
||||
def discord_toggle_inbox():
|
||||
actions.key("cmd-i")
|
||||
|
||||
def discord_toggle_members():
|
||||
actions.key("cmd-u")
|
||||
|
||||
def discord_emoji_picker():
|
||||
actions.key("cmd-e")
|
||||
|
||||
def discord_gif_picker():
|
||||
actions.key("cmd-g")
|
||||
|
||||
def discord_sticker_picker():
|
||||
actions.key("cmd-s")
|
||||
|
||||
# Misc
|
||||
def messaging_mark_workspace_read():
|
||||
actions.key("shift-esc")
|
||||
|
||||
def messaging_mark_channel_read():
|
||||
actions.key("esc")
|
||||
|
||||
def messaging_upload_file():
|
||||
actions.key("cmd-shift-u")
|
||||
|
||||
def discord_mark_inbox_read():
|
||||
actions.key("cmd-shift-e")
|
||||
|
||||
def discord_mute():
|
||||
actions.key("cmd-shift-m")
|
||||
|
||||
def discord_deafen():
|
||||
actions.key("cmd-shift-d")
|
||||
|
||||
def discord_answer_call():
|
||||
actions.key("cmd-enter")
|
||||
|
||||
def discord_decline_call():
|
||||
actions.key("esc")
|
||||
|
||||
def discord_go_current_call():
|
||||
actions.key("cmd-alt-a")
|
||||
|
||||
def discord_toggle_dms():
|
||||
actions.key("cmd-alt-right")
|
97
talon/user/community/apps/discord/discord_win.py
Normal file
97
talon/user/community/apps/discord/discord_win.py
Normal file
|
@ -0,0 +1,97 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
os: windows
|
||||
os: linux
|
||||
app: discord
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# Navigation: QuickSwitcher
|
||||
def discord_quick_switcher(dest_type: str, dest_search: str):
|
||||
actions.key("ctrl-k")
|
||||
actions.insert(dest_type)
|
||||
if dest_search:
|
||||
actions.insert(dest_search)
|
||||
|
||||
# Navigation: Servers
|
||||
def messaging_workspace_previous():
|
||||
actions.key("ctrl-alt-up")
|
||||
|
||||
def messaging_workspace_next():
|
||||
actions.key("ctrl-alt-down")
|
||||
|
||||
# Navigation: Channels
|
||||
def messaging_channel_previous():
|
||||
actions.key("alt-up")
|
||||
|
||||
def messaging_channel_next():
|
||||
actions.key("alt-down")
|
||||
|
||||
def messaging_unread_previous():
|
||||
actions.key("alt-shift-up")
|
||||
|
||||
def messaging_unread_next():
|
||||
actions.key("alt-shift-down")
|
||||
|
||||
def discord_mentions_last():
|
||||
actions.key("ctrl-alt-shift-up")
|
||||
|
||||
def discord_mentions_next():
|
||||
actions.key("ctrl-alt-shift-down")
|
||||
|
||||
def discord_oldest_unread():
|
||||
actions.key("shift-pageup")
|
||||
|
||||
# UI
|
||||
def discord_toggle_pins():
|
||||
actions.key("ctrl-p")
|
||||
|
||||
def discord_toggle_inbox():
|
||||
actions.key("ctrl-i")
|
||||
|
||||
def discord_toggle_members():
|
||||
actions.key("ctrl-u")
|
||||
|
||||
def discord_emoji_picker():
|
||||
actions.key("ctrl-e")
|
||||
|
||||
def discord_gif_picker():
|
||||
actions.key("ctrl-g")
|
||||
|
||||
def discord_sticker_picker():
|
||||
actions.key("ctrl-s")
|
||||
|
||||
# Misc
|
||||
def messaging_mark_workspace_read():
|
||||
actions.key("shift-esc")
|
||||
|
||||
def messaging_mark_channel_read():
|
||||
actions.key("esc")
|
||||
|
||||
def messaging_upload_file():
|
||||
actions.key("ctrl-shift-u")
|
||||
|
||||
def discord_mark_inbox_read():
|
||||
actions.key("ctrl-shift-e")
|
||||
|
||||
def discord_mute():
|
||||
actions.key("ctrl-shift-m")
|
||||
|
||||
def discord_deafen():
|
||||
actions.key("ctrl-shift-d")
|
||||
|
||||
def discord_answer_call():
|
||||
actions.key("ctrl-enter")
|
||||
|
||||
def discord_decline_call():
|
||||
actions.key("esc")
|
||||
|
||||
def discord_go_current_call():
|
||||
actions.key("ctrl-shift-alt-v")
|
||||
|
||||
def discord_toggle_dms():
|
||||
actions.key("ctrl-alt-right")
|
22
talon/user/community/apps/dock/dock.py
Normal file
22
talon/user/community/apps/dock/dock.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
from talon import Context, Module, actions, clip, ui
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
ctx.matches = """
|
||||
os: mac
|
||||
"""
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def dock_send_notification(notification: str):
|
||||
"""Send a CoreDock notification to the macOS Dock using SPI"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def dock_send_notification(notification: str):
|
||||
from talon.mac.dock import dock_notify
|
||||
|
||||
dock_notify(notification)
|
5
talon/user/community/apps/dock/dock.talon
Normal file
5
talon/user/community/apps/dock/dock.talon
Normal file
|
@ -0,0 +1,5 @@
|
|||
os: mac
|
||||
-
|
||||
^desktop$: user.dock_send_notification("com.apple.showdesktop.awake")
|
||||
^window$: user.dock_send_notification("com.apple.expose.front.awake")
|
||||
^launch pad$: user.dock_send_notification("com.apple.launchpad.toggle")
|
9
talon/user/community/apps/dunst/dunst.talon
Normal file
9
talon/user/community/apps/dunst/dunst.talon
Normal file
|
@ -0,0 +1,9 @@
|
|||
os: linux
|
||||
-
|
||||
|
||||
show notifications: key(ctrl-`)
|
||||
dismiss [notifications]: user.system_command("dunstctl close")
|
||||
dismiss all [notifications]: user.system_command("dunstctl close-all")
|
||||
#dunce pause: user.system_command('notify-send "DUNST_COMMAND_PAUSE"')
|
||||
#dunce resume: user.system_command('notify-send "DUNST_COMMAND_RESUME"')
|
||||
#test notification: user.system_command('notify-send "Hello from Talon"')
|
144
talon/user/community/apps/eclipse/eclipse.talon
Normal file
144
talon/user/community/apps/eclipse/eclipse.talon
Normal file
|
@ -0,0 +1,144 @@
|
|||
#custom eclipse commands go here
|
||||
app: eclipse
|
||||
-
|
||||
tag(): user.find_and_replace
|
||||
tag(): user.line_commands
|
||||
# tag(): user.multiple_cursors
|
||||
tag(): user.splits
|
||||
tag(): user.tabs
|
||||
tag(): user.command_search
|
||||
# splits.py support end
|
||||
|
||||
# Sidebar
|
||||
bar explore: key(alt-shift-w p)
|
||||
# bar extensions:
|
||||
bar outline: key(alt-shift-q o)
|
||||
|
||||
# bar run:
|
||||
|
||||
# bar source:
|
||||
# bar switch:
|
||||
|
||||
# Panels
|
||||
# panel control:
|
||||
panel output:
|
||||
key(alt-shift-q)
|
||||
sleep(200ms)
|
||||
key(c)
|
||||
panel problems:
|
||||
key(alt-shift-q)
|
||||
sleep(200ms)
|
||||
key(x)
|
||||
panel errors:
|
||||
key(alt-shift-q)
|
||||
sleep(200ms)
|
||||
key(l)
|
||||
panel breakpoints:
|
||||
key(alt-shift-q)
|
||||
sleep(200ms)
|
||||
key(b)
|
||||
panel search:
|
||||
key(alt-shift-q)
|
||||
sleep(200ms)
|
||||
key(s)
|
||||
panel variables:
|
||||
key(alt-shift-q)
|
||||
sleep(200ms)
|
||||
key(v)
|
||||
# panel switch:
|
||||
# panel terminal:
|
||||
|
||||
# Settings
|
||||
show settings: key(alt-w p)
|
||||
show shortcuts: key(ctrl-shift-l)
|
||||
#show snippets:
|
||||
|
||||
# Display
|
||||
# centered switch:
|
||||
# fullscreen switch:
|
||||
# theme switch:
|
||||
# wrap switch:
|
||||
# zen switch:
|
||||
|
||||
# File Commands
|
||||
file hunt [<user.text>]:
|
||||
key(ctrl-shift-r)
|
||||
sleep(50ms)
|
||||
insert(text or "")
|
||||
# file copy path:
|
||||
# file create sibling:
|
||||
file create: key(ctrl-n)
|
||||
file open folder: key(alt-shift-w x)
|
||||
file rename: key(alt-shift-w p enter f2)
|
||||
file reveal: key(alt-shift-w p enter)
|
||||
|
||||
# Language Features
|
||||
# suggest show:
|
||||
# hint show:
|
||||
# definition show:
|
||||
# definition peek:
|
||||
# definition side:
|
||||
# references show:
|
||||
# references find:
|
||||
# format that:
|
||||
# format selection:
|
||||
imports fix: key(ctrl-shift-o)
|
||||
# problem last:
|
||||
# problem fix:
|
||||
# rename that:
|
||||
# refactor that:
|
||||
# whitespace trim:
|
||||
# language switch:
|
||||
refactor rename: key(alt-shift-r)
|
||||
refactor this: key(alt-shift-i)
|
||||
|
||||
#code navigation
|
||||
(go declaration | follow): key(f3)
|
||||
go back: key(alt-left)
|
||||
go forward: key(alt-right)
|
||||
# go implementation:
|
||||
# go recent:
|
||||
# go type:
|
||||
# go usage:
|
||||
|
||||
# Bookmarks.
|
||||
#requires https://marketplace.eclipse.org/content/quick-bookmarks
|
||||
go marks: key(alt-end)
|
||||
toggle mark: key(ctrl-alt-b down enter)
|
||||
go next mark: key(alt-pagedown)
|
||||
go last mark: key(alt-pageup)
|
||||
|
||||
# Folding
|
||||
# fold that:
|
||||
# unfold that:
|
||||
# fold those:
|
||||
# unfold those:
|
||||
# fold all:
|
||||
# unfold all:
|
||||
# fold comments:
|
||||
|
||||
#Debugging
|
||||
break point: key(ctrl-shift-b)
|
||||
step over: key(f6)
|
||||
debug step into: key(f5)
|
||||
debug step out [of]: key(f7)
|
||||
#debug start: user.vscode("workbench.action.debug.start")
|
||||
#debug pause:
|
||||
#debug stopper:
|
||||
debug continue: key(f8)
|
||||
#debug restart:
|
||||
|
||||
# Terminal
|
||||
# terminal external: user.vscode("workbench.action.terminal.openNativeConsole")
|
||||
|
||||
# terminal new: user.vscode("workbench.action.terminal.new")
|
||||
# terminal next: user.vscode("workbench.action.terminal.focusNextPane")
|
||||
# terminal last:user.vscode("workbench.action.terminal.focusPreviousPane")
|
||||
# terminal split: user.vscode("workbench.action.terminal.split")
|
||||
# terminal trash: user.vscode("Terminal:Kill")
|
||||
# terminal scroll up: user.vscode("Terminal:ScrollUp")
|
||||
# terminal scroll down: user.vscode("Terminal:ScrollDown")
|
||||
|
||||
#TODO: should this be added to linecommands?
|
||||
copy line down: key(ctrl-alt-down)
|
||||
copy line up: key(ctrl-alt-up)
|
175
talon/user/community/apps/eclipse/eclipse_win.py
Normal file
175
talon/user/community/apps/eclipse/eclipse_win.py
Normal file
|
@ -0,0 +1,175 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
mod.apps.eclipse = """
|
||||
os: windows
|
||||
and app.name: eclipse.exe
|
||||
"""
|
||||
|
||||
ctx.matches = r"""
|
||||
app: eclipse
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
# talon app actions
|
||||
def tab_close():
|
||||
actions.key("ctrl-w")
|
||||
|
||||
def tab_next():
|
||||
actions.key("ctrl-pagedown")
|
||||
|
||||
def tab_previous():
|
||||
actions.key("ctrl-pageup")
|
||||
|
||||
# action(app.tab_reopen):
|
||||
def window_close():
|
||||
actions.key("alt-f4")
|
||||
|
||||
def window_open():
|
||||
actions.key("alt-w n")
|
||||
|
||||
|
||||
@ctx.action_class("code")
|
||||
class CodeActions:
|
||||
# talon code actions
|
||||
def toggle_comment():
|
||||
actions.key("ctrl-7")
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def find_next():
|
||||
actions.key("enter")
|
||||
|
||||
def find_previous():
|
||||
actions.key("shift-enter")
|
||||
|
||||
def line_swap_up():
|
||||
actions.key("alt-up")
|
||||
|
||||
def line_swap_down():
|
||||
actions.key("alt-down")
|
||||
|
||||
def line_clone():
|
||||
actions.key("ctrl-alt-down")
|
||||
|
||||
def jump_line(n: int):
|
||||
actions.key("ctrl-l")
|
||||
actions.insert(str(n))
|
||||
actions.key("enter")
|
||||
|
||||
def delete_line():
|
||||
actions.key("ctrl-d")
|
||||
|
||||
def indent_more():
|
||||
actions.key("tab")
|
||||
|
||||
def indent_less():
|
||||
actions.key("shift-tab")
|
||||
|
||||
def save_all():
|
||||
actions.key("ctrl-shift-s")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# splits.py support begin
|
||||
# requires https://marketplace.eclipse.org/content/handysplit
|
||||
def split_clear_all():
|
||||
actions.key("alt-shift-s f")
|
||||
|
||||
def split_clear():
|
||||
actions.key("alt-shift-s f")
|
||||
|
||||
# action(user.split_flip):
|
||||
def split_last():
|
||||
actions.key("alt-shift-s t")
|
||||
|
||||
def split_next():
|
||||
actions.key("alt-shift-s t")
|
||||
|
||||
def split_window_down():
|
||||
actions.key("alt-shift-s m")
|
||||
|
||||
def split_window_horizontally():
|
||||
actions.key("alt-ctrl-s s")
|
||||
|
||||
def split_window_right():
|
||||
actions.key("alt-shift-s m")
|
||||
|
||||
def split_window_up():
|
||||
actions.key("alt-shift-s m")
|
||||
|
||||
def split_window_vertically():
|
||||
actions.key("alt-shift-s s")
|
||||
|
||||
def split_window():
|
||||
actions.key("alt-ctrl-s s")
|
||||
|
||||
def command_search(command: str = ""):
|
||||
actions.key("ctrl-3")
|
||||
if command != "":
|
||||
actions.insert(command)
|
||||
|
||||
# splits.py support end
|
||||
|
||||
# find_and_replace.py support begin
|
||||
|
||||
def find_everywhere(text: str):
|
||||
"""Triggers find across project"""
|
||||
actions.key("ctrl-h")
|
||||
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
# todo: these commands should only be available
|
||||
# when it's focused
|
||||
def find_toggle_match_by_case():
|
||||
"""Toggles find match by case sensitivity"""
|
||||
actions.key("alt-c")
|
||||
|
||||
def find_toggle_match_by_word():
|
||||
"""Toggles find match by whole words"""
|
||||
actions.key("alt-w")
|
||||
|
||||
def find_toggle_match_by_regex():
|
||||
"""Toggles find match by regex"""
|
||||
actions.key("alt-e")
|
||||
|
||||
def replace(text: str):
|
||||
"""Search and replaces in the active editor"""
|
||||
actions.key("ctrl-f")
|
||||
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
def replace_everywhere(text: str):
|
||||
"""Search and replaces in the entire project"""
|
||||
actions.key("alt-a f")
|
||||
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
def replace_confirm():
|
||||
"""Confirm replace at current position"""
|
||||
actions.key("alt-r")
|
||||
|
||||
def replace_confirm_all():
|
||||
"""Confirm replace all"""
|
||||
actions.key("alt-a")
|
||||
|
||||
def select_previous_occurrence(text: str):
|
||||
actions.edit.find(text)
|
||||
actions.sleep("100ms")
|
||||
actions.key("alt-b alt-f enter esc")
|
||||
|
||||
def select_next_occurrence(text: str):
|
||||
actions.edit.find(text)
|
||||
actions.sleep("100ms")
|
||||
actions.key("alt-f alt-o esc")
|
||||
|
||||
# find_and_replace.py support end
|
28
talon/user/community/apps/edge/edge.py
Normal file
28
talon/user/community/apps/edge/edge.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
mod = Module()
|
||||
ctx = Context()
|
||||
|
||||
mod.apps.microsoft_edge = r"""
|
||||
os: windows
|
||||
and app.name: msedge.exe
|
||||
os: windows
|
||||
and app.name: Microsoft Edge
|
||||
os: windows
|
||||
and app.exe: /^msedge\.exe$/i
|
||||
os: mac
|
||||
and app.bundle: com.microsoft.edgemac
|
||||
os: linux
|
||||
and app.exe: msedge
|
||||
"""
|
||||
|
||||
ctx.matches = r"""
|
||||
app: microsoft_edge
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("browser")
|
||||
class BrowserActions:
|
||||
def show_extensions():
|
||||
actions.app.tab_open()
|
||||
actions.browser.go("edge://extensions")
|
4
talon/user/community/apps/edge/edge.talon
Normal file
4
talon/user/community/apps/edge/edge.talon
Normal file
|
@ -0,0 +1,4 @@
|
|||
app: microsoft_edge
|
||||
-
|
||||
tag(): browser
|
||||
tag(): user.tabs
|
363
talon/user/community/apps/emacs/emacs.py
Normal file
363
talon/user/community/apps/emacs/emacs.py
Normal file
|
@ -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()
|
367
talon/user/community/apps/emacs/emacs.talon
Normal file
367
talon/user/community/apps/emacs/emacs.talon
Normal file
|
@ -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")
|
231
talon/user/community/apps/emacs/emacs_commands.csv
Normal file
231
talon/user/community/apps/emacs/emacs_commands.csv
Normal file
|
@ -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
|
Can't render this file because it has a wrong number of fields in line 2.
|
71
talon/user/community/apps/emacs/emacs_commands.py
Normal file
71
talon/user/community/apps/emacs/emacs_commands.py
Normal file
|
@ -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
|
6
talon/user/community/apps/evernote/mac.talon
Normal file
6
talon/user/community/apps/evernote/mac.talon
Normal file
|
@ -0,0 +1,6 @@
|
|||
app: evernote
|
||||
os: mac
|
||||
-
|
||||
settings():
|
||||
# Necessary to stop commands like 'slap' getting jumbled
|
||||
key_wait = 9.0
|
4
talon/user/community/apps/evince/evince.talon
Normal file
4
talon/user/community/apps/evince/evince.talon
Normal file
|
@ -0,0 +1,4 @@
|
|||
app: evince
|
||||
-
|
||||
# Set tags
|
||||
tag(): user.pages
|
39
talon/user/community/apps/evince/evince_linux.py
Normal file
39
talon/user/community/apps/evince/evince_linux.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
# --- App definition ---
|
||||
mod = Module()
|
||||
mod.apps.evince = """
|
||||
os: linux
|
||||
and app.name: Evince
|
||||
"""
|
||||
|
||||
# Context matching
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: evince
|
||||
"""
|
||||
|
||||
|
||||
# --- Implement actions ---
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# user.pages
|
||||
def page_current():
|
||||
actions.key("ctrl-l")
|
||||
page = actions.edit.selected_text()
|
||||
actions.key("escape")
|
||||
return int(page)
|
||||
|
||||
def page_next():
|
||||
actions.key("n")
|
||||
|
||||
def page_previous():
|
||||
actions.key("p")
|
||||
|
||||
def page_jump(number: int):
|
||||
actions.key("ctrl-l")
|
||||
actions.insert(str(number))
|
||||
actions.key("enter")
|
||||
|
||||
def page_final():
|
||||
actions.key("ctrl-end")
|
77
talon/user/community/apps/finder/finder.py
Normal file
77
talon/user/community/apps/finder/finder.py
Normal file
|
@ -0,0 +1,77 @@
|
|||
import os
|
||||
|
||||
from talon import Context, actions, ui
|
||||
from talon.mac import applescript
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: finder
|
||||
"""
|
||||
directories_to_remap = {"": "/Volumes"}
|
||||
directories_to_exclude = {}
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def file_manager_open_parent():
|
||||
actions.key("cmd-up")
|
||||
|
||||
def file_manager_current_path():
|
||||
title = ui.active_window().title
|
||||
|
||||
if "~" in title:
|
||||
title = os.path.expanduser(title)
|
||||
|
||||
if title in directories_to_remap:
|
||||
title = directories_to_remap[title]
|
||||
|
||||
if title in directories_to_exclude:
|
||||
title = ""
|
||||
|
||||
return title
|
||||
|
||||
def file_manager_terminal_here():
|
||||
applescript.run(
|
||||
r"""
|
||||
tell application "Finder"
|
||||
set myWin to window 1
|
||||
set thePath to (quoted form of POSIX path of (target of myWin as alias))
|
||||
tell application "Terminal"
|
||||
activate
|
||||
tell window 1
|
||||
do script "cd " & thePath
|
||||
end tell
|
||||
end tell
|
||||
end tell"""
|
||||
)
|
||||
|
||||
def file_manager_show_properties():
|
||||
"""Shows the properties for the file"""
|
||||
actions.key("cmd-i")
|
||||
|
||||
def file_manager_open_directory(path: str):
|
||||
"""opens the directory that's already visible in the view"""
|
||||
actions.key("cmd-shift-g")
|
||||
actions.sleep("50ms")
|
||||
actions.insert(path)
|
||||
actions.key("enter")
|
||||
|
||||
def file_manager_select_directory(path: str):
|
||||
"""selects the directory"""
|
||||
actions.insert(path)
|
||||
|
||||
def file_manager_new_folder(name: str):
|
||||
"""Creates a new folder in a gui filemanager or inserts the command to do so for terminals"""
|
||||
actions.key("cmd-shift-n")
|
||||
actions.insert(name)
|
||||
|
||||
def file_manager_open_file(path: str):
|
||||
"""opens the file"""
|
||||
actions.key("home")
|
||||
actions.insert(path)
|
||||
actions.key("cmd-o")
|
||||
|
||||
def file_manager_select_file(path: str):
|
||||
"""selects the file"""
|
||||
actions.key("home")
|
||||
actions.insert(path)
|
28
talon/user/community/apps/finder/finder.talon
Normal file
28
talon/user/community/apps/finder/finder.talon
Normal file
|
@ -0,0 +1,28 @@
|
|||
os: mac
|
||||
app: finder
|
||||
-
|
||||
tag(): user.file_manager
|
||||
tag(): user.tabs
|
||||
preferences: key(cmd-,)
|
||||
options: key(cmd-j)
|
||||
search: key(cmd-alt-f)
|
||||
|
||||
# bit of a mouthful, but it's probably not the kind of thing you'd be saying frequently
|
||||
sort by none: key(ctrl-alt-cmd-0)
|
||||
sort by name: key(ctrl-alt-cmd-1)
|
||||
sort by kind: key(ctrl-alt-cmd-2)
|
||||
sort by date opened: key(ctrl-alt-cmd-3)
|
||||
sort by date added: key(ctrl-alt-cmd-4)
|
||||
sort by date modified: key(ctrl-alt-cmd-5)
|
||||
sort by size: key(ctrl-alt-cmd-6)
|
||||
|
||||
icon view: key(cmd-1)
|
||||
column view: key(cmd-3)
|
||||
list view: key(cmd-2)
|
||||
gallery view: key(cmd-4)
|
||||
|
||||
copy path: key(alt-cmd-c)
|
||||
trash it: key(cmd-backspace)
|
||||
|
||||
hide [finder]: key(cmd-h)
|
||||
hide others: app.window_hide_others()
|
60
talon/user/community/apps/firefox/firefox.py
Normal file
60
talon/user/community/apps/firefox/firefox.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
from talon import Context, Module, actions, app
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
apps = mod.apps
|
||||
apps.firefox = "app.name: Firefox"
|
||||
apps.firefox = "app.name: Firefox Developer Edition"
|
||||
apps.firefox = "app.name: firefox"
|
||||
apps.firefox = "app.name: Firefox-esr"
|
||||
apps.firefox = "app.name: firefox-esr"
|
||||
apps.firefox = "app.name: LibreWolf"
|
||||
apps.firefox = "app.name: waterfox"
|
||||
apps.firefox = r"""
|
||||
os: windows
|
||||
and app.name: Firefox
|
||||
os: windows
|
||||
and app.exe: /^firefox\.exe$/i
|
||||
"""
|
||||
apps.firefox = """
|
||||
os: mac
|
||||
and app.bundle: org.mozilla.firefox
|
||||
"""
|
||||
|
||||
# Make the context match more specifically than anything else. This is important, eg. to
|
||||
# override the browser.go_home() implementation in tags/browser/browser_mac.py.
|
||||
ctx.matches = r"""
|
||||
os: windows
|
||||
os: linux
|
||||
os: mac
|
||||
tag: browser
|
||||
app: firefox
|
||||
"""
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def firefox_bookmarks_sidebar():
|
||||
"""Toggles the Firefox bookmark sidebar"""
|
||||
|
||||
def firefox_history_sidebar():
|
||||
"""Toggles the Firefox history sidebar"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def tab_close_wrapper():
|
||||
actions.sleep("180ms")
|
||||
actions.app.tab_close()
|
||||
|
||||
|
||||
@ctx.action_class("browser")
|
||||
class BrowserActions:
|
||||
def focus_page():
|
||||
actions.browser.focus_address()
|
||||
actions.edit.find()
|
||||
actions.sleep("180ms")
|
||||
actions.key("escape")
|
||||
|
||||
def go_home():
|
||||
actions.key("alt-home")
|
15
talon/user/community/apps/firefox/firefox.talon
Normal file
15
talon/user/community/apps/firefox/firefox.talon
Normal file
|
@ -0,0 +1,15 @@
|
|||
app: firefox
|
||||
-
|
||||
tag(): browser
|
||||
tag(): user.tabs
|
||||
|
||||
tab search:
|
||||
browser.focus_address()
|
||||
insert("% ")
|
||||
tab search <user.text>$:
|
||||
browser.focus_address()
|
||||
insert("% {text}")
|
||||
key(down)
|
||||
|
||||
(sidebar | panel) bookmarks: user.firefox_bookmarks_sidebar()
|
||||
(sidebar | panel) history: user.firefox_history_sidebar()
|
33
talon/user/community/apps/firefox/firefox_mac.py
Normal file
33
talon/user/community/apps/firefox/firefox_mac.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
|
||||
ctx.matches = r"""
|
||||
os: mac
|
||||
tag: browser
|
||||
app: firefox
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def firefox_bookmarks_sidebar():
|
||||
actions.key("cmd-b")
|
||||
|
||||
def firefox_history_sidebar():
|
||||
actions.key("cmd-shift-h")
|
||||
|
||||
|
||||
@ctx.action_class("browser")
|
||||
class BrowserActions:
|
||||
def bookmarks():
|
||||
actions.key("cmd-shift-o")
|
||||
|
||||
def open_private_window():
|
||||
actions.key("cmd-shift-p")
|
||||
|
||||
def show_downloads():
|
||||
actions.key("cmd-j")
|
||||
|
||||
def show_extensions():
|
||||
actions.key("cmd-shift-a")
|
44
talon/user/community/apps/firefox/firefox_win_linux.py
Normal file
44
talon/user/community/apps/firefox/firefox_win_linux.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from talon import Context, actions, app
|
||||
|
||||
ctx = Context()
|
||||
|
||||
ctx.matches = r"""
|
||||
os: windows
|
||||
os: linux
|
||||
tag: browser
|
||||
app: firefox
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def firefox_bookmarks_sidebar():
|
||||
actions.key("ctrl-b")
|
||||
|
||||
def firefox_history_sidebar():
|
||||
actions.key("ctrl-h")
|
||||
|
||||
|
||||
@ctx.action_class("browser")
|
||||
class BrowserActions:
|
||||
def focus_address():
|
||||
# Only using "ctrl-l" might fail and clear the console if the user
|
||||
# is focused in the devtools
|
||||
actions.key("f6")
|
||||
actions.sleep("100ms")
|
||||
actions.key("ctrl-l")
|
||||
|
||||
def open_private_window():
|
||||
actions.key("ctrl-shift-p")
|
||||
|
||||
def show_downloads():
|
||||
if app.platform == "linux":
|
||||
actions.key("ctrl-shift-y")
|
||||
else:
|
||||
actions.key("ctrl-j")
|
||||
|
||||
def show_extensions():
|
||||
actions.key("ctrl-shift-a")
|
||||
|
||||
def show_history():
|
||||
actions.key("ctrl-shift-h")
|
70
talon/user/community/apps/foxit_reader/foxit_reader.py
Normal file
70
talon/user/community/apps/foxit_reader/foxit_reader.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
mod = Module()
|
||||
ctx = Context()
|
||||
|
||||
# --- App definition ---
|
||||
mod.apps.foxit_reader = r"""
|
||||
os: windows
|
||||
and app.name: /^Foxit Reader/
|
||||
os: windows
|
||||
and app.exe: /^foxitreader\.exe$/i
|
||||
os: windows
|
||||
and app.name: Foxit PDF Reader
|
||||
os: windows
|
||||
and app.exe: /^foxitpdfreader\.exe$/i
|
||||
"""
|
||||
# Context matching
|
||||
ctx.matches = """
|
||||
app: foxit_reader
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
# app.tabs
|
||||
def tab_open():
|
||||
actions.key("ctrl-o")
|
||||
|
||||
def tab_reopen():
|
||||
actions.app.notify("Foxit does not support this action.")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# user.tabs
|
||||
def tab_jump(number):
|
||||
actions.app.notify("Foxit does not support this action.")
|
||||
|
||||
def tab_final():
|
||||
actions.app.notify("Foxit does not support this action.")
|
||||
|
||||
def tab_duplicate():
|
||||
actions.app.notify("Foxit does not support this action.")
|
||||
|
||||
# user.pages
|
||||
def page_current() -> int:
|
||||
actions.key("ctrl-g")
|
||||
page = actions.edit.selected_text()
|
||||
return int(page)
|
||||
|
||||
def page_next():
|
||||
actions.key("right")
|
||||
|
||||
def page_previous():
|
||||
actions.key("left")
|
||||
|
||||
def page_jump(number: int):
|
||||
actions.key("ctrl-g")
|
||||
actions.insert(str(number))
|
||||
actions.key("enter")
|
||||
|
||||
def page_final():
|
||||
# actions.key("fn-right")
|
||||
actions.key("end")
|
||||
|
||||
def page_rotate_right():
|
||||
actions.key("shift-ctrl-keypad_plus")
|
||||
|
||||
def page_rotate_left():
|
||||
actions.key("shift-ctrl-keypad_minus")
|
|
@ -0,0 +1,6 @@
|
|||
app: foxit_reader
|
||||
-
|
||||
tag(): user.tabs
|
||||
tag(): user.pages
|
||||
|
||||
tab close all: key(ctrl-shift-w)
|
117
talon/user/community/apps/gdb/gdb.py
Normal file
117
talon/user/community/apps/gdb/gdb.py
Normal file
|
@ -0,0 +1,117 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
mod = Module()
|
||||
mod.tag("gdb", "Tag to enabled gdb-related functionality")
|
||||
|
||||
# user.gdb-specific context
|
||||
ctx_gdb_enabled = Context()
|
||||
ctx_gdb_enabled.matches = r"""
|
||||
tag: user.gdb
|
||||
"""
|
||||
|
||||
# global context for enabling and disabling user.gdb tag
|
||||
ctx_global = Context()
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def gdb_enable():
|
||||
"""Enables the gdb tag"""
|
||||
ctx_global.tags = ["user.gdb"]
|
||||
|
||||
def gdb_disable():
|
||||
"""Disables the gdb tag"""
|
||||
ctx_global.tags = []
|
||||
|
||||
|
||||
@ctx_gdb_enabled.action_class("user")
|
||||
class UserActions:
|
||||
##
|
||||
# Generic debugger actions
|
||||
##
|
||||
|
||||
# Code execution
|
||||
def debugger_step_into():
|
||||
actions.auto_insert("stepi\n")
|
||||
|
||||
def debugger_step_over():
|
||||
actions.auto_insert("nexti\n")
|
||||
|
||||
def debugger_step_line():
|
||||
actions.auto_insert("step\n")
|
||||
|
||||
def debugger_step_over_line():
|
||||
actions.auto_insert("next\n")
|
||||
|
||||
def debugger_step_out():
|
||||
actions.auto_insert("finish\n")
|
||||
|
||||
def debugger_continue():
|
||||
actions.auto_insert("c\n")
|
||||
|
||||
def debugger_stop():
|
||||
actions.key("ctrl-c")
|
||||
|
||||
def debugger_start():
|
||||
actions.auto_insert("run\n")
|
||||
|
||||
def debugger_restart():
|
||||
actions.auto_insert("run\n")
|
||||
|
||||
# XXX -
|
||||
def debugger_detach():
|
||||
actions.auto_insert("")
|
||||
|
||||
# Registers
|
||||
def debugger_show_registers():
|
||||
actions.auto_insert("info registers\n")
|
||||
|
||||
def debugger_get_register():
|
||||
actions.auto_insert("r ")
|
||||
|
||||
def debugger_set_register():
|
||||
actions.user.insert_between("set $", "=")
|
||||
# Breakpoints
|
||||
|
||||
def debugger_show_breakpoints():
|
||||
actions.auto_insert("info breakpoints\n")
|
||||
|
||||
def debugger_add_sw_breakpoint():
|
||||
actions.auto_insert("break ")
|
||||
|
||||
# XXX -
|
||||
def debugger_add_hw_breakpoint():
|
||||
actions.auto_insert("")
|
||||
|
||||
def debugger_break_now():
|
||||
actions.key("ctrl-c")
|
||||
|
||||
def debugger_break_here():
|
||||
actions.auto_insert("break\n")
|
||||
|
||||
def debugger_clear_all_breakpoints():
|
||||
actions.auto_insert("d br\n")
|
||||
|
||||
def debugger_clear_breakpoint():
|
||||
actions.insert("d br ")
|
||||
|
||||
def debugger_enable_all_breakpoints():
|
||||
actions.insert("enable br\n")
|
||||
|
||||
def debugger_enable_breakpoint():
|
||||
actions.insert("enable br ")
|
||||
|
||||
def debugger_disable_all_breakpoints():
|
||||
actions.insert("disable br\n")
|
||||
|
||||
def debugger_disable_breakpoint():
|
||||
actions.insert("disable br ")
|
||||
|
||||
def debugger_clear_breakpoint_id(number_small: int):
|
||||
actions.insert(f"d br {number_small}\n")
|
||||
|
||||
def debugger_disable_breakpoint_id(number_small: int):
|
||||
actions.insert(f"disable br {number_small}\n")
|
||||
|
||||
def debugger_enable_breakpoint_id(number_small: int):
|
||||
actions.insert(f"enable br {number_small}\n")
|
102
talon/user/community/apps/gdb/gdb_active.talon
Normal file
102
talon/user/community/apps/gdb/gdb_active.talon
Normal file
|
@ -0,0 +1,102 @@
|
|||
os: linux
|
||||
# XXX - this matches .gdb files atm
|
||||
#win.title: /gdb/
|
||||
tag: terminal
|
||||
and tag: user.gdb
|
||||
-
|
||||
tag(): user.debugger
|
||||
until <number>: "until {number}"
|
||||
force clear all break points:
|
||||
insert("d br\n")
|
||||
insert("y\n")
|
||||
break [on] clipboard:
|
||||
insert("break ")
|
||||
key(ctrl-shift-v)
|
||||
key(enter)
|
||||
|
||||
# information
|
||||
list [source]: "list\n"
|
||||
info source: "info source\n"
|
||||
|
||||
print: "p "
|
||||
print [variable] <user.text>: "p {text}"
|
||||
print hex: "p/x "
|
||||
print hex [variable] <user.text>: "p/x {text}"
|
||||
print string: "p/s "
|
||||
|
||||
# hexdumping
|
||||
# XXX - switch the sizes to a list in python?
|
||||
# XXX - should cache the last used size
|
||||
hex dump <number> bytes: "x/{number}bx "
|
||||
hex dump <number> (half | short) words: "x/{number}hx "
|
||||
hex dump <number> (d | long) words: "x/{number}dx "
|
||||
hex dump <number> quad words: "x/{number}gx "
|
||||
# this is some arbitrary default for convenience
|
||||
hex dump: "x/100gx "
|
||||
hex dump highlighted:
|
||||
insert("x/100gx ")
|
||||
edit.copy()
|
||||
edit.paste()
|
||||
key(enter)
|
||||
hex dump clipboard:
|
||||
insert("x/100gx ")
|
||||
edit.paste()
|
||||
key(enter)
|
||||
|
||||
# execution
|
||||
source: "source \t\t"
|
||||
|
||||
# displays
|
||||
# XXX - move thee invoke command into a python script
|
||||
(list | show | info) display: "info display\n"
|
||||
display assembly line$: "display /i $pc\n"
|
||||
display source: "display "
|
||||
enable display <number_small>: "enable display {number_small}\n"
|
||||
disable display <number_small>: "disable display {number_small}\n"
|
||||
undisplay: "undisplay\n"
|
||||
|
||||
# variables
|
||||
(list | show | info) local: "info local "
|
||||
(list | show | info) local typed: "info local -t "
|
||||
(list | show | info) variable: "info variable "
|
||||
(list | show | info) variable typed: "info variable -t "
|
||||
(list | show | info) locals: "info local\n"
|
||||
(list | show | info) variables: "info variables\n"
|
||||
|
||||
# threads
|
||||
info threads: "info threads\n"
|
||||
|
||||
restart [program]: "r\n"
|
||||
continue: "c\n"
|
||||
back trace: "bt\n"
|
||||
debug quit: "quit\n"
|
||||
# more quickly quit when there are inferiors
|
||||
debug force quit: "quit\ny\n"
|
||||
(show | info) (inf | inferiors): "info inferiors\n"
|
||||
inferior <number_small>$: "inferior {number_small}\n"
|
||||
inferior: "inferior "
|
||||
resume main (inf | inferior):
|
||||
insert("inferior 1\n")
|
||||
insert("c\n")
|
||||
resume [from] (inf | inferior) <number_small>$:
|
||||
insert("inferior {number_small}\n")
|
||||
insert("c\n")
|
||||
|
||||
# arguments
|
||||
set args: "set args "
|
||||
|
||||
# settings
|
||||
show follow (fork | forks) [mode]: "show follow-fork-mode\n"
|
||||
[set] follow (fork | forks) [mode] child: "set follow-fork-mode child\n"
|
||||
[set] follow (fork | forks) [mode] parent: "set follow-fork-mode parent\n"
|
||||
|
||||
show detach on fork: "show detach-on-fork\n"
|
||||
set detach on fork: "set detach-on-fork on\n"
|
||||
unset detach on fork: "set detach-on-fork off\n"
|
||||
|
||||
# list
|
||||
show list size: "show listsize\n"
|
||||
set list size <number_small>: "set listsize {number_small}\n"
|
||||
|
||||
# misc
|
||||
clear screen: "shell clear\n"
|
2
talon/user/community/apps/gdb/gdb_global.talon
Normal file
2
talon/user/community/apps/gdb/gdb_global.talon
Normal file
|
@ -0,0 +1,2 @@
|
|||
[enable] debug mode: user.gdb_enable()
|
||||
disable debug mode: user.gdb_disable()
|
17
talon/user/community/apps/git/git.py
Normal file
17
talon/user/community/apps/git/git.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
import csv
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from talon import Context, Module, actions, resource
|
||||
|
||||
mod = Module()
|
||||
ctx = Context()
|
||||
|
||||
mod.list("git_command", desc="Git commands.")
|
||||
mod.list("git_argument", desc="Command-line git options and arguments.")
|
||||
|
||||
|
||||
@mod.capture(rule="{user.git_argument}+")
|
||||
def git_arguments(m) -> str:
|
||||
"""A non-empty sequence of git command arguments, preceded by a space."""
|
||||
return " " + " ".join(m.git_argument_list)
|
51
talon/user/community/apps/git/git.talon
Normal file
51
talon/user/community/apps/git/git.talon
Normal file
|
@ -0,0 +1,51 @@
|
|||
tag: terminal
|
||||
and tag: user.git
|
||||
-
|
||||
git {user.git_command} [<user.git_arguments>]:
|
||||
args = git_arguments or ""
|
||||
"git {git_command}{args} "
|
||||
git commit [<user.git_arguments>] message [<user.prose>]:
|
||||
args = git_arguments or ""
|
||||
message = prose or ""
|
||||
user.insert_between('git commit{args} --message "{message}', '"')
|
||||
git stash [push] [<user.git_arguments>] message [<user.prose>]:
|
||||
args = git_arguments or ""
|
||||
message = prose or ""
|
||||
user.insert_between('git stash push{args} --message "{message}', '"')
|
||||
|
||||
# Optimistic execution for frequently used commands that are harmless (don't
|
||||
# change repository or index state).
|
||||
git status$: "git status\n"
|
||||
git add patch$: "git add --patch\n"
|
||||
git show head$: "git show HEAD\n"
|
||||
git diff$: "git diff\n"
|
||||
git diff (cached | cashed)$: "git diff --cached\n"
|
||||
|
||||
# Convenience
|
||||
git clone clipboard:
|
||||
insert("git clone ")
|
||||
edit.paste()
|
||||
key(enter)
|
||||
git diff highlighted:
|
||||
edit.copy()
|
||||
insert("git diff ")
|
||||
edit.paste()
|
||||
key(enter)
|
||||
git diff clipboard:
|
||||
insert("git diff ")
|
||||
edit.paste()
|
||||
key(enter)
|
||||
git add highlighted:
|
||||
edit.copy()
|
||||
insert("git add ")
|
||||
edit.paste()
|
||||
key(enter)
|
||||
git add clipboard:
|
||||
insert("git add ")
|
||||
edit.paste()
|
||||
key(enter)
|
||||
git commit highlighted:
|
||||
edit.copy()
|
||||
insert("git add ")
|
||||
edit.paste()
|
||||
insert("\ngit commit\n")
|
19
talon/user/community/apps/git/git_add_patch.talon
Normal file
19
talon/user/community/apps/git/git_add_patch.talon
Normal file
|
@ -0,0 +1,19 @@
|
|||
tag: terminal
|
||||
and tag: user.git
|
||||
title: /git add .*\-p/
|
||||
-
|
||||
yank:
|
||||
key(y)
|
||||
key(enter)
|
||||
near:
|
||||
key(n)
|
||||
key(enter)
|
||||
quench:
|
||||
key(q)
|
||||
key(enter)
|
||||
drum:
|
||||
key(d)
|
||||
key(enter)
|
||||
air:
|
||||
key(a)
|
||||
key(enter)
|
69
talon/user/community/apps/git/git_argument.talon-list
Normal file
69
talon/user/community/apps/git/git_argument.talon-list
Normal file
|
@ -0,0 +1,69 @@
|
|||
list: user.git_argument
|
||||
-
|
||||
abort: --abort
|
||||
all: --all
|
||||
allow empty: --allow-empty
|
||||
amend: --amend
|
||||
cached: --cached
|
||||
cashed: --cached
|
||||
color words: --color-words
|
||||
colour words: --color-words
|
||||
continue: --continue
|
||||
copy: --copy
|
||||
create: --create
|
||||
delete: --delete
|
||||
detach: --detach
|
||||
dir diff: --dir-diff
|
||||
directory diff: --dir-diff
|
||||
dry run: --dry-run
|
||||
edit: --edit
|
||||
fast forward only: --ff-only
|
||||
force: --force
|
||||
force create: --force-create
|
||||
force with lease: --force-with-lease
|
||||
global: --global
|
||||
global: --global
|
||||
hard: --hard
|
||||
ignore case: --ignore-case
|
||||
include untracked: --include-untracked
|
||||
interactive: --interactive
|
||||
keep index: --keep-index
|
||||
list: --list
|
||||
local: --local
|
||||
mixed: --mixed
|
||||
move: --move
|
||||
no edit: --no-edit
|
||||
no keep index: --no-keep-index
|
||||
no rebase: --no-rebase
|
||||
no track: --no-track
|
||||
no verify: --no-verify
|
||||
orphan: --orphan
|
||||
patch: --patch
|
||||
prune: --prune
|
||||
quiet: --quiet
|
||||
quit: --quit
|
||||
rebase: --rebase
|
||||
remote: --remote
|
||||
set up stream: --set-upstream
|
||||
set up stream to: --set-upstream-to
|
||||
short: --short
|
||||
short stat: --shortstat
|
||||
skip: --skip
|
||||
soft: --soft
|
||||
staged: --staged
|
||||
stat: --stat
|
||||
system: --system
|
||||
track: --track
|
||||
update: --update
|
||||
verbose: --verbose
|
||||
branch: -b
|
||||
combined: -c
|
||||
deep: -d
|
||||
very verbose: -vv
|
||||
HEAD
|
||||
main
|
||||
master
|
||||
origin
|
||||
upstream
|
||||
origin main: origin/main
|
||||
origin master: origin/master
|
71
talon/user/community/apps/git/git_command.talon-list
Normal file
71
talon/user/community/apps/git/git_command.talon-list
Normal file
|
@ -0,0 +1,71 @@
|
|||
list: user.git_command
|
||||
-
|
||||
add
|
||||
archive
|
||||
bisect
|
||||
blame
|
||||
branch
|
||||
checkout
|
||||
cherry pick: cherry-pick
|
||||
clean
|
||||
clone
|
||||
commit
|
||||
config
|
||||
diff
|
||||
diff tool: difftool
|
||||
fetch
|
||||
gc
|
||||
grep
|
||||
help
|
||||
in it: init
|
||||
log
|
||||
ls files: ls-files
|
||||
merge
|
||||
merge tool: mergetool
|
||||
move: mv
|
||||
pull
|
||||
push
|
||||
range diff: range-diff
|
||||
rebase
|
||||
ref log: reflog
|
||||
remote
|
||||
remote add
|
||||
remote remove
|
||||
remote rename
|
||||
remote set url: remote set-url
|
||||
remote set you are el: remote set-url
|
||||
remote show
|
||||
rerere
|
||||
rerere diff
|
||||
rerere status
|
||||
reset
|
||||
restore
|
||||
revert
|
||||
remove: rm
|
||||
short log: shortlog
|
||||
show
|
||||
sparse checkout: sparse-checkout
|
||||
stash
|
||||
stash apply
|
||||
stash list
|
||||
stash pop
|
||||
stash push
|
||||
stash show
|
||||
stash save
|
||||
status
|
||||
submodule
|
||||
submodule add
|
||||
submodule in it: submodule init
|
||||
submodule status
|
||||
submodule update
|
||||
switch
|
||||
tag
|
||||
worktree
|
||||
worktree add
|
||||
worktree list
|
||||
worktree lock
|
||||
worktree move
|
||||
worktree prune
|
||||
worktree remove
|
||||
worktree repair
|
||||
worktree unlock
|
70
talon/user/community/apps/github/github_web.talon
Normal file
70
talon/user/community/apps/github/github_web.talon
Normal file
|
@ -0,0 +1,70 @@
|
|||
# https://help.github.com/en/github/getting-started-with-github/keyboard-shortcuts
|
||||
tag: browser
|
||||
browser.host: github.com
|
||||
-
|
||||
|
||||
# site wide shortcuts
|
||||
focus search: key(s)
|
||||
go to notifications: insert("gn")
|
||||
go to dashboard: insert("gd")
|
||||
(keyboard shortcuts show | show keyboard shortcuts): key(?)
|
||||
(selection move down | move selection down): key(j)
|
||||
(selection move up | move selection up): key(k)
|
||||
(selection toggle | toggle selection): key(x)
|
||||
(selection open | open selection): key(o)
|
||||
|
||||
# repositories
|
||||
go to code: insert("gc")
|
||||
go to issues: insert("gi")
|
||||
go to pull requests: insert("gp")
|
||||
go to wiki: insert("gw")
|
||||
go to actions: insert("ga")
|
||||
go to projects: insert("gb")
|
||||
go to discussions: insert("gg")
|
||||
|
||||
# source code editing
|
||||
[web] editor open: key(.)
|
||||
|
||||
# source code browsing
|
||||
(file find | find file): key(t)
|
||||
jump to line: key(l)
|
||||
((branch | tag) switch | switch (branch | tag)): key(w)
|
||||
(url expand | expand url): key(y)
|
||||
(show | hide) comments: key(i)
|
||||
blame view open: key(b)
|
||||
(show | hide) annotations: key(a)
|
||||
|
||||
# issues
|
||||
(issue create | create [an] issue): key(c)
|
||||
search (issues | [pull] requests): key(/)
|
||||
(filter by | edit) labels: key(l)
|
||||
(filter by | edit) milestones: key(m)
|
||||
(filter by | edit) assignee: key(a)
|
||||
reply: key(r)
|
||||
(comment submit | submit comment): key(ctrl-enter)
|
||||
(comment preview | preview comment): key(ctrl-shift-p)
|
||||
git hub full screen: key(ctrl-shift-l)
|
||||
|
||||
# browsing commit
|
||||
(form close | close form): key(escape)
|
||||
parent commit: key(p)
|
||||
other parent commit: key(o)
|
||||
|
||||
# notifications
|
||||
mark as read: key(y)
|
||||
(thread mute | mute thread): key(shift-m)
|
||||
|
||||
# issue or pull request list
|
||||
(issue open | open issue): key(o)
|
||||
(issue create | create issue): key(c)
|
||||
|
||||
# issues and pull requests
|
||||
reviewer request: key(q)
|
||||
milestone set: key(m)
|
||||
assignee set: key(a)
|
||||
label set: key(l)
|
||||
|
||||
# actions
|
||||
go to workflow: insert("gf")
|
||||
timestamps toggle: key(shift-t)
|
||||
fullscreen toggle: key(shift-f)
|
60
talon/user/community/apps/gitlab/gitlab.talon
Normal file
60
talon/user/community/apps/gitlab/gitlab.talon
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Shortcuts taken from: https://docs.gitlab.com/ee/user/shortcuts.html
|
||||
#
|
||||
tag: browser
|
||||
browser.host: /gitlab\.com/
|
||||
#win.title: /GitLab/
|
||||
-
|
||||
|
||||
# global shortcuts
|
||||
show shortcuts: key(?)
|
||||
go to projects [page]: key(shift-p)
|
||||
go to groups [page]: key(shift-g)
|
||||
go to activity [page]: key(shift-a)
|
||||
go to milestones [page]: key(shift-l)
|
||||
go to snippets [page]: key(shift-s)
|
||||
search page: key(s)
|
||||
go to issues [page]: key(shift-i)
|
||||
go to merge requests [page]: key(shift-m)
|
||||
go to to do [list] [page]: key(shift-t)
|
||||
(show | hide) performance bar: key(p)
|
||||
|
||||
edit last comment: key(1)
|
||||
toggle mark down [preview]: key(ctrl-shift-p)
|
||||
|
||||
# projects
|
||||
go [to] project home [page]: insert("gp")
|
||||
go [to] project activity [feed]: insert("gv")
|
||||
go [to] project releases [list]: insert("gr")
|
||||
go [to] project files [list]: insert("gf")
|
||||
go [to] project file search [page]: key(t)
|
||||
go [to] project (commit | commits) [list]: insert("gc")
|
||||
go [to] (repository | repo) graph [page]: insert("gn")
|
||||
go [to] (repository | repo) charts: insert("gd")
|
||||
go [to] project issues [list]: insert("gi")
|
||||
go [to] new issues [list]: insert("i")
|
||||
go [to] project issues boards [list]: insert("gb")
|
||||
go [to] project merge requests [list]: insert("gm")
|
||||
go [to] jobs [list]: insert("gj")
|
||||
go [to] project metrics: insert("gl")
|
||||
go [to] project environments: insert("ge")
|
||||
go [to] project cubes: insert("gk")
|
||||
go [to] project snippets [list]: insert("gs")
|
||||
go [to] project wiki: insert("gw")
|
||||
|
||||
# issues and merge requests
|
||||
edit description: key(e)
|
||||
change assignee: key(a)
|
||||
change milestone: key(m)
|
||||
change label: key(l)
|
||||
right comment: key(r)
|
||||
next [unresolved] discussion: key(n)
|
||||
previous [unresolved] discussion: key(p)
|
||||
next file: key(])
|
||||
previous file: key([)
|
||||
|
||||
# project files
|
||||
back to files: key(escape)
|
||||
open permalink: key(y)
|
||||
|
||||
# wiki pages
|
||||
edit page: key(e)
|
93
talon/user/community/apps/gnome_terminal/gnome_terminal.py
Normal file
93
talon/user/community/apps/gnome_terminal/gnome_terminal.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
# App definition
|
||||
mod = Module()
|
||||
mod.apps.gnome_terminal = """
|
||||
os: linux
|
||||
and app.exe: gnome-terminal-server
|
||||
os: linux
|
||||
and app.name: Gnome-terminal
|
||||
os: linux
|
||||
and app.name: Mate-terminal
|
||||
"""
|
||||
|
||||
# Context matching
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: gnome_terminal
|
||||
"""
|
||||
|
||||
|
||||
# --- Implement actions ---
|
||||
@ctx.action_class("user")
|
||||
class user_actions:
|
||||
# user.tabs
|
||||
def tab_jump(number):
|
||||
actions.key(f"alt-{number}")
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class app_actions:
|
||||
# app.tabs
|
||||
def tab_open():
|
||||
actions.key("ctrl-shift-t")
|
||||
|
||||
def tab_previous():
|
||||
actions.key("ctrl-pageup")
|
||||
|
||||
def tab_next():
|
||||
actions.key("ctrl-pagedown")
|
||||
|
||||
def tab_close():
|
||||
actions.key("ctrl-shift-w")
|
||||
|
||||
# global (overwrite linux/app.py)
|
||||
def window_open():
|
||||
actions.key("ctrl-shift-n")
|
||||
|
||||
def window_close():
|
||||
actions.key("ctrl-shift-q")
|
||||
|
||||
|
||||
# global (overwrite linux/edit.py)
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def page_down():
|
||||
actions.key("shift-pagedown")
|
||||
|
||||
def page_up():
|
||||
actions.key("shift-pageup")
|
||||
|
||||
def paste():
|
||||
actions.key("ctrl-shift-v")
|
||||
|
||||
def copy():
|
||||
actions.key("ctrl-shift-c")
|
||||
|
||||
def find(text: str = None):
|
||||
actions.key("ctrl-shift-f")
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
def delete_line():
|
||||
actions.edit.line_start()
|
||||
actions.key("ctrl-k")
|
||||
|
||||
# afaik not possible in gnome-terminal
|
||||
def extend_left():
|
||||
pass
|
||||
|
||||
def extend_right():
|
||||
pass
|
||||
|
||||
def extend_up():
|
||||
pass
|
||||
|
||||
def extend_down():
|
||||
pass
|
||||
|
||||
def extend_word_left():
|
||||
pass
|
||||
|
||||
def extend_word_right():
|
||||
pass
|
|
@ -0,0 +1,8 @@
|
|||
app: gnome_terminal
|
||||
-
|
||||
# Set tags
|
||||
tag(): terminal
|
||||
tag(): user.tabs
|
||||
tag(): user.generic_unix_shell
|
||||
tag(): user.git
|
||||
tag(): user.kubectl
|
23
talon/user/community/apps/guake/guake_linux.py
Normal file
23
talon/user/community/apps/guake/guake_linux.py
Normal file
|
@ -0,0 +1,23 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
os: linux
|
||||
app: Guake
|
||||
"""
|
||||
ctx.tags = ["user.git", "user.kubectl", "user.tabs", "terminal"]
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
def tab_open():
|
||||
actions.key("ctrl-shift-t")
|
||||
|
||||
def tab_close():
|
||||
actions.key("ctrl-shift-w")
|
||||
|
||||
def tab_next():
|
||||
actions.key("ctrl-pagedown")
|
||||
|
||||
def tab_previous():
|
||||
actions.key("ctrl-pageup")
|
118
talon/user/community/apps/i3wm/i3wm.py
Normal file
118
talon/user/community/apps/i3wm/i3wm.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
import subprocess
|
||||
from typing import Optional, Union
|
||||
|
||||
from talon import Context, Module, actions, settings
|
||||
|
||||
mod = Module()
|
||||
ctx = Context()
|
||||
|
||||
mod.tag("i3wm", desc="tag for loading i3wm related files")
|
||||
mod.setting(
|
||||
"i3_config_path",
|
||||
type=str,
|
||||
default="~/.i3/config",
|
||||
desc="Where to find the configuration path",
|
||||
)
|
||||
mod.setting(
|
||||
"i3_mod_key",
|
||||
type=str,
|
||||
default="super",
|
||||
desc="The default key to use for i3wm commands",
|
||||
)
|
||||
|
||||
ctx.matches = """
|
||||
tag: user.i3wm
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
def window_close():
|
||||
subprocess.check_call(("i3-msg", "kill"))
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def i3wm_mode(name: str):
|
||||
"""Switch i3 mode"""
|
||||
subprocess.check_call(("i3-msg", "mode", name))
|
||||
|
||||
def i3wm_reload():
|
||||
"""Reload the i3 config"""
|
||||
subprocess.check_call(("i3-msg", "reload"))
|
||||
|
||||
def i3wm_restart():
|
||||
"""Restart the window manager"""
|
||||
subprocess.check_call(("i3-msg", "restart"))
|
||||
|
||||
def i3wm_layout(layout: Optional[str] = None):
|
||||
"""Change to specified layout. Toggle split if unspecified."""
|
||||
if layout is None:
|
||||
subprocess.check_call(("i3-msg", "layout", "toggle", "split"))
|
||||
else:
|
||||
subprocess.check_call(("i3-msg", "layout", layout))
|
||||
|
||||
def i3wm_fullscreen():
|
||||
"""Fullscreen the current container"""
|
||||
subprocess.check_call(("i3-msg", "fullscreen"))
|
||||
|
||||
def i3wm_split(direction: str):
|
||||
"""Split the focused container"""
|
||||
subprocess.check_call(("i3-msg", "split", direction))
|
||||
|
||||
def i3wm_float():
|
||||
"""Toggle whether the focused container should float."""
|
||||
subprocess.check_call(("i3-msg", "floating", "toggle"))
|
||||
|
||||
def i3wm_launch():
|
||||
"""Trigger the i3 launcher: ex rofi"""
|
||||
key = settings.get("user.i3_mod_key")
|
||||
actions.key(f"{key}-d")
|
||||
|
||||
def i3wm_shell():
|
||||
"""Launch a shell"""
|
||||
key = settings.get("user.i3_mod_key")
|
||||
actions.key(f"{key}-enter")
|
||||
|
||||
def i3wm_focus(what: str):
|
||||
"""Move focus"""
|
||||
subprocess.check_call(("i3-msg", "focus", what))
|
||||
|
||||
def i3wm_switch_to_workspace(which: Union[str, int]):
|
||||
"""Focus the specified workspace"""
|
||||
if isinstance(which, int):
|
||||
subprocess.check_call(("i3-msg", "workspace", "number", str(which)))
|
||||
else:
|
||||
subprocess.check_call(("i3-msg", "workspace", which))
|
||||
|
||||
def i3wm_show_scratchpad():
|
||||
"""Focus/cycle/hide the scratchpad"""
|
||||
subprocess.check_call(("i3-msg", "scratchpad", "show"))
|
||||
|
||||
def i3wm_move(to: str):
|
||||
"""Move the focused container"""
|
||||
subprocess.check_call(("i3-msg", "move", to))
|
||||
|
||||
def i3wm_move_to_workspace(which: Union[str, int]):
|
||||
"""Move the focused container to the specified workspace"""
|
||||
if isinstance(which, int):
|
||||
subprocess.check_call(
|
||||
("i3-msg", "move", "container", "to", "workspace", "number", str(which))
|
||||
)
|
||||
else:
|
||||
subprocess.check_call(
|
||||
("i3-msg", "move", "container", "to", "workspace", which)
|
||||
)
|
||||
|
||||
def i3wm_move_to_output(which: str):
|
||||
"""Move the focused container to the specified output."""
|
||||
subprocess.check_call(("i3-msg", "move", "container", "to", "output", which))
|
||||
|
||||
def i3wm_move_position(where: str):
|
||||
"""Move the focused container to the specified position."""
|
||||
subprocess.check_call(("i3-msg", "move", "position", where))
|
||||
|
||||
def i3wm_lock():
|
||||
"""Trigger the lock screen"""
|
||||
key = settings.get("user.i3_mod_key")
|
||||
actions.key(f"{key}-shift-x")
|
99
talon/user/community/apps/i3wm/i3wm.talon
Normal file
99
talon/user/community/apps/i3wm/i3wm.talon
Normal file
|
@ -0,0 +1,99 @@
|
|||
# NOTE: If you want to use i3wm you must enable the tag settings.talon. i.e.: `tag(): user.i3wm`
|
||||
os: linux
|
||||
tag: user.i3wm
|
||||
-
|
||||
port <number_small>: user.i3wm_switch_to_workspace(number_small)
|
||||
(port flip | flipper): user.i3wm_switch_to_workspace("back_and_forth")
|
||||
port right: user.i3wm_switch_to_workspace("next")
|
||||
port left: user.i3wm_switch_to_workspace("prev")
|
||||
|
||||
(win | window) left: user.i3wm_focus("left")
|
||||
(win | window) right: user.i3wm_focus("right")
|
||||
(win | window) up: user.i3wm_focus("up")
|
||||
(win | window) down: user.i3wm_focus("down")
|
||||
(win | window) kill: app.window_close()
|
||||
(win | window) stacking: user.i3wm_layout("stacking")
|
||||
(win | window) default: user.i3wm_layout()
|
||||
(win | window) tabbed: user.i3wm_layout("tabbed")
|
||||
|
||||
reload i three config: user.i3wm_reload()
|
||||
restart i three: user.i3wm_restart()
|
||||
|
||||
(full screen | scuba): user.i3wm_fullscreen()
|
||||
toggle floating: user.i3wm_float()
|
||||
focus floating: user.i3wm_focus("mode_toggle")
|
||||
center window: user.i3wm_move_position("center")
|
||||
resize mode: user.i3wm_mode("resize")
|
||||
focus parent: user.i3wm_focus("parent")
|
||||
focus child: user.i3wm_focus("child")
|
||||
|
||||
# resize helpers
|
||||
grow window:
|
||||
user.i3wm_mode("resize")
|
||||
key(right:10)
|
||||
key(down:10)
|
||||
# escape resize mode
|
||||
key(escape)
|
||||
# center window
|
||||
sleep(200ms)
|
||||
user.i3wm_move_position("center")
|
||||
|
||||
# resize helpers
|
||||
shrink window:
|
||||
user.i3wm_mode("resize")
|
||||
key(left:10)
|
||||
key(up:10)
|
||||
# escape resize mode
|
||||
key(escape)
|
||||
# center window
|
||||
sleep(200ms)
|
||||
user.i3wm_move_position("center")
|
||||
|
||||
horizontal (shell | terminal):
|
||||
user.i3wm_split("h")
|
||||
user.i3wm_shell()
|
||||
|
||||
vertical (shell | terminal):
|
||||
user.i3wm_split("v")
|
||||
user.i3wm_shell()
|
||||
|
||||
# XXX - just replace with shuffle eventually?
|
||||
# XXX - like also need to match the generic talon commands
|
||||
(shuffle | move (win | window) [to] port) <number_small>:
|
||||
user.i3wm_move_to_workspace(number_small)
|
||||
(shuffle | move (win | window) [to] last port):
|
||||
user.i3wm_move_to_workspace("back_and_forth")
|
||||
(shuffle | move) flipper: user.i3wm_move_to_workspace("back_and_forth")
|
||||
(shuffle | move (win | window) left): user.i3wm_move("left")
|
||||
(shuffle | move (win | window) right): user.i3wm_move("right")
|
||||
(shuffle | move (win | window) up): user.i3wm_move("up")
|
||||
(shuffle | move (win | window) down): user.i3wm_move("down")
|
||||
|
||||
(win | window) horizontal: user.i3wm_split("h")
|
||||
(win | window) vertical: user.i3wm_split("v")
|
||||
|
||||
make scratch: user.i3wm_move("scratchpad")
|
||||
[(show | hide)] scratch: user.i3wm_show_scratchpad()
|
||||
next scratch:
|
||||
user.i3wm_show_scratchpad()
|
||||
user.i3wm_show_scratchpad()
|
||||
|
||||
# these rely on the user settings for the mod key. see i3wm.py Actions class
|
||||
launch: user.i3wm_launch()
|
||||
launch <user.text>:
|
||||
user.i3wm_launch()
|
||||
sleep(100ms)
|
||||
insert("{text}")
|
||||
lock screen: user.i3wm_lock()
|
||||
|
||||
(launch shell | koopa): user.i3wm_shell()
|
||||
|
||||
new scratch (shell | window):
|
||||
user.i3wm_shell()
|
||||
sleep(200ms)
|
||||
user.i3wm_move("scratchpad")
|
||||
user.i3wm_show_scratchpad()
|
||||
|
||||
murder:
|
||||
user.deprecate_command("2023-02-04", "murder", "win kill")
|
||||
app.window_close()
|
81
talon/user/community/apps/iterm/iterm.py
Normal file
81
talon/user/community/apps/iterm/iterm.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
mod.apps.iterm2 = """
|
||||
os: mac
|
||||
and app.bundle: com.googlecode.iterm2
|
||||
"""
|
||||
ctx.matches = r"""
|
||||
app: iterm2
|
||||
"""
|
||||
|
||||
directories_to_remap = {}
|
||||
directories_to_exclude = {}
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def line_start():
|
||||
actions.key("home")
|
||||
|
||||
def line_end():
|
||||
actions.key("end")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# def file_manager_current_path():
|
||||
# title = ui.active_window().title
|
||||
|
||||
# if "~" in title:
|
||||
# title = os.path.expanduser(title)
|
||||
|
||||
# if title in directories_to_remap:
|
||||
# title = directories_to_remap[title]
|
||||
|
||||
# if title in directories_to_exclude:
|
||||
# title = None
|
||||
|
||||
# return title
|
||||
|
||||
# def file_manager_show_properties():
|
||||
# """Shows the properties for the file"""
|
||||
|
||||
# def file_manager_open_directory(path: str):
|
||||
# """opens the directory that's already visible in the view"""
|
||||
# actions.insert("cd ")
|
||||
# path = '"{}"'.format(path)
|
||||
# actions.insert(path)
|
||||
# actions.key("enter")
|
||||
# actions.user.file_manager_refresh_title()
|
||||
|
||||
# def file_manager_select_directory(path: str):
|
||||
# """selects the directory"""
|
||||
# actions.insert(path)
|
||||
|
||||
# def file_manager_new_folder(name: str):
|
||||
# """Creates a new folder in a gui filemanager or inserts the command to do so for terminals"""
|
||||
# name = '"{}"'.format(name)
|
||||
|
||||
# actions.insert("mkdir " + name)
|
||||
|
||||
# def file_manager_open_file(path: str):
|
||||
# """opens the file"""
|
||||
# actions.insert(path)
|
||||
# actions.key("enter")
|
||||
|
||||
# def file_manager_select_file(path: str):
|
||||
# """selects the file"""
|
||||
# actions.insert(path)
|
||||
|
||||
def tab_jump(number: int):
|
||||
actions.key(f"cmd-{number}")
|
||||
|
||||
def tab_final():
|
||||
actions.key("cmd-9")
|
||||
|
||||
def terminal_clear_screen():
|
||||
"""Clear screen"""
|
||||
actions.key("ctrl-l")
|
11
talon/user/community/apps/iterm/iterm.talon
Normal file
11
talon/user/community/apps/iterm/iterm.talon
Normal file
|
@ -0,0 +1,11 @@
|
|||
os: mac
|
||||
app: iterm2
|
||||
-
|
||||
tag(): terminal
|
||||
# todo: filemanager support
|
||||
#tag(): user.file_manager
|
||||
tag(): user.generic_unix_shell
|
||||
tag(): user.git
|
||||
tag(): user.kubectl
|
||||
tag(): user.tabs
|
||||
tag(): user.readline
|
376
talon/user/community/apps/jetbrains/jetbrains.py
Normal file
376
talon/user/community/apps/jetbrains/jetbrains.py
Normal file
|
@ -0,0 +1,376 @@
|
|||
import os
|
||||
import os.path
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import requests
|
||||
from talon import Context, Module, actions, app, clip, ui
|
||||
|
||||
# Courtesy of https://github.com/anonfunc/talon-user/blob/master/apps/jetbrains.py
|
||||
|
||||
# Each IDE gets its own port, as otherwise you wouldn't be able
|
||||
# to run two at the same time and switch between them.
|
||||
# Note that MPS and IntelliJ ultimate will conflict...
|
||||
port_mapping = {
|
||||
"com.google.android.studio": 8652,
|
||||
"com.jetbrains.AppCode": 8655,
|
||||
"com.jetbrains.CLion": 8657,
|
||||
"com.jetbrains.datagrip": 8664,
|
||||
"com.jetbrains.goland-EAP": 8659,
|
||||
"com.jetbrains.goland": 8659,
|
||||
"com.jetbrains.intellij-EAP": 8653,
|
||||
"com.jetbrains.intellij.ce": 8654,
|
||||
"com.jetbrains.intellij": 8653,
|
||||
"com.jetbrains.PhpStorm": 8662,
|
||||
"com.jetbrains.pycharm": 8658,
|
||||
"com.jetbrains.rider": 8660,
|
||||
"com.jetbrains.rubymine": 8661,
|
||||
"com.jetbrains.rubymine-EAP": 8661,
|
||||
"com.jetbrains.WebStorm": 8663,
|
||||
"google-android-studio": 8652,
|
||||
"idea64.exe": 8653,
|
||||
"IntelliJ IDEA": 8653,
|
||||
"jetbrains-appcode": 8655,
|
||||
"jetbrains-clion": 8657,
|
||||
"jetbrains-datagrip": 8664,
|
||||
"jetbrains-goland-eap": 8659,
|
||||
"jetbrains-goland": 8659,
|
||||
"jetbrains-idea-ce": 8654,
|
||||
"jetbrains-idea-eap": 8653,
|
||||
"jetbrains-idea": 8653,
|
||||
"jetbrains-phpstorm": 8662,
|
||||
"jetbrains-pycharm-ce": 8658,
|
||||
"jetbrains-pycharm": 8658,
|
||||
"jetbrains-rider": 8660,
|
||||
"JetBrains Rider": 8660,
|
||||
"jetbrains-rubymine": 8661,
|
||||
"jetbrains-rubymine-eap": 8661,
|
||||
"jetbrains-studio": 8652,
|
||||
"jetbrains-webstorm": 8663,
|
||||
"RubyMine": 8661,
|
||||
"RubyMine-EAP": 8661,
|
||||
"PyCharm": 8658,
|
||||
"pycharm64.exe": 8658,
|
||||
"WebStorm": 8663,
|
||||
"webstorm64.exe": 8663,
|
||||
}
|
||||
|
||||
|
||||
def _get_nonce(port: int, file_prefix: str) -> Optional[str]:
|
||||
file_name = file_prefix + str(port)
|
||||
try:
|
||||
with open(os.path.join(tempfile.gettempdir(), file_name)) as fh:
|
||||
return fh.read()
|
||||
except FileNotFoundError:
|
||||
try:
|
||||
with open(Path.home() / file_name) as fh:
|
||||
return fh.read()
|
||||
except FileNotFoundError:
|
||||
print(f"Could not find {file_name} in tmp or home")
|
||||
return None
|
||||
except OSError as e:
|
||||
print(e)
|
||||
return None
|
||||
|
||||
|
||||
def send_idea_command(cmd: str) -> str:
|
||||
active_app = ui.active_app()
|
||||
bundle = active_app.bundle or active_app.name
|
||||
port = port_mapping.get(bundle, None)
|
||||
if not port:
|
||||
raise Exception(f"unknown application {bundle}")
|
||||
nonce = _get_nonce(port, ".vcidea_") or _get_nonce(port, "vcidea_")
|
||||
if not nonce:
|
||||
raise FileNotFoundError(f"Couldn't find IDEA nonce file for port {port}")
|
||||
|
||||
response = requests.get(
|
||||
f"http://localhost:{port}/{nonce}/{cmd}",
|
||||
proxies={"http": None, "https": None},
|
||||
timeout=(0.05, 3.05),
|
||||
)
|
||||
response.raise_for_status()
|
||||
return response.text
|
||||
|
||||
|
||||
def get_idea_location() -> list[str]:
|
||||
return send_idea_command("location").split()
|
||||
|
||||
|
||||
ctx = Context()
|
||||
mod = Module()
|
||||
|
||||
mod.apps.jetbrains = "app.name: /jetbrains/"
|
||||
mod.apps.jetbrains = "app.name: CLion"
|
||||
mod.apps.jetbrains = "app.name: IntelliJ IDEA"
|
||||
mod.apps.jetbrains = "app.name: PhpStorm"
|
||||
mod.apps.jetbrains = "app.name: PyCharm"
|
||||
mod.apps.jetbrains = "app.name: WebStorm"
|
||||
mod.apps.jetbrains = "app.name: RubyMine"
|
||||
mod.apps.jetbrains = "app.name: RubyMine-EAP"
|
||||
mod.apps.jetbrains = "app.name: DataGrip"
|
||||
mod.apps.jetbrains = """
|
||||
os: mac
|
||||
and app.bundle: com.google.android.studio
|
||||
"""
|
||||
# windows
|
||||
mod.apps.jetbrains = r"app.exe: /^idea64\.exe$/i"
|
||||
mod.apps.jetbrains = r"app.exe: /^PyCharm64\.exe$/i"
|
||||
mod.apps.jetbrains = r"app.exe: /^webstorm64\.exe$/i"
|
||||
mod.apps.jetbrains = """
|
||||
os: mac
|
||||
and app.bundle: com.jetbrains.pycharm
|
||||
os: mac
|
||||
and app.bundle: com.jetbrains.rider
|
||||
"""
|
||||
mod.apps.jetbrains = r"""
|
||||
os: windows
|
||||
and app.name: JetBrains Rider
|
||||
os: windows
|
||||
and app.exe: /^rider64\.exe$/i
|
||||
"""
|
||||
|
||||
|
||||
@mod.action_class
|
||||
class Actions:
|
||||
def idea(commands: str):
|
||||
"""Send a command to Jetbrains product"""
|
||||
command_list = commands.split(",")
|
||||
try:
|
||||
for cmd in command_list:
|
||||
if cmd:
|
||||
send_idea_command(cmd.strip())
|
||||
actions.sleep(0.1)
|
||||
except Exception as e:
|
||||
app.notify(e)
|
||||
raise
|
||||
|
||||
def idea_grab(times: int):
|
||||
"""Copies specified number of words to the left"""
|
||||
old_clip = clip.get()
|
||||
try:
|
||||
original_line, original_column = get_idea_location()
|
||||
for _ in range(times):
|
||||
send_idea_command("action EditorSelectWord")
|
||||
send_idea_command("action EditorCopy")
|
||||
send_idea_command(f"goto {original_line} {original_column}")
|
||||
send_idea_command("action EditorPaste")
|
||||
finally:
|
||||
clip.set(old_clip)
|
||||
|
||||
|
||||
ctx.matches = r"""
|
||||
app: jetbrains
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
def tab_next():
|
||||
actions.user.idea("action NextTab")
|
||||
|
||||
def tab_previous():
|
||||
actions.user.idea("action PreviousTab")
|
||||
|
||||
def tab_close():
|
||||
actions.user.idea("action CloseContent")
|
||||
|
||||
def tab_reopen():
|
||||
actions.user.idea("action ReopenClosedTab")
|
||||
|
||||
|
||||
@ctx.action_class("code")
|
||||
class CodeActions:
|
||||
# talon code actions
|
||||
def toggle_comment():
|
||||
actions.user.idea("action CommentByLineComment")
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
# talon edit actions
|
||||
def copy():
|
||||
actions.user.idea("action EditorCopy")
|
||||
|
||||
def cut():
|
||||
actions.user.idea("action EditorCut")
|
||||
|
||||
def delete():
|
||||
actions.user.idea("action EditorBackSpace")
|
||||
|
||||
def paste():
|
||||
actions.user.idea("action EditorPaste")
|
||||
|
||||
def find_next():
|
||||
actions.user.idea("action FindNext")
|
||||
|
||||
def find_previous():
|
||||
actions.user.idea("action FindPrevious")
|
||||
|
||||
def find(text: str = None):
|
||||
actions.user.idea("action Find")
|
||||
if text:
|
||||
actions.insert(text)
|
||||
|
||||
def line_clone():
|
||||
actions.user.idea("action EditorDuplicate")
|
||||
|
||||
def line_swap_down():
|
||||
actions.user.idea("action MoveLineDown")
|
||||
|
||||
def line_swap_up():
|
||||
actions.user.idea("action MoveLineUp")
|
||||
|
||||
def indent_more():
|
||||
actions.user.idea("action EditorIndentLineOrSelection")
|
||||
|
||||
def indent_less():
|
||||
actions.user.idea("action EditorUnindentSelection")
|
||||
|
||||
def select_line(n: int = None):
|
||||
actions.user.idea("action EditorSelectLine")
|
||||
|
||||
def select_word():
|
||||
actions.user.idea("action EditorSelectWord")
|
||||
|
||||
def select_all():
|
||||
actions.user.idea("action $SelectAll")
|
||||
|
||||
def file_start():
|
||||
actions.user.idea("action EditorTextStart")
|
||||
|
||||
def file_end():
|
||||
actions.user.idea("action EditorTextEnd")
|
||||
|
||||
def extend_file_start():
|
||||
actions.user.idea("action EditorTextStartWithSelection")
|
||||
|
||||
def extend_file_end():
|
||||
actions.user.idea("action EditorTextEndWithSelection")
|
||||
|
||||
def extend_word_left():
|
||||
actions.user.idea("action EditorPreviousWordWithSelection")
|
||||
|
||||
def extend_word_right():
|
||||
actions.user.idea("action EditorNextWordWithSelection")
|
||||
|
||||
def jump_line(n: int):
|
||||
actions.user.idea(f"goto {n} 0")
|
||||
# move the cursor to the first nonwhite space character of the line
|
||||
actions.user.idea("action EditorLineEnd")
|
||||
actions.user.idea("action EditorLineStart")
|
||||
|
||||
|
||||
@ctx.action_class("win")
|
||||
class WinActions:
|
||||
def filename() -> str:
|
||||
title: str = actions.win.title()
|
||||
result = title.split()
|
||||
|
||||
# iterate over reversed result
|
||||
# to support titles such as
|
||||
# Class.Library2 – a.js [.workspace]
|
||||
for word in reversed(result):
|
||||
if not word.startswith("[") and "." in word:
|
||||
return word
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def tab_jump(number: int):
|
||||
# depends on plugin GoToTabs
|
||||
if number < 10:
|
||||
actions.user.idea(f"action GoToTab{number}")
|
||||
|
||||
def extend_until_line(line: int):
|
||||
actions.user.idea(f"extend {line}")
|
||||
|
||||
def select_range(line_start: int, line_end: int):
|
||||
# if it's a single line, select the entire thing including the ending new-line5
|
||||
if line_start == line_end:
|
||||
actions.user.idea(f"goto {line_start} 0")
|
||||
actions.user.idea("action EditorSelectLine")
|
||||
else:
|
||||
actions.user.idea(f"range {line_start} {line_end}")
|
||||
|
||||
def extend_camel_left():
|
||||
actions.user.idea("action EditorPreviousWordInDifferentHumpsModeWithSelection")
|
||||
|
||||
def extend_camel_right():
|
||||
actions.user.idea("action EditorNextWordInDifferentHumpsModeWithSelection")
|
||||
|
||||
def camel_left():
|
||||
actions.user.idea("action EditorPreviousWordInDifferentHumpsMode")
|
||||
|
||||
def camel_right():
|
||||
actions.user.idea("action EditorNextWordInDifferentHumpsMode")
|
||||
|
||||
def command_search(command: str = ""):
|
||||
actions.user.idea("action GotoAction")
|
||||
if command != "":
|
||||
actions.insert(command)
|
||||
|
||||
def line_clone(line: int):
|
||||
actions.user.idea(f"clone {line}")
|
||||
|
||||
# multi-cursor tag functions
|
||||
def multi_cursor_enable():
|
||||
actions.skip()
|
||||
|
||||
def multi_cursor_disable():
|
||||
actions.key("escape")
|
||||
|
||||
def multi_cursor_add_above():
|
||||
actions.user.idea("action EditorCloneCaretAbove")
|
||||
|
||||
def multi_cursor_add_below():
|
||||
actions.user.idea("action EditorCloneCaretBelow")
|
||||
|
||||
def multi_cursor_select_fewer_occurrences():
|
||||
actions.user.idea("action UnselectPreviousOccurrence")
|
||||
|
||||
def multi_cursor_select_more_occurrences():
|
||||
actions.user.idea("action SelectNextOccurrence")
|
||||
|
||||
# def multi_cursor_skip_occurrence():
|
||||
def multi_cursor_select_all_occurrences():
|
||||
actions.user.idea("action SelectAllOccurrences")
|
||||
|
||||
def multi_cursor_add_to_line_ends():
|
||||
actions.user.idea("action EditorAddCaretPerSelectedLine")
|
||||
|
||||
# splits tag functions
|
||||
# def split_window_right():
|
||||
# actions.user.idea("action OpenInRightSplit")
|
||||
# def split_window_left():
|
||||
# def split_window_down():
|
||||
# def split_window_up():
|
||||
def split_window_vertically():
|
||||
actions.user.idea("action SplitVertically")
|
||||
|
||||
def split_window_horizontally():
|
||||
actions.user.idea("action SplitHorizontally")
|
||||
|
||||
def split_flip():
|
||||
actions.user.idea("action ChangeSplitOrientation")
|
||||
|
||||
def split_maximize():
|
||||
actions.key("ctrl-shift-f12")
|
||||
|
||||
def split_reset():
|
||||
actions.key("shift-f12")
|
||||
|
||||
# def split_window():
|
||||
def split_clear():
|
||||
actions.user.idea("action Unsplit")
|
||||
|
||||
def split_clear_all():
|
||||
actions.user.idea("action UnsplitAll")
|
||||
|
||||
def split_next():
|
||||
actions.user.idea("action NextSplitter")
|
||||
|
||||
# def split_last():
|
||||
# def split_number(index: int):
|
286
talon/user/community/apps/jetbrains/jetbrains.talon
Normal file
286
talon/user/community/apps/jetbrains/jetbrains.talon
Normal file
|
@ -0,0 +1,286 @@
|
|||
# Requires https://plugins.jetbrains.com/plugin/10504-voice-code-idea
|
||||
app: jetbrains
|
||||
-
|
||||
tag(): user.line_commands
|
||||
tag(): user.multiple_cursors
|
||||
tag(): user.splits
|
||||
tag(): user.tabs
|
||||
tag(): user.command_search
|
||||
# multiple_cursors.py support end
|
||||
|
||||
# Auto complete
|
||||
complete: user.idea("action CodeCompletion")
|
||||
perfect: user.idea("action CodeCompletion,action CodeCompletion")
|
||||
smart: user.idea("action SmartTypeCompletion")
|
||||
(done | finish): user.idea("action EditorCompleteStatement")
|
||||
# Copying
|
||||
grab <number>: user.idea_grab(number)
|
||||
action [<user.text>]: user.deprecate_command("2024-09-02", "action", "please")
|
||||
# Refactoring
|
||||
refactor: user.idea("action Refactorings.QuickListPopupAction")
|
||||
refactor <user.text>:
|
||||
user.idea("action Refactorings.QuickListPopupAction")
|
||||
insert(text)
|
||||
extract variable: user.idea("action IntroduceVariable")
|
||||
extract field: user.idea("action IntroduceField")
|
||||
extract constant: user.idea("action IntroduceConstant")
|
||||
extract parameter: user.idea("action IntroduceParameter")
|
||||
extract interface: user.idea("action ExtractInterface")
|
||||
extract method: user.idea("action ExtractMethod")
|
||||
refactor in line: user.idea("action Inline")
|
||||
refactor move: user.idea("action Move")
|
||||
refactor rename: user.idea("action RenameElement")
|
||||
rename file: user.idea("action RenameFile")
|
||||
fix (format | formatting): user.idea("action ReformatCode")
|
||||
fix imports: user.idea("action OptimizeImports")
|
||||
#navigation
|
||||
(go declaration | follow): user.idea("action GotoDeclaration")
|
||||
go implementation: user.idea("action GotoImplementation")
|
||||
go usage: user.idea("action FindUsages")
|
||||
go type: user.idea("action GotoTypeDeclaration")
|
||||
go test: user.idea("action GotoTest")
|
||||
go back: user.idea("action Back")
|
||||
go forward: user.idea("action Forward")
|
||||
# Search
|
||||
find (everywhere | all): user.idea("action SearchEverywhere")
|
||||
find (everywhere | all) <user.text> [over]:
|
||||
user.idea("action SearchEverywhere")
|
||||
sleep(500ms)
|
||||
insert(text)
|
||||
(search | find) class: user.idea("action GotoClass")
|
||||
(search | find) file: user.idea("action GotoFile")
|
||||
(search | find) path: user.idea("action FindInPath")
|
||||
(search | find) symbol: user.idea("action GotoSymbol")
|
||||
(search | find) symbol <user.text>$:
|
||||
user.idea("action GotoSymbol")
|
||||
insert(text)
|
||||
key("enter")
|
||||
recent: user.idea("action RecentFiles")
|
||||
|
||||
surround [this] with <user.text> [over]:
|
||||
idea("action SurroundWith")
|
||||
sleep(500ms)
|
||||
insert(text)
|
||||
# Making these longer to reduce collisions with real code dictation.
|
||||
insert generated <user.text> [over]:
|
||||
user.idea("action Generate")
|
||||
sleep(500ms)
|
||||
insert(text)
|
||||
insert template <user.text> [over]:
|
||||
idea("action InsertLiveTemplate")
|
||||
sleep(500ms)
|
||||
insert(text)
|
||||
create (template | snippet): user.idea("action SaveAsTemplate")
|
||||
# Recording
|
||||
toggle recording: user.idea("action StartStopMacroRecording")
|
||||
change (recording | recordings): user.idea("action EditMacros")
|
||||
play recording: user.idea("action PlaybackLastMacro")
|
||||
play recording <user.text> [over]:
|
||||
idea("action PlaySavedMacrosAction")
|
||||
insert(text)
|
||||
sleep(500ms)
|
||||
Key("enter")
|
||||
# Marks
|
||||
go mark: user.idea("action ShowBookmarks")
|
||||
toggle mark: user.idea("action ToggleBookmark")
|
||||
go next mark: user.idea("action GotoNextBookmark")
|
||||
go last mark: user.idea("action GotoPreviousBookmark")
|
||||
toggle mark <number>: user.idea("action ToggleBookmark{number}")
|
||||
go mark <number>: user.idea("action GotoBookmark{number}")
|
||||
# Folding
|
||||
expand deep: user.idea("action ExpandRegionRecursively")
|
||||
expand all: user.idea("action ExpandAllRegions")
|
||||
collapse deep: user.idea("action CollapseRegionRecursively")
|
||||
collapse all: user.idea("action CollapseAllRegions")
|
||||
# miscellaneous
|
||||
# XXX These might be better than the structural ones depending on language.
|
||||
go next (method | function): user.idea("action MethodDown")
|
||||
go last (method | function): user.idea("action MethodUp")
|
||||
# Clipboard
|
||||
clippings: user.idea("action PasteMultiple")
|
||||
copy path: user.idea("action CopyPaths")
|
||||
copy reference: user.idea("action CopyReference")
|
||||
copy pretty: user.idea("action CopyAsRichText")
|
||||
# File Creation
|
||||
create sibling: user.idea("action NewElementSamePlace")
|
||||
create sibling <user.text> [over]:
|
||||
user.idea("action NewElementSamePlace")
|
||||
sleep(500ms)
|
||||
insert(text)
|
||||
create file: user.idea("action NewElement")
|
||||
create file <user.text> [over]:
|
||||
user.idea("action NewElement")
|
||||
sleep(500ms)
|
||||
insert(text)
|
||||
# Task Management
|
||||
go task: user.idea("action tasks.goto")
|
||||
go browser task: user.idea("action tasks.open.in.browser")
|
||||
switch task: user.idea("action tasks.switch")
|
||||
clear task: user.idea("action tasks.close")
|
||||
configure servers: user.idea("action tasks.configure.servers")
|
||||
# Git / Github (not using verb-noun-adjective pattern, mirroring terminal commands.)
|
||||
git pull: user.idea("action Vcs.UpdateProject")
|
||||
git commit: user.idea("action CheckinProject")
|
||||
git push: user.idea("action CheckinProject")
|
||||
git log: user.idea("action Vcs.ShowTabbedFileHistory")
|
||||
git browse: user.idea("action Github.Open.In.Browser")
|
||||
git (gets | gist): user.idea("action Github.Create.Gist")
|
||||
git (pull request | request): user.idea("action Github.Create.Pull.Request")
|
||||
git (view | show | list) (requests | request):
|
||||
user.idea("action Github.View.Pull.Request")
|
||||
git (annotate | blame): user.idea("action Annotate")
|
||||
git menu: user.idea("action Vcs.QuickListPopupAction")
|
||||
# Tool windows:
|
||||
# Toggling various tool windows
|
||||
toggle project: user.idea("action ActivateProjectToolWindow")
|
||||
toggle find: user.idea("action ActivateFindToolWindow")
|
||||
toggle run: user.idea("action ActivateRunToolWindow")
|
||||
toggle debug: user.idea("action ActivateDebugToolWindow")
|
||||
toggle events: user.idea("action ActivateEventLogToolWindow")
|
||||
toggle terminal: user.idea("action ActivateTerminalToolWindow")
|
||||
toggle git: user.idea("action ActivateVersionControlToolWindow")
|
||||
toggle structure: user.idea("action ActivateStructureToolWindow")
|
||||
toggle database: user.idea("action ActivateDatabaseToolWindow")
|
||||
toggle database changes: user.idea("action ActivateDatabaseChangesToolWindow")
|
||||
toggle make: user.idea("action ActivatemakeToolWindow")
|
||||
toggle to do: user.idea("action ActivateTODOToolWindow")
|
||||
toggle docker: user.idea("action ActivateDockerToolWindow")
|
||||
toggle favorites: user.idea("action ActivateFavoritesToolWindow")
|
||||
toggle last: user.idea("action JumpToLastWindow")
|
||||
# Pin/dock/float
|
||||
toggle pinned: user.idea("action TogglePinnedMode")
|
||||
toggle docked: user.idea("action ToggleDockMode")
|
||||
toggle floating: user.idea("action ToggleFloatingMode")
|
||||
toggle windowed: user.idea("action ToggleWindowedMode")
|
||||
toggle split: user.idea("action ToggleSideMode")
|
||||
# Settings, not windows
|
||||
toggle tool buttons: user.idea("action ViewToolButtons")
|
||||
toggle toolbar: user.idea("action ViewToolBar")
|
||||
toggle status [bar]: user.idea("action ViewStatusBar")
|
||||
toggle navigation [bar]: user.idea("action ViewNavigationBar")
|
||||
# Active editor settings
|
||||
toggle power save: user.idea("action TogglePowerSave")
|
||||
toggle whitespace: user.idea("action EditorToggleShowWhitespaces")
|
||||
toggle indents: user.idea("action EditorToggleShowIndentLines")
|
||||
toggle line numbers: user.idea("action EditorToggleShowLineNumbers")
|
||||
toggle (bread crumbs | breadcrumbs): user.idea("action EditorToggleShowBreadcrumbs")
|
||||
toggle gutter icons: user.idea("action EditorToggleShowGutterIcons")
|
||||
toggle wrap: user.idea("action EditorToggleUseSoftWraps")
|
||||
toggle parameters: user.idea("action ToggleInlineHintsAction")
|
||||
# Toggleable views
|
||||
toggle fullscreen: user.idea("action ToggleFullScreen")
|
||||
toggle distraction [free mode]: user.idea("action ToggleDistractionFreeMode")
|
||||
toggle presentation [mode]: user.idea("action TogglePresentationMode")
|
||||
# Toggle additionals
|
||||
toggle comment: code.toggle_comment()
|
||||
# Quick popups
|
||||
change scheme: user.idea("action QuickChangeScheme")
|
||||
# Always javadoc
|
||||
(toggle | pop) (doc | documentation): user.idea("action QuickJavaDoc")
|
||||
(pop deaf | toggle definition): user.idea("action QuickImplementations")
|
||||
pop type: user.idea("action ExpressionTypeInfo")
|
||||
pop parameters: user.idea("action ParameterInfo")
|
||||
# Breakpoints / debugging
|
||||
go breakpoints: user.idea("action ViewBreakpoints")
|
||||
toggle [line] breakpoint: user.idea("action ToggleLineBreakpoint")
|
||||
toggle method breakpoint: user.idea("action ToggleMethodBreakpoint")
|
||||
run menu: user.idea("action ChooseRunConfiguration")
|
||||
run test: user.idea("action RunClass")
|
||||
run test again: user.idea("action Rerun")
|
||||
debug test: user.idea("action DebugClass")
|
||||
step over: user.idea("action StepOver")
|
||||
step into: user.idea("action StepInto")
|
||||
step smart: user.idea("action SmartStepInto")
|
||||
step to line: user.idea("action RunToCursor")
|
||||
continue: user.idea("action Resume")
|
||||
# Grow / Shrink
|
||||
(grow | shrink) window right: user.idea("action ResizeToolWindowRight")
|
||||
(grow | shrink) window left: user.idea("action ResizeToolWindowLeft")
|
||||
(grow | shrink) window up: user.idea("action ResizeToolWindowUp")
|
||||
(grow | shrink) window down: user.idea("action ResizeToolWindowDown")
|
||||
# Movement
|
||||
go next (error | air): user.idea("action GotoNextError")
|
||||
go last (error | air): user.idea("action GotoPreviousError")
|
||||
fix next (error | air):
|
||||
user.idea("action GotoNextError")
|
||||
user.idea("action ShowIntentionActions")
|
||||
fix last (error | air):
|
||||
user.idea("action GotoPreviousError")
|
||||
user.idea("action ShowIntentionActions")
|
||||
# Special Selects
|
||||
select less: user.idea("action EditorUnSelectWord")
|
||||
select (more | this): user.idea("action EditorSelectWord")
|
||||
#jet brains-specific line commands. see line_commands.talon for generic ones
|
||||
expand <number> until <number>:
|
||||
user.select_range(number_1, number_2)
|
||||
user.idea("action ExpandRegion")
|
||||
collapse <number> until <number>:
|
||||
user.select_range(number_1, number_2)
|
||||
user.idea("action CollapseRegion")
|
||||
paste <number> until <number>:
|
||||
user.select_range(number_1, number_2)
|
||||
user.idea("action EditorPaste")
|
||||
refactor <number> until <number>:
|
||||
user.select_range(number_1, number_2)
|
||||
user.idea("action Refactorings.QuickListPopupAction")
|
||||
clone <number>: user.line_clone(number)
|
||||
|
||||
#find/replace
|
||||
clear last <user.text> [over]: user.idea("find prev {text}, action EditorBackSpace")
|
||||
clear next <user.text> [over]: user.idea("find next {text}, action EditorBackSpace")
|
||||
comment last <user.text> [over]:
|
||||
user.idea("find prev {text}, action CommentByLineComment")
|
||||
comment next <user.text> [over]:
|
||||
user.idea("find next {text}, action CommentByLineComment")
|
||||
go last <user.text> [over]: user.idea("find prev {text}, action EditorRight")
|
||||
go next <user.text> [over]: user.idea("find next {text}, action EditorRight")
|
||||
go <number> <user.text> [over]:
|
||||
user.idea("goto {number} 0,find next {text}, action EditorRight")
|
||||
paste last <user.text> [over]:
|
||||
user.idea("find prev {text}, action EditorRight, action EditorPaste")
|
||||
paste next <user.text> [over]:
|
||||
user.idea("find next {text}, action EditorRight, action EditorPaste")
|
||||
refactor <number> <user.text> [over]:
|
||||
user.idea("goto {number} 0,find next {text}, action Refactorings.QuickListPopupAction")
|
||||
refactor last <user.text> [over]:
|
||||
user.idea("find prev {text}, action Refactorings.QuickListPopupAction")
|
||||
refactor next <user.text> [over]:
|
||||
user.idea("find next {text}, action Refactorings.QuickListPopupAction")
|
||||
rename <number> <user.text> [over]:
|
||||
user.idea("goto {number} 0,find next {text}, action RenameElement")
|
||||
rename next <user.text> [over]: user.idea("find next {text}, action RenameElement")
|
||||
rename last <user.text> [over]: user.idea("find prev {text}, action RenameElement")
|
||||
complete <number> <user.text> [over]:
|
||||
user.idea("goto {number} 0,find next {text},action CodeCompletion")
|
||||
complete next <user.text> [over]: user.idea("find next {text},action CodeCompletion")
|
||||
complete last <user.text> [over]: user.idea("find prev {text},action CodeCompletion")
|
||||
quick fix <number> <user.text> [over]:
|
||||
user.idea("goto {number} 0,find next {text},action ShowIntentionActions")
|
||||
quick fix next <user.text> [over]:
|
||||
user.idea("find next {text},action ShowIntentionActions")
|
||||
quick fix last <user.text> [over]:
|
||||
user.idea("find prev {text},action ShowIntentionActions")
|
||||
replace last <user.text> [over]: user.idea("find prev {text}, action EditorPaste")
|
||||
replace next <user.text> [over]: user.idea("find next {text}, action EditorPaste")
|
||||
|
||||
follow <number> <user.text> [over]:
|
||||
user.idea("goto {number} 0,find next {text},action GotoDeclaration")
|
||||
follow next <user.text> [over]: user.idea("find next {text},action GotoDeclaration")
|
||||
follow last <user.text> [over]: user.idea("find prev {text},action GotoDeclaration")
|
||||
|
||||
reference <number> <user.text> [over]:
|
||||
user.idea("goto {number} 0,find next {text},action FindUsages")
|
||||
reference next <user.text> [over]: user.idea("find next {text},action FindUsages")
|
||||
reference last <user.text> [over]: user.idea("find prev {text},action FindUsages")
|
||||
|
||||
select last <user.text> [over]: user.idea("find prev {text}")
|
||||
select next <user.text> [over]: user.idea("find next {text}")
|
||||
select <number> <user.text> [over]: user.idea("goto {number} 0,find next {text}")
|
||||
|
||||
select camel left: user.extend_camel_left()
|
||||
select camel right: user.extend_camel_right()
|
||||
go camel left: user.camel_left()
|
||||
go camel right: user.camel_right()
|
||||
|
||||
# requires plug-in: black-pycharm
|
||||
blacken: user.idea("action BLACKReformatCode")
|
65
talon/user/community/apps/kde_konsole/kde_konsole.py
Normal file
65
talon/user/community/apps/kde_konsole/kde_konsole.py
Normal file
|
@ -0,0 +1,65 @@
|
|||
from talon import Context, actions
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app.name: konsole
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class user_actions:
|
||||
# tabs-tag functions implementations
|
||||
def tab_jump(number):
|
||||
actions.key(f"alt-{number}")
|
||||
|
||||
# tab_final is not supported by konsole by default
|
||||
# but short cut can be configured
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class app_actions:
|
||||
# tabs-tag functions implementations
|
||||
def tab_open():
|
||||
actions.key("ctrl-shift-t")
|
||||
|
||||
def tab_previous():
|
||||
actions.key("shift-left")
|
||||
|
||||
def tab_next():
|
||||
actions.key("shift-right")
|
||||
|
||||
def tab_close():
|
||||
actions.key("ctrl-shift-w")
|
||||
|
||||
def tab_reopen():
|
||||
# TODO: decide whether this notification is good style
|
||||
# (if this function wouldn't be defined here a wrong default would be activated)
|
||||
actions.app.notify("tab reopen is not possible in kde konsole")
|
||||
|
||||
def window_open():
|
||||
actions.key("ctrl-shift-n")
|
||||
|
||||
|
||||
# this overwrites the unfitting parts of linux/edit.py
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def page_down():
|
||||
actions.key("shift-pagedown")
|
||||
|
||||
def page_up():
|
||||
actions.key("shift-pageup")
|
||||
|
||||
def paste():
|
||||
actions.key("ctrl-shift-v")
|
||||
|
||||
def copy():
|
||||
actions.key("ctrl-shift-c")
|
||||
|
||||
def find(text: str = None):
|
||||
actions.key("ctrl-shift-f")
|
||||
if str:
|
||||
actions.insert(text)
|
||||
|
||||
# TODO: fix select line and other selection (like shift-right)
|
||||
# see: https://unix.stackexchange.com/questions/485536/kde-konsole-swallows-shift-left-and-shift-right
|
||||
# also fix extend_left and co
|
17
talon/user/community/apps/kde_konsole/kde_konsole.talon
Normal file
17
talon/user/community/apps/kde_konsole/kde_konsole.talon
Normal file
|
@ -0,0 +1,17 @@
|
|||
os: linux
|
||||
and app.name: konsole
|
||||
-
|
||||
# makes the commands in terminal.talon available
|
||||
tag(): terminal
|
||||
|
||||
# activates the implementation of the commands/functions in terminal.talon
|
||||
tag(): user.generic_unix_shell
|
||||
|
||||
# makes commands for certain applications available
|
||||
# you can deactivate them if you do not use the application
|
||||
tag(): user.git
|
||||
tag(): user.anaconda
|
||||
# tag(): user.kubectl
|
||||
|
||||
tag(): user.tabs
|
||||
# TODO: add file_manager support
|
22
talon/user/community/apps/keepassx/keepassx_linux.talon
Normal file
22
talon/user/community/apps/keepassx/keepassx_linux.talon
Normal file
|
@ -0,0 +1,22 @@
|
|||
app: keepass
|
||||
-
|
||||
# Database
|
||||
open database: key(ctrl-o)
|
||||
save database: key(ctrl-s)
|
||||
close database: key(ctrl-w)
|
||||
lock database: key(ctrl-l)
|
||||
quit: key(ctrl-q)
|
||||
|
||||
# Entries
|
||||
[add] new entry: key(ctrl-n)
|
||||
clone entry: key(ctrl-k)
|
||||
(view | edit) entry: key(ctrl-e)
|
||||
delete entry: key(ctrl-d)
|
||||
copy user [name]: key(ctrl-b)
|
||||
copy password: key(ctrl-c)
|
||||
open (earl | url | link): key(ctrl-u)
|
||||
copy (earl | url | link): key(ctrl-alt-u)
|
||||
find: key(ctrl-f)
|
||||
find <user.text>:
|
||||
key(ctrl-f)
|
||||
insert("{text}")
|
11
talon/user/community/apps/kindle/kindle.py
Normal file
11
talon/user/community/apps/kindle/kindle.py
Normal file
|
@ -0,0 +1,11 @@
|
|||
from talon import Module
|
||||
|
||||
# --- App definition ---
|
||||
mod = Module()
|
||||
mod.apps.kindle = """
|
||||
os: windows
|
||||
and app.name: Kindle
|
||||
os: windows
|
||||
and app.exe: /^kindle\.exe$/i
|
||||
"""
|
||||
# TODO: mac context and implementation
|
4
talon/user/community/apps/kindle/kindle.talon
Normal file
4
talon/user/community/apps/kindle/kindle.talon
Normal file
|
@ -0,0 +1,4 @@
|
|||
app: kindle
|
||||
-
|
||||
# Set tags
|
||||
tag(): user.pages
|
24
talon/user/community/apps/kindle/kindle_win.py
Normal file
24
talon/user/community/apps/kindle/kindle_win.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
from talon import Context, actions
|
||||
|
||||
# Context matching
|
||||
ctx = Context()
|
||||
ctx.matches = """
|
||||
os: windows
|
||||
app: kindle
|
||||
"""
|
||||
|
||||
|
||||
# --- Implement actions ---
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# user.pages
|
||||
def page_next():
|
||||
actions.key("down")
|
||||
|
||||
def page_previous():
|
||||
actions.key("up")
|
||||
|
||||
def page_jump(number: int):
|
||||
actions.key("ctrl-g")
|
||||
actions.insert(str(number))
|
||||
actions.key("enter")
|
26
talon/user/community/apps/kubectl/kubectl.py
Normal file
26
talon/user/community/apps/kubectl/kubectl.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
from talon import Context, Module
|
||||
|
||||
mod = Module()
|
||||
mod.tag("kubectl", desc="tag for enabling kubectl commands in your terminal")
|
||||
kubectl = "kubectl"
|
||||
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
tag: user.kubectl
|
||||
"""
|
||||
|
||||
mod.list("kubectl_action", desc="actions performed by kubectl")
|
||||
ctx.lists["self.kubectl_action"] = ("get", "delete", "describe", "label")
|
||||
|
||||
mod.list("kubectl_object", desc="objects performed by kubectl")
|
||||
ctx.lists["self.kubectl_object"] = (
|
||||
"nodes",
|
||||
"jobs",
|
||||
"pods",
|
||||
"namespaces",
|
||||
"services",
|
||||
"events",
|
||||
"deployments",
|
||||
"replicasets",
|
||||
"daemonsets",
|
||||
)
|
66
talon/user/community/apps/kubectl/kubectl.talon
Normal file
66
talon/user/community/apps/kubectl/kubectl.talon
Normal file
|
@ -0,0 +1,66 @@
|
|||
tag: terminal
|
||||
and tag: user.kubectl
|
||||
-
|
||||
cube [control]: "kubectl "
|
||||
|
||||
cube create: "kubectl create "
|
||||
cube expose: "kubectl expose "
|
||||
cube run: "kubectl run "
|
||||
cube set: "kubectl set "
|
||||
cube run container: "kubectl run-container "
|
||||
|
||||
cube explain: "kubectl explain "
|
||||
cube get: "kubectl get "
|
||||
cube edit: "kubectl edit "
|
||||
cube delete: "kubectl delete "
|
||||
|
||||
cube rollout: "kubectl rollout "
|
||||
cube rolling update: "kubectl rolling-update "
|
||||
cube scale: "kubectl scale "
|
||||
cube auto scale: "kubectl autoscale "
|
||||
|
||||
cube certificate: "kubectl certificate "
|
||||
cube top: "kubectl top "
|
||||
cube drain: "kubectl drain "
|
||||
cube taint: "kubectl taint "
|
||||
cube (cord | cordon): "kubectl cordon "
|
||||
cube (uncord | uncordon): "kubectl uncordon "
|
||||
cube cluster (info | information): "kubectl cluster-info "
|
||||
|
||||
cube describe: "kubectl describe "
|
||||
cube logs: "kubectl logs "
|
||||
cube attach: "kubectl attach "
|
||||
cube exec: "kubectl exec "
|
||||
cube port forward: "kubectl port-forward "
|
||||
cube proxy: "kubectl proxy "
|
||||
cube copy: "kubectl cp "
|
||||
cube auth: "kubectl auth "
|
||||
|
||||
cube diff: "kubectl diff "
|
||||
cube apply: "kubectl apply "
|
||||
cube patch: "kubectl patch "
|
||||
cube replace: "kubectl replace "
|
||||
cube wait: "kubectl wait "
|
||||
cube convert: "kubectl convert "
|
||||
cube customize: "kubectl kustomize "
|
||||
|
||||
cube label: "kubectl label "
|
||||
cube annotate: "kubectl annotate "
|
||||
cube completion: "kubectl completion "
|
||||
|
||||
cube (interface | API): "kubectl api "
|
||||
cube interface resources: "kubectl api-resources "
|
||||
cube interface versions: "kubectl api-versions "
|
||||
cube config: "kubectl config "
|
||||
cube help: "kubectl help "
|
||||
cube plugin: "kubectl plugin "
|
||||
cube version: "kubectl version "
|
||||
|
||||
cube {user.kubectl_action} [{user.kubectl_object}]:
|
||||
insert("kubectl {kubectl_action} ")
|
||||
insert(kubectl_object or "")
|
||||
|
||||
cube detach:
|
||||
key("ctrl-p")
|
||||
key("ctrl-q")
|
||||
cube shell: user.insert_between("kubectl exec -it ", " -- /bin/bash")
|
44
talon/user/community/apps/meld/meld.py
Normal file
44
talon/user/community/apps/meld/meld.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
from talon import Context, Module, actions
|
||||
|
||||
mod = Module()
|
||||
ctx = Context()
|
||||
|
||||
apps = mod.apps
|
||||
apps.meld = """
|
||||
os: windows
|
||||
and app.name: Visual diff and merge tool
|
||||
os: windows
|
||||
and app.exe: meld.exe
|
||||
"""
|
||||
|
||||
ctx.matches = r"""
|
||||
app: meld
|
||||
"""
|
||||
|
||||
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
def tab_open():
|
||||
actions.key("ctrl-n")
|
||||
|
||||
def tab_previous():
|
||||
actions.key("ctrl-alt-pageup")
|
||||
|
||||
def tab_next():
|
||||
actions.key("ctrl-alt-pagedown")
|
||||
|
||||
def tab_reopen():
|
||||
print("Meld does not support this action.")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def tab_jump(number):
|
||||
if number < 10:
|
||||
actions.key(f"alt-{number}")
|
||||
|
||||
def tab_final():
|
||||
print("Meld does not support this action.")
|
||||
|
||||
def tab_duplicate():
|
||||
print("Meld does not support this action.")
|
6
talon/user/community/apps/meld/meld.talon
Normal file
6
talon/user/community/apps/meld/meld.talon
Normal file
|
@ -0,0 +1,6 @@
|
|||
app: meld
|
||||
-
|
||||
tag(): user.tabs
|
||||
|
||||
change next: key(alt-down)
|
||||
change (previous | last): key(alt-up)
|
144
talon/user/community/apps/mintty/mintty_win.py
Normal file
144
talon/user/community/apps/mintty/mintty_win.py
Normal file
|
@ -0,0 +1,144 @@
|
|||
import subprocess
|
||||
|
||||
from talon import Context, Module, actions, settings, ui
|
||||
|
||||
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.generic_unix_shell",
|
||||
"user.file_manager",
|
||||
"user.git",
|
||||
"user.kubectl",
|
||||
]
|
||||
|
||||
directories_to_remap = {}
|
||||
directories_to_exclude = {}
|
||||
|
||||
mod.setting(
|
||||
"cygpath",
|
||||
type=str,
|
||||
default="C:\\cygwin64\\bin\\cygpath.exe",
|
||||
desc="Path to cygpath.exe",
|
||||
)
|
||||
|
||||
|
||||
def get_win_path(cyg_path):
|
||||
path = ""
|
||||
try:
|
||||
si = subprocess.STARTUPINFO()
|
||||
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
path = (
|
||||
subprocess.check_output(
|
||||
[settings.get("user.cygpath"), "-w", cyg_path], startupinfo=si
|
||||
)
|
||||
.strip(b"\n")
|
||||
.decode()
|
||||
)
|
||||
except:
|
||||
path = ""
|
||||
return path
|
||||
|
||||
|
||||
@ctx.action_class("edit")
|
||||
class EditActions:
|
||||
def paste():
|
||||
actions.key("shift-insert")
|
||||
|
||||
def copy():
|
||||
actions.key("ctrl-insert")
|
||||
|
||||
def delete_line():
|
||||
actions.key("ctrl-u")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
def file_manager_open_parent():
|
||||
actions.insert("cd ..")
|
||||
actions.key("enter")
|
||||
|
||||
def file_manager_current_path():
|
||||
path = ui.active_window().title
|
||||
path = get_win_path(path)
|
||||
|
||||
if path in directories_to_remap:
|
||||
path = directories_to_remap[title]
|
||||
|
||||
if path in directories_to_exclude:
|
||||
path = ""
|
||||
return path
|
||||
|
||||
def file_manager_show_properties():
|
||||
"""Shows the properties for the file"""
|
||||
|
||||
def file_manager_open_directory(path: str):
|
||||
"""opens the directory that's already visible in the view"""
|
||||
actions.insert("cd ")
|
||||
path = f'"{path}"'
|
||||
actions.insert(path)
|
||||
actions.key("enter")
|
||||
|
||||
def file_manager_select_directory(path: str):
|
||||
"""selects the directory"""
|
||||
actions.insert(path)
|
||||
|
||||
def file_manager_new_folder(name: str):
|
||||
"""Creates a new folder in a gui filemanager or inserts the command to do so for terminals"""
|
||||
name = f'"{name}"'
|
||||
|
||||
actions.insert("mkdir " + name)
|
||||
|
||||
def file_manager_open_file(path: str):
|
||||
"""opens the file"""
|
||||
actions.insert(path)
|
||||
actions.key("enter")
|
||||
|
||||
def file_manager_select_file(path: str):
|
||||
"""selects the file"""
|
||||
actions.insert(path)
|
||||
|
||||
def file_manager_open_volume(volume: str):
|
||||
"""file_manager_open_volume"""
|
||||
actions.user.file_manager_open_directory(volume)
|
||||
|
||||
def terminal_list_directories():
|
||||
actions.insert("ls")
|
||||
actions.key("enter")
|
||||
|
||||
def terminal_list_all_directories():
|
||||
actions.insert("ls -a")
|
||||
actions.key("enter")
|
||||
|
||||
def terminal_change_directory(path: str):
|
||||
actions.insert(f"cd {path}")
|
||||
if path:
|
||||
actions.key("enter")
|
||||
|
||||
def terminal_change_directory_root():
|
||||
"""Root of current drive"""
|
||||
actions.insert("cd /")
|
||||
actions.key("enter")
|
||||
|
||||
def terminal_clear_screen():
|
||||
"""Clear screen"""
|
||||
actions.key("ctrl-l")
|
||||
|
||||
def terminal_run_last():
|
||||
actions.key("up enter")
|
||||
|
||||
def terminal_kill_all():
|
||||
actions.key("ctrl-c")
|
||||
actions.insert("y")
|
||||
actions.key("enter")
|
66
talon/user/community/apps/nautilus/nautilus.py
Normal file
66
talon/user/community/apps/nautilus/nautilus.py
Normal file
|
@ -0,0 +1,66 @@
|
|||
from talon import Context, Module, actions, clip, ui
|
||||
|
||||
# App definition
|
||||
mod = Module()
|
||||
mod.apps.nautilus = """
|
||||
os: linux
|
||||
and app.exe: nautilus
|
||||
os: linux
|
||||
and app.name: Org.gnome.Nautilus
|
||||
os: linux
|
||||
and app.name: Caja
|
||||
"""
|
||||
|
||||
# Context matching
|
||||
ctx = Context()
|
||||
ctx.matches = r"""
|
||||
app: nautilus
|
||||
"""
|
||||
|
||||
|
||||
# --- Implement actions ---
|
||||
@ctx.action_class("app")
|
||||
class AppActions:
|
||||
# app.tabs
|
||||
def tab_next():
|
||||
actions.key("ctrl-pagedown")
|
||||
|
||||
def tab_previous():
|
||||
actions.key("ctrl-pageup")
|
||||
|
||||
|
||||
@ctx.action_class("user")
|
||||
class UserActions:
|
||||
# user.tabs
|
||||
def tab_jump(number: int):
|
||||
actions.key(f"alt-{number}")
|
||||
|
||||
# user.navigation
|
||||
def go_back():
|
||||
actions.key("alt-left")
|
||||
|
||||
def go_forward():
|
||||
actions.key("alt-right")
|
||||
|
||||
# user.file_manager
|
||||
def file_manager_open_parent():
|
||||
actions.key("alt-up")
|
||||
|
||||
def file_manager_show_properties():
|
||||
actions.key("ctrl-i")
|
||||
|
||||
def file_manager_open_directory(path: str):
|
||||
actions.key("ctrl-l")
|
||||
actions.insert(path)
|
||||
actions.key("enter")
|
||||
|
||||
def file_manager_new_folder(name: str = None):
|
||||
actions.key("ctrl-shift-n")
|
||||
if name:
|
||||
actions.insert(name)
|
||||
|
||||
def file_manager_terminal_here():
|
||||
actions.key("ctrl-l")
|
||||
with clip.capture() as path:
|
||||
actions.edit.copy()
|
||||
ui.launch(path="gnome-terminal", args=[f"--working-directory={path.get()}"])
|
5
talon/user/community/apps/nautilus/nautilus.talon
Normal file
5
talon/user/community/apps/nautilus/nautilus.talon
Normal file
|
@ -0,0 +1,5 @@
|
|||
app: nautilus
|
||||
-
|
||||
# Set tags
|
||||
tag(): user.tabs
|
||||
tag(): user.file_manager
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue