add talon, WIP

This commit is contained in:
Kate 2024-11-15 07:16:59 -07:00
parent 065a7d1e6f
commit cd2440df0f
721 changed files with 14083 additions and 30291 deletions

386
README.md
View file

@ -1,12 +1,382 @@
# Kate's Dotfiles
# community
These are our personal dotfiles -- if you find this link, please don't pass it around. <3
Voice command set for [Talon](https://talonvoice.com/), community-supported.
## Notes
_(Originally called `knausj_talon`, after [its original creator :superhero:](https://github.com/knausj85))_
Most things in here are managed by `NixOS`, nix-darwin`, or `home-manager`. The following things,
however, need to work on native Windows, and thus shouldn't be Nixified:
Can be used on its own, but shines when combined with:
- neovim's configuration
- wezterm's configruation
- xonsh's configruation
- [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 AZ.
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 dont 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`.

View file

@ -207,7 +207,6 @@
stylix
is-hm-standalone
is-droid
talon
;
niri = niri.outputs;
@ -218,6 +217,7 @@
attic = attic.outputs.packages.${system};
esp-dev = esp-dev.outputs.packages.${system};
lix = lix.outputs.packages.${system};
talon = talon.outputs.packages.${system};
# Helper to convert hm modules into NixOS or nix-on-droid modules.
callHm = module: (specialArgs: (import module) specialArgs);
@ -283,7 +283,6 @@
./nixos/hosts/valere.nix
./nixos/configs/steam.nix
./nixos/configs/vmware.nix
./nixos/configs/talon-voice.nix
./nixos/configs/power-saving.nix
];
};

View file

@ -39,4 +39,7 @@
xdg.configFile."task/taskrc".source = ../../../taskwarrior/taskrc;
xdg.dataFile."task/hooks".source = ../../../taskwarrior/hooks;
# talon
home.file.".talon/user".source = ../../../talon;
}

View file

@ -245,7 +245,7 @@ in
"custom/events"
"privacy"
"custom/yubikey"
"wireplumber"
#"wireplumber"
"custom/puckdown"
"battery"
];

View file

@ -4,7 +4,7 @@
#
# vim: et:ts=2:sw=2:
#
{ pkgs, deprekages, lib, ... }:
{ pkgs, deprekages, talon, ... }:
{
# Ensures the system state isn't changed breakingly (e.g. by updating
@ -90,6 +90,7 @@
services.udev.packages = [
pkgs.minipro
talon.default
];
services.fwupd.enable = true;

View file

@ -0,0 +1,2 @@
*.flac
data/

View file

@ -0,0 +1,7 @@
{
"python.formatting.provider": "black",
"python.analysis.stubPath": "/Applications/Talon.app/Contents/Resources/python/lib/python3.9/site-packages",
"cSpell.words": [
"mkfifo"
]
}

View file

@ -0,0 +1,328 @@
# Talon documentation
For up-to-date documentation on Talon's API and features, please visit https://talon.wiki/.
https://talon.wiki/unofficial_talon_docs/ is a great place to learn about Talon files, actions, and voice command definitions.
# knausj_talon
Talon configs for Mac, Windows, and Linux. Very much in progress. This is also intended to work with both Dragon Naturally Speaking and wav2letter.\
Notes:
- commands are subject to change. We do our best to minimize changes, but we are moving to an [object][verb] standard slowly but surely.
- @knausj85 makes extensive use of Talon's eye tracking features, so the grammar for certain programs may be much smaller than you may require.
- The repository was mostly developed with Dragon, so commands are mostly still optimized for that speech engine.
## Linux & Mac setup
Clone repo into `~/.talon/user`
```insert code:
cd ~/.talon/user
git clone git@github.com:knausj85/knausj_talon.git knausj_talon
```
Alternatively, access the directory by right clicking the Talon icon in taskbar, clicking Scripting>Open ~/talon, and navigating to user.
The folder structure should look like:
```insert code:
~/.talon/user/knausj_talon
~/.talon/user/knausj_talon/code
~/.talon/user/knausj_talon/lang
```
## Windows setup
Note: Talon for Windows should be placed in the Program Files directory (or another 'secure' directory): `C:\Program Files\talon` Talon has been signed and utilizes uiAccess for several goodies: this will allow Talon to work with applications that are run as admin.
Clone repo into `%AppData%\Talon\user`
```insert code:
cd %AppData%\Talon\user
git clone git@github.com:knausj85/knausj_talon.git knausj_talon
```
Alternatively, access the directory by right clicking the Talon icon in taskbar, clicking Scripting>Open ~/talon, and navigating to user.
The folder structure should look like:
```insert code:
%AppData%\Talon\user\knausj_talon
%AppData%\Talon\user\knausj_talon\code
%AppData%\Talon\user\knausj_talon\lang
```
## Getting started with Talon
1. `help active` will display the available commands for the active application.
- Available commands can change with the application, or even window title that has focus.
- You may navigate help using the displayed numbers. e.g., `help one one` or `help eleven` to open the 11th item in the help list.
- Without opening help first, you can also search for commands e.g. `help search tab` to display all tab-related commands
- Without opening help first, you can also jump immediately into a particular help context display by recalling the name displayed in help window (based on the name of the .talon file) e.g. `help symbols` or `help visual studio`
- All help-related commands are defined in misc/help.talon and misc/help_open.talon
2. `help alphabet` will display the alphabet
3. `command history` will toggle a display of the recent commands
4. `format help` will display the available formatters with examples.
5. Many useful, basic commands are defined in https://github.com/knausj85/knausj_talon/blob/master/misc/standard.talon#L36
- `undo that` and `redo that` are the default undo/redo commands.
- `paste that`, `copy that`, and `cut that` for pasting/copy/cutting, respectively.
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 here
https://github.com/knausj85/knausj_talon/blob/master/code/keys.py#L6
`help alphabet` will open a window that displays the alphabet. `help close` to hide the window.
Try saying e.g. `air bat cap` to insert abc.
### Keys
Keys are defined in keys.py from line 83 - 182. The alphabet is used for A-Z.
https://github.com/knausj85/knausj_talon/blob/84c6f637ba8304352aa15e01b030e8fa36f4f1a2/code/keys.py#L83
All key commands are defined in keys.talon
https://github.com/knausj85/knausj_talon/blob/master/misc/keys.talon
On Windows, try commands such as
`control air` to press `control-a` and select all.
`super-shift-sun` to press `windows-shift-s` to trigger the screenshot application (Windows 10). Then try `escape` to exit the screenshot application.
On Mac, try commands such as
`command air` to press `command-a` and select all.
`control shift command 4` to press ` ctrl-shift-cmd-4` to trigger the screenshot application. Then try `escape` to exit the screenshot application. Please note the order of the modifiers doesn't matter.
Any combination of the modifiers, symbols, alphabet, numbers and function keys can be executed via voice to execute shorcuts. Out of the box, only the modifier keys (command, shift, alt, super) cannot be triggered by themselves.
### Symbols
Some symbols are defined in keys.py, so you can say e.g. `control colon` to press those keys.
https://github.com/knausj85/knausj_talon/blob/master/code/keys.py#L93
Some other symbols are defined here:
https://github.com/knausj85/knausj_talon/blob/master/text/symbols.talon
### Formatters
`format help` will display the available formatters with examples of the output.
Try using formatters by saying e.g. `snake hello world`, which will insert hello_world
Mutliple formatters can be used togther, e.g. `dubstring snake hello world`. This will insert "hello_world"
Formatters (snake, dubstring) are defined here
https://github.com/knausj85/knausj_talon/blob/master/code/formatters.py#L146
All formatter-related commands are defined here
https://github.com/knausj85/knausj_talon/blob/master/misc/formatters.talon#L2
### Mouse commands
See https://github.com/knausj85/knausj_talon/blob/master/misc/mouse.talon
### Generic editor
https://github.com/knausj85/knausj_talon/blob/master/text/generic_editor.talon#L7
These generic commands are global. Commands such as `go word left` will work in any text box.
### Repeating commands
For repeating commands, useful voice commands are defined here:
https://github.com/knausj85/knausj_talon/blob/ced46aee4b59e6ec5e8545bb01434e27792c830e/misc/repeater.talon#L2
Try saying e.g. `go up fifth` will go up five lines.
Try saying e.g. `select up third` to hit `shift-up` three times to select some lines in a text field.
### Window management
Global window managment commands are defined here:
https://github.com/knausj85/knausj_talon/blob/master/misc/window_management.talon#L1
`running list` will toggle a GUI list of words you can say to switch to running applications.
`focus chrome` will focus the chrome application.
`launch music` will launch the music application. Note this is currently only implemented on Mac OS X.
### Screenshot commands
https://github.com/knausj85/knausj_talon/blob/master/misc/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.
The commands for enabling languages are defined here:
https://github.com/knausj85/knausj_talon/blob/master/modes/language_modes.talon
By default, title tracking activates coding languages in supported applications such as VSCode, Visual Studio (requires plugin), and Notepad++.
To enable title tracking for your application:
1. The active filename (including extension) must be included in the editor's title
2. Implement the required Talon-defined actions (filename, file_ext) to correctly extract the filename and extension from the programs's title. See https://github.com/knausj85/knausj_talon/blob/master/apps/vscode/vscode.py#L18 for an example.
Python, C#, Talon and javascript language support is currently broken up into ~four contexts in an attempt to define a common grammar where possible between languages
• operators.talon - operator commands
• comment.talon - commenting commands
• programming.talon - function, loop commands, etc
• {your-language-here}.talon - for implementation of the actioIans for the above, and any language-specific stuff
## File Manager commands
For the following file manager commands to work, your file manager must display the full folder path in the title bar. https://github.com/knausj85/knausj_talon/blob/baa323fcd34d8a1124658a425abe8eed59cf2ee5/apps/file_manager.talon
For Mac OS X's Finder, run this command in terminal to display the full path in the 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 folder 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.
## Terminal commands
Many terminal programs are supported out of the box, but you may not want all the commands enabled.
To disable various commandsets in your terminal, find the relevant talon file and enable/disable the tags for command sets as appropriate.
```
tag(): user.file_manager
tag(): user.git
tag(): user.kubectl
tag(): user.tabs
```
For instance, kubectl commands (kubernetes) aren't relevant to everyone.
## Jetbrains commands
For Jetbrains commands to work you must install https://plugins.jetbrains.com/plugin/10504-voice-code-idea
into each editor.
## Settings
Several options are configurable via a single settings file out of the box. Any setting can be made context specific as needed (e.g., per-OS, per-app, etc).
https://github.com/knausj85/knausj_talon/blob/master/settings.talon
```
#adjust the scale of the imgui to my liking
imgui.scale = 1.3
# enable if you'd like the picker gui to automatically appear when explorer has focus
user.file_manager_auto_show_pickers = 0
#set the max number of command lines per page in help
user.help_max_command_lines_per_page = 50
# set the max number of contexts display per page in help
user.help_max_contexts_per_page = 20
# The default amount used when scrolling continuously
user.mouse_continuous_scroll_amount = 80
#stop continuous scroll/gaze scroll with a pop
user.mouse_enable_pop_stops_scroll = 1
#enable pop click with 'control mouse' mode
user.mouse_enable_pop_click = 1
#When enabled, the 'Scroll Mouse' GUI will not be shown.
user.mouse_hide_mouse_gui = 0
#hide cursor when mouse_wake is called to enable zoom mouse
user.mouse_wake_hides_cursor = 0
#the amount to scroll up/down (equivalent to mouse wheel on Windows by default)
user.mouse_wheel_down_amount = 120
```
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.
• Uncomment `tag(): user.mouse_grid_enabled` to enable the mouse grid.
# Collaborators
This repository is now officially a team effort. The following contributors have direct access:
- @dwiel
- @fidgetingbits
- @knausj85
- @rntz
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
Anyone is welcome to submit PRs and report issues.
## Guidelines for contributions
- Any addition to the global grammar will be scrutinized a bit more thoroughly. The more specific a new context, the less scrutiny that is typically applied.
- New grammars should follow the [subject][verb] standard where-ever possible.
- For Mac OS X, the bundle id should be used for defining app contexts, rather than the name.
- For Windows, both the friendly app name and exe name should be used for defining app contexts when they are different. For some people, the MUICache breaks.
- For new web apps, ensure the domain is used to minimize potential mismatches
https://github.com/knausj85/knausj_talon/blob/master/apps/web/window_titles.md
- New applications should support the appropriate 'generic' grammars where possible
```
generic_browser.talon
find_and_replace.talon
line_commands.talon
multiple_cursors.talon
snippets.talon
splits.talon
tabs.talon
```
- New programming languages should support the appropriate 'generic' grammars where possible as well
```
operators.talon
programming.talon
comment.talon
block_comment.talon
```
and should support the lists
```
user.code_functions
user.code_libraries
```
where appropriate. See e.g. csharp.py/csharp.talon. At least, until we come up with something better 👍

View file

@ -0,0 +1,24 @@
os: mac
#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
-
action(user.password_fill):
key(cmd-\)
action(user.password_show):
key(cmd-alt-\)
action(user.password_new):
key(cmd-i)
action(user.password_duplicate):
key(cmd-d)
action(user.password_edit):
key(cmd-e)
action(user.password_delete):
key(cmd-backspace)

View file

@ -1,4 +1,4 @@
from talon import Module
from talon import app, Context, Module
mod = Module()

View file

@ -0,0 +1,24 @@
os: windows
#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
-
action(user.password_fill):
key(ctrl-\\)
action(user.password_show):
key(alt-ctrl-\\)
action(user.password_new):
key(ctrl-n)
action(user.password_duplicate):
key(ctrl-d)
action(user.password_edit):
key(ctrl-e)
action(user.password_delete):
key(ctrl-delete)

View file

@ -4,7 +4,6 @@ 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")

View file

@ -0,0 +1,72 @@
os: mac
app: chrome
-
tag(): browser
tag(): user.tabs
#action(browser.address):
action(browser.bookmark):
key(cmd-d)
action(browser.bookmark_tabs):
key(cmd-shift-d)
action(browser.bookmarks):
key(cmd-alt-b)
action(browser.bookmarks_bar):
key(cmd-shift-b)
action(browser.focus_address):
key(cmd-l)
#action(browser.focus_page):
action(browser.focus_search):
browser.focus_address()
action(browser.go_blank):
key(cmd-n)
action(browser.go_back):
key(cmd-[)
action(browser.go_forward):
key(cmd-])
action(browser.go_home):
key(cmd-shift-h)
action(browser.open_private_window):
key(cmd-shift-n)
action(browser.reload):
key(cmd-r)
action(browser.reload_hard):
key(cmd-shift-r)
#action(browser.reload_hardest):
action(browser.show_clear_cache):
key(cmd-shift-delete)
action(browser.show_downloads):
key(cmd-shift-j)
#action(browser.show_extensions)
action(browser.show_history):
key(cmd-y)
action(browser.submit_form):
key(enter)
#action(browser.title)
action(browser.toggle_dev_tools):
key(cmd-alt-i)
action(user.dental_click): key(escape f)
fill password: user.fill_password()

View file

@ -0,0 +1,52 @@
from talon import ctrl, ui, Module, Context, actions, clip, app
from talon.experimental.locate import locate_hover
ctx = Context()
mod = Module()
mod.apps.chrome = "app.name: Google Chrome"
mod.apps.chrome = """
os: windows
and app.name: Google Chrome
os: windows
and app.exe: chrome.exe
"""
mod.apps.chrome = """
os: mac
and app.bundle: com.google.Chrome
"""
ctx.matches = r"""
app: chrome
"""
@ctx.action_class("user")
class user_actions:
def tab_jump(number: int):
if number < 9:
if app.platform == "mac":
actions.key("cmd-{}".format(number))
else:
actions.key("ctrl-{}".format(number))
def tab_final():
if app.platform == "mac":
actions.key("cmd-9")
else:
actions.key("ctrl-9")
@mod.action_class
class Actions:
def fill_password():
"""Move mouse to last pass fill password button"""
locate_hover("templates/fill-password.png")
@ctx.action_class("browser")
class browser_actions:
def go(url: str):
actions.browser.focus_address()
actions.sleep("50ms")
actions.insert(url)
actions.key("enter")

View file

@ -0,0 +1,68 @@
os: windows
app: chrome
-
tag(): browser
tag(): user.tabs
#action(browser.address):
action(browser.bookmark):
key(ctrl-d)
action(browser.bookmark_tabs):
key(ctrl-shift-d)
action(browser.bookmarks):
key(ctrl-shift-o)
action(browser.bookmarks_bar):
key(ctrl-shift-b)
action(browser.focus_address):
key(ctrl-l)
#action(browser.focus_page):
action(browser.focus_search):
browser.focus_address()
action(browser.go_blank):
key(ctrl-n)
action(browser.go_back):
key(alt-left)
action(browser.go_forward):
key(alt-right)
action(browser.go_home):
key(alt-home)
action(browser.open_private_window):
key(ctrl-shift-n)
action(browser.reload):
key(ctrl-r)
action(browser.reload_hard):
key(ctrl-shift-r)
#action(browser.reload_hardest):
action(browser.show_clear_cache):
key(ctrl-shift-delete)
action(browser.show_downloads):
key(ctrl-j)
#action(browser.show_extensions)
action(browser.show_history):
key(ctrl-h)
action(browser.submit_form):
key(enter)
#action(browser.title)
action(browser.toggle_dev_tools):
key(ctrl-shift-i)

View file

@ -1,6 +1,7 @@
os: windows
app.exe: /^conemu64\.exe$/i
app.exe: ConEmu64.exe
-
tag(): terminal
tag(): user.git

View file

@ -0,0 +1,35 @@
os: mac
app: discord
-
tag(): user.messaging
# Navigation: Servers
action(user.messaging_workspace_previous): key(cmd-alt-up)
action(user.messaging_workspace_next): key(cmd-alt-down)
# Navigation: Channels
action(user.messaging_open_channel_picker): key(cmd-k)
action(user.messaging_channel_previous): key(alt-up)
action(user.messaging_channel_next): key(alt-down)
action(user.messaging_unread_previous): key(alt-shift-up)
action(user.messaging_unread_next): key(alt-shift-down)
action(user.discord_mentions_last): key(cmd-alt-shift-up)
action(user.discord_mentions_next): key(cmd-alt-shift-down)
action(user.discord_oldest_unread): key(shift-pageup)
# UI
action(user.discord_toggle_pins): key(cmd-p)
action(user.discord_toggle_inbox): key(cmd-i)
action(user.discord_toggle_members): key(cmd-u)
action(user.discord_emoji_picker): key(cmd-e)
action(user.discord_gif_picker): key(cmd-g)
# Misc
action(user.messaging_mark_workspace_read): key(shift-esc)
action(user.messaging_mark_channel_read): key(esc)
action(user.messaging_upload_file): key(cmd-shift-u)
action(user.discord_mark_inbox_read): key(cmd-shift-e)
action(user.discord_mute): key(cmd-shift-m)
action(user.discord_deafen): key(cmd-shift-d)
action(user.discord_answer_call): key(cmd-enter)
action(user.discord_decline_call): key(esc)

View file

@ -1,28 +1,9 @@
from talon import Context, Module, actions
from talon import Module
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:
@ -50,9 +31,6 @@ class discord_actions:
def discord_gif_picker():
"""Toggle gif picker"""
def discord_sticker_picker():
"""Toggle sticker picker"""
def discord_mark_inbox_read():
"""Mark top inbox channel read"""
@ -67,19 +45,3 @@ class discord_actions:
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("#", "")

View file

@ -1,34 +1,20 @@
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()

View file

@ -0,0 +1,36 @@
os: windows
os: linux
app: discord
-
tag(): user.messaging
# Navigation: Servers
action(user.messaging_workspace_previous): key(ctrl-alt-up)
action(user.messaging_workspace_next): key(ctrl-alt-down)
# Navigation: Channels
action(user.messaging_open_channel_picker): key(ctrl-k)
action(user.messaging_channel_previous): key(alt-up)
action(user.messaging_channel_next): key(alt-down)
action(user.messaging_unread_previous): key(alt-shift-up)
action(user.messaging_unread_next): key(alt-shift-down)
action(user.discord_mentions_last): key(ctrl-alt-shift-up)
action(user.discord_mentions_next): key(ctrl-alt-shift-down)
action(user.discord_oldest_unread): key(shift-paegup)
# UI
action(user.discord_toggle_pins): key(ctrl-p)
action(user.discord_toggle_inbox): key(ctrl-i)
action(user.discord_toggle_members): key(ctrl-u)
action(user.discord_emoji_picker): key(ctrl-e)
action(user.discord_gif_picker): key(ctrl-g)
# Misc
action(user.messaging_mark_workspace_read): key(shift-esc)
action(user.messaging_mark_channel_read): key(esc)
action(user.messaging_upload_file): key(ctrl-shift-u)
action(user.discord_mark_inbox_read): key(ctrl-shift-e)
action(user.discord_mute): key(ctrl-shift-m)
action(user.discord_deafen): key(ctrl-shift-d)
action(user.discord_answer_call): key(ctrl-enter)
action(user.discord_decline_call): key(esc)

View file

@ -1,4 +1,7 @@
from talon import Context, Module, actions
from talon import Context, actions, ui, Module, app, clip
from typing import List, Union
is_mac = app.platform == "mac"
ctx = Context()
mod = Module()
@ -13,40 +16,30 @@ app: eclipse
"""
@ctx.action_class("app")
class AppActions:
# talon app actions
def tab_close():
actions.key("ctrl-w")
@ctx.action_class("win")
class win_actions:
def filename():
title = actions.win.title()
# this doesn't seem to be necessary on VSCode for Mac
# if title == "":
# title = ui.active_window().doc
def tab_next():
actions.key("ctrl-pagedown")
if " - " in title:
result = title.split(" - ")[1]
else:
result = title
def tab_previous():
actions.key("ctrl-pageup")
if "." in result:
return result
# 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")
return ""
@ctx.action_class("edit")
class EditActions:
def find_next():
actions.key("enter")
def find_previous():
actions.key("shift-enter")
class edit_actions:
def find(text: str):
actions.key("ctrl-f")
actions.insert(text)
def line_swap_up():
actions.key("alt-up")
@ -65,60 +58,65 @@ class EditActions:
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:
class user_actions:
# snippet.py support beginHelp close
# def snippet_search(text: str):
# actions.user.vscode("Insert Snippet")
# actions.insert(text)
# def snippet_insert(text: str):
# """Inserts a snippet"""
# actions.user.vscode("Insert Snippet")
# actions.insert(text)
# actions.key("enter")
# def snippet_create():
# """Triggers snippet creation"""
# actions.user.vscode("Preferences: Configure User Snippets")
# snippet.py support end
# def tab_jump(number: int):
# if number < 10:
# if is_mac:
# actions.key("ctrl-{}".format(number))
# else:
# actions.key("alt-{}".format(number))
# def tab_final():
# if is_mac:
# actions.key("ctrl-0")
# else:
# actions.key("alt-0")
# 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)
# def split_number(index: int):
# """Navigates to a the specified split"""
# if index < 9:
# if is_mac:
# actions.key("cmd-{}".format(index))
# else:
# actions.key("ctrl-{}".format(index))
# splits.py support end
# find_and_replace.py support begin
def find(text: str):
"""Triggers find in current editor"""
actions.key("ctrl-f")
if text:
actions.insert(text)
def find_next():
actions.key("enter")
def find_previous():
actions.key("shift-enter")
def find_everywhere(text: str):
"""Triggers find across project"""
actions.key("ctrl-h")
@ -173,3 +171,4 @@ class UserActions:
actions.key("alt-f alt-o esc")
# find_and_replace.py support end

View file

@ -0,0 +1,195 @@
#custom eclipse commands go here
app: eclipse
-
tag(): user.find_and_replace
tag(): user.line_commands
# tag(): user.multiple_cursors
# tag(): user.snippets
tag(): user.splits
tag(): user.tabs
#talon app actions
action(app.tab_close): key(ctrl-w)
action(app.tab_next): key(ctrl-pagedown)
action(app.tab_previous): key(ctrl-pageup)
#action(app.tab_reopen):
action(app.window_close): key(alt-f4)
action(app.window_open): key(alt-w n)
#talon code actions
action(code.toggle_comment): key(ctrl-7)
#talon edit actions
action(edit.indent_more): key(tab)
action(edit.indent_less): key(shift-tab)
action(edit.save_all): key(ctrl-shift-s)
# splits.py support begin
# requires https://marketplace.eclipse.org/content/handysplit
action(user.split_clear_all): key(alt-shift-s f)
action(user.split_clear): key(alt-shift-s f)
# action(user.split_flip):
action(user.split_last): key(alt-shift-s t)
action(user.split_next): key(alt-shift-s t)
action(user.split_window_down): key(alt-shift-s m)
action(user.split_window_horizontally): key(alt-ctrl-s s)
action(user.split_window_right): key(alt-shift-s m)
action(user.split_window_up): key(alt-shift-s m)
action(user.split_window_vertically): key(alt-shift-s s)
action(user.split_window): key(alt-ctrl-s s)
# splits.py support end
#multiple_cursor.py support begin
#note: vscode has no explicit mode for multiple cursors
# action(user.multi_cursor_add_above):
# action(user.multi_cursor_add_below):
# action(user.multi_cursor_add_to_line_ends):
# action(user.multi_cursor_disable):
# action(user.multi_cursor_enable):
# action(user.multi_cursor_select_all_occurrences):
# action(user.multi_cursor_select_fewer_occurrences):
# action(user.multi_cursor_select_more_occurrences):
#multiple_cursor.py support end
please [<user.text>]:
key(ctrl-3)
insert(user.text or "")
# 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)
#Expand/Shrink AST Selection
# select less: user.vscode("editor.action.smartSelect.shrink")
# select (more|this): user.vscode("editor.action.smartSelect.expand")

View file

@ -0,0 +1,68 @@
os: mac
app: microsoft_edge
-
tag(): browser
tag(): user.tabs
#action(browser.address):
action(browser.bookmark):
key(ctrl-d)
action(browser.bookmark_tabs):
key(ctrl-shift-d)
action(browser.bookmarks):
key(ctrl-shift-o)
action(browser.bookmarks_bar):
key(ctrl-shift-b)
action(browser.focus_address):
key(ctrl-l)
#action(browser.focus_page):
action(browser.focus_search):
browser.focus_address()
action(browser.go_blank):
key(ctrl-n)
action(browser.go_back):
key(alt-left)
action(browser.go_forward):
key(alt-right)
action(browser.go_home):
key(alt-home)
action(browser.open_private_window):
key(ctrl-shift-p)
action(browser.reload):
key(ctrl-r)
action(browser.reload_hard):
key(shift-f5)
#action(browser.reload_hardest):
action(browser.show_clear_cache):
key(ctrl-shift-delete)
action(browser.show_downloads):
key(ctrl-j)
#action(browser.show_extensions)
action(browser.show_history):
key(ctrl-h)
action(browser.submit_form):
key(enter)
#action(browser.title)
action(browser.toggle_dev_tools):
key(ctrl-shift-i)

View file

@ -0,0 +1,42 @@
from talon import ctrl, ui, Module, Context, actions, clip, app
ctx = Context()
mod = Module()
mod.apps.microsoft_edge = """
os: windows
and app.name: msedge.exe
os: windows
and app.name: Microsoft Edge
os: windows
and app.exe: msedge.exe
"""
ctx.matches = r"""
app: microsoft_edge
"""
@ctx.action_class("user")
class user_actions:
def tab_jump(number: int):
if number < 9:
if app.platform == "mac":
actions.key("cmd-{}".format(number))
else:
actions.key("ctrl-{}".format(number))
def tab_final():
if app.platform == "mac":
actions.key("cmd-9")
else:
actions.key("ctrl-9")
@ctx.action_class("browser")
class browser_actions:
def go(url: str):
actions.browser.focus_address()
actions.sleep("50ms")
actions.insert(url)
actions.key("enter")

View file

@ -0,0 +1,68 @@
os: windows
app: microsoft_edge
-
tag(): browser
tag(): user.tabs
#action(browser.address):
action(browser.bookmark):
key(ctrl-d)
action(browser.bookmark_tabs):
key(ctrl-shift-d)
action(browser.bookmarks):
key(ctrl-shift-o)
action(browser.bookmarks_bar):
key(ctrl-shift-b)
action(browser.focus_address):
key(ctrl-l)
#action(browser.focus_page):
action(browser.focus_search):
browser.focus_address()
action(browser.go_blank):
key(ctrl-n)
action(browser.go_back):
key(alt-left)
action(browser.go_forward):
key(alt-right)
action(browser.go_home):
key(alt-home)
action(browser.open_private_window):
key(ctrl-shift-p)
action(browser.reload):
key(ctrl-r)
action(browser.reload_hard):
key(shift-f5)
#action(browser.reload_hardest):
action(browser.show_clear_cache):
key(ctrl-shift-delete)
action(browser.show_downloads):
key(ctrl-j)
#action(browser.show_extensions)
action(browser.show_history):
key(ctrl-h)
action(browser.submit_form):
key(enter)
#action(browser.title)
action(browser.toggle_dev_tools):
key(ctrl-shift-i)

View file

@ -0,0 +1,47 @@
tag: user.file_manager
-
title force: user.file_manager_refresh_title()
manager show: user.file_manager_toggle_pickers()
manager refresh: user.file_manager_update_lists()
go desk: user.file_manager_open_user_directory("Desktop")
go docks: user.file_manager_open_user_directory("Documents")
go downloads: user.file_manager_open_user_directory("Downloads")
go pictures: user.file_manager_open_user_directory("Pictures")
go profile: user.file_manager_open_user_directory("")
go talon home: user.file_manager_open_directory(path.talon_home())
go talon user: user.file_manager_open_directory(path.talon_user())
go user: user.file_manager_open_directory(path.user_home())
go back: user.file_manager_go_back()
go forward: user.file_manager_go_forward()
daddy: user.file_manager_open_parent()
^follow <number>$:
directory = user.file_manager_get_directory_by_index(number - 1)
user.file_manager_open_directory(directory)
^follow {user.file_manager_directories}$: user.file_manager_open_directory(file_manager_directories)
^open <number>$:
file = user.file_manager_get_file_by_index(number - 1)
user.file_manager_open_file(file)
^folder <number>$:
directory = user.file_manager_get_directory_by_index(number - 1)
user.file_manager_select_directory(directory)
^file <number>$:
file = user.file_manager_get_file_by_index(number - 1)
user.file_manager_select_file(file)
^file {user.file_manager_files}$: user.file_manager_select_file(file_manager_files)
#new folder
folder new <user.text>:
user.file_manager_new_folder(text)
#show properties
properties show: user.file_manager_show_properties()
# open terminal at location
terminal here: user.file_manager_terminal_here()
folder next: user.file_manager_next_folder_page()
folder last: user.file_manager_previous_folder_page()
file next: user.file_manager_next_file_page()
file last: user.file_manager_previous_file_page()

View file

@ -0,0 +1,61 @@
os: linux
app: Firefox
app: firefox
-
action(app.tab_next): key(ctrl-pagedown)
action(app.tab_previous): key(ctrl-pageup)
action(browser.bookmark):
key(ctrl-d)
action(browser.bookmark_tabs):
key(ctrl-shift-d)
action(browser.bookmarks):
key(ctrl-shift-o)
action(browser.bookmarks_bar):
key(ctrl-b)
action(browser.focus_address):
key(ctrl-l)
#action(browser.focus_page):
action(browser.go_blank):
key(ctrl-n)
action(browser.go_back):
key(alt-left)
action(browser.go_forward):
key(alt-right)
action(browser.go_home):
key(alt-home)
action(browser.open_private_window):
key(ctrl-shift-p)
action(browser.reload):
key(ctrl-r)
action(browser.reload_hard):
key(ctrl-shift-r)
#action(browser.reload_hardest):
action(browser.show_clear_cache):
key(ctrl-shift-del)
action(browser.show_downloads):
key(ctrl-shift-y)
action(browser.show_extensions):
key(ctrl-shift-a)
action(browser.show_history):
key(ctrl-h)
action(browser.toggle_dev_tools):
key(ctrl-shift-i)

View file

@ -0,0 +1,57 @@
os: mac
app: firefox
-
action(browser.bookmark):
key(cmd-d)
action(browser.bookmark_tabs):
key(cmd-shift-d)
action(browser.bookmarks):
key(cmd-alt-b)
#action(browser.bookmarks_bar):
# key(ctrl-shift-b)
action(browser.focus_address):
key(cmd-l)
#action(browser.focus_page):
action(browser.go_blank):
key(cmd-n)
action(browser.go_back):
key(cmd-left)
action(browser.go_forward):
key(cmd-right)
action(browser.go_home):
key(cmd-shift-h)
action(browser.open_private_window):
key(cmd-shift-p)
action(browser.reload):
key(cmd-r)
action(browser.reload_hard):
key(cmd-shift-r)
#action(browser.reload_hardest):
action(browser.show_clear_cache):
key(cmd-shift-delete)
action(browser.show_downloads):
key(cmd-shift-j)
action(browser.show_extensions):
key(cmd-shift-a)
action(browser.show_history):
key(cmd-y)
action(browser.toggle_dev_tools):
key(cmd-alt-i)

View file

@ -0,0 +1,46 @@
from talon import ctrl, ui, Module, Context, actions, clip, app
ctx = Context()
mod = Module()
apps = mod.apps
apps.firefox = "app.name: Firefox"
apps.firefox = "app.name: firefox"
apps.firefox = """
os: windows
and app.name: Firefox
os: windows
and app.exe: firefox.exe
"""
apps.firefox = """
os: mac
and app.bundle: org.mozilla.firefox
"""
ctx.matches = r"""
app: firefox
"""
@ctx.action_class("user")
class user_actions:
def tab_jump(number: int):
if number < 9:
if app.platform == "mac":
actions.key("cmd-{}".format(number))
else:
actions.key("ctrl-{}".format(number))
def tab_final():
if app.platform == "mac":
actions.key("cmd-9")
else:
actions.key("ctrl-9")
@ctx.action_class("browser")
class browser_actions:
def go(url: str):
actions.browser.focus_address()
actions.sleep("50ms")
actions.insert(url)
actions.key("enter")

View file

@ -0,0 +1,23 @@
app: firefox
-
tag(): browser
tag(): user.tabs
# TODO
#action(browser.address):
#action(browser.title):
action(browser.focus_search):
browser.focus_address()
action(browser.submit_form):
key(enter)
tab search:
browser.focus_address()
insert("% ")
tab search <user.text>$:
browser.focus_address()
insert("% {text}")
key(down)

View file

@ -0,0 +1,64 @@
os: windows
app: firefox
-
action(app.tab_next): key(ctrl-pagedown)
action(app.tab_previous): key(ctrl-pageup)
action(browser.bookmark):
key(ctrl-d)
action(browser.bookmark_tabs):
key(ctrl-shift-d)
action(browser.bookmarks):
key(ctrl-shift-b)
action(browser.bookmarks_bar):
key(alt-v)
sleep(50ms)
key(t)
sleep(50ms)
key(b)
action(browser.focus_address):
key(ctrl-l)
#action(browser.focus_page):
action(browser.go_blank):
key(ctrl-n)
action(browser.go_back):
key(alt-left)
action(browser.go_forward):
key(alt-right)
action(browser.go_home):
key(alt-home)
action(browser.open_private_window):
key(ctrl-shift-p)
action(browser.reload):
key(ctrl-r)
action(browser.reload_hard):
key(ctrl-shift-r)
#action(browser.reload_hardest):
action(browser.show_clear_cache):
key(ctrl-shift-delete)
action(browser.show_downloads):
key(ctrl-j)
action(browser.show_extensions):
key(ctrl-shift-a)
action(browser.show_history):
key(ctrl-h)
action(browser.toggle_dev_tools):
key(ctrl-shift-i)

View file

@ -0,0 +1,19 @@
from talon import Context, Module, actions, ui
ctx = Context()
ctx.matches = r"""
mode: user.gdb
"""
@ctx.action_class("user")
class user_actions:
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")

View file

@ -0,0 +1,156 @@
os: linux
# XXX - this matches .gdb files atm
#win.title: /gdb/
tag: terminal
mode: user.gdb
-
tag(): user.gdb
tag(): user.debugger
##
# Generic debugger actions
##
# Code execution
action(user.debugger_step_into): "stepi\n"
action(user.debugger_step_over): "nexti\n"
action(user.debugger_step_line): "step\n"
action(user.debugger_step_over_line): "next\n"
action(user.debugger_step_out): "finish\n"
until <number>: "until {number}"
action(user.debugger_continue): "c\n"
action(user.debugger_stop): key("ctrl-c")
action(user.debugger_start): "run\n"
action(user.debugger_restart): "run\n"
# XXX -
action(user.debugger_detach): ""
# Registers
action(user.debugger_show_registers): "info registers\n"
action(user.debugger_get_register): "r "
action(user.debugger_set_register):
insert("set $=")
edit.left()
# Breakpoints
action(user.debugger_show_breakpoints): "info breakpoints\n"
action(user.debugger_add_sw_breakpoint): "break "
# XXX -
action(user.debugger_add_hw_breakpoint): ""
action(user.debugger_break_now): key("ctrl-c")
action(user.debugger_break_here): "break\n"
action(user.debugger_clear_all_breakpoints): "d br\n"
force clear all break points:
insert("d br\n")
insert("y\n")
action(user.debugger_clear_breakpoint):
insert("d br ")
action(user.debugger_enable_all_breakpoints):
insert("enable br\n")
action(user.debugger_enable_breakpoint):
insert("enable br ")
action(user.debugger_disable_all_breakpoints):
insert("disable br\n")
action(user.debugger_disable_breakpoint):
insert("disable br ")
break [on] clipboard:
insert("break ")
key(ctrl-shift-v)
key(enter)
# Memory inspection
# Type inspection
##
# gdb specific functionality
##
# 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"

View file

@ -0,0 +1,64 @@
tag: browser
-
(address bar | go address | go url): browser.focus_address()
go home: browser.go_home()
[go] forward: browser.go_forward()
go (back | backward): browser.go_back()
go private: browser.open_private_window()
bookmark show: browser.bookmarks()
bookmark bar: browser.bookmarks_bar()
bookmark it: browser.bookmark()
bookmark tabs: browser.bookmark_tabs()
(refresh | reload) it: browser.reload()
(refresh | reload) it hard: browser.reload_hard()
show downloads: browser.show_downloads()
show extensions: browser.show_extensions()
show history: browser.show_history()
show cache: browser.show_clear_cache()
dev tools: browser.toggle_dev_tools()
#todo - port to apps
# navigating current page
# help: key(?)
# scroll tiny down: key(j)
# scroll tiny up: key(k)
# scroll left: key(h)
# scroll right: key(l)
# scroll (pop | spring): key(z H)
# scroll push: key(z L)
# scroll top: key(gg)
# scroll (bottom | end): key(G)
# (scroll half down | mini page): key(d)
# scroll half up: key(u)
# [open] link: key(f)
# [open] link new: key(F)
# copy link: key(y f)
# copy (address | url): key(escape y y)
# (refresh | reload): browser.reload()
# view source: key(g s)
# insert mode: key(i)
# next frame: key(g f)
# main frame: key(g F)
# navigating to new pages
# (open | go) (url | history): key(o)
# (open | go) (url | history) new: key(O)
# (open | go) bookmark: key(b)
# (open | go) bookmark new: key(B)
# using find
# find mode: key(/)
# next match: key(n)
# previous match: key(N)
# navigating history
# history back: key(H)
# history forward: key(L)
# manipulating tabs
# last visited: key(^)
# dupe tab: key(y t)
# restore: key(X)
# search tabs: key(T)
# move to window: key(W)

View file

@ -1,4 +1,4 @@
tag: user.debugger
tag: debugger
-
# Code execution
@ -29,26 +29,27 @@ set register: user.debugger_set_register()
# Breakpoints
break now: user.debugger_break_now()
break here: user.debugger_break_here()
(list | show) (breaks | break points): user.debugger_show_breakpoints()
(set | add) (break | break point): user.debugger_add_sw_breakpoint()
(set | add) hardware (break | break point): user.debugger_add_hw_breakpoint()
clear all (breaks | break points): user.debugger_clear_all_breakpoints()
clear (break | break point): user.debugger_clear_breakpoint()
clear (break | break point) <number_small>:
(list|show) (breaks|break points): user.debugger_show_breakpoints()
(set|add) (break|break point): user.debugger_add_sw_breakpoint()
(set|add) hardware (break|break point): user.debugger_add_hw_breakpoint()
clear all (breaks|break points): user.debugger_clear_all_breakpoints()
clear (break|break point): user.debugger_clear_breakpoint()
clear (break|break point) <number_small>:
user.debugger_clear_breakpoint_id(number_small)
disable all (breaks | break points): user.debugger_disable_all_breakpoints()
disable (break | break point): user.debugger_disable_breakpoint()
disable (break | break point) <number_small>:
disable all (breaks|break points): user.debugger_disable_all_breakpoints()
disable (break|break point): user.debugger_disable_breakpoint()
disable (break|break point) <number_small>:
user.debugger_disable_breakpoint_id(number_small)
enable all (breaks | break points): user.debugger_enable_all_breakpoints()
enable (break | break point): user.debugger_enable_breakpoint()
enable (break | break point) <number_small>:
enable all (breaks|break points): user.debugger_enable_all_breakpoints()
enable (break|break point): user.debugger_enable_breakpoint()
enable (break|break point) <number_small>:
user.debugger_enable_breakpoint_id(number_small)
# Navigation
# Memory Inspection
(stack | back) trace: user.debugger_backtrace()
(stack|back) trace: user.debugger_backtrace()
disassemble: user.debugger_disassemble()
disassemble here: user.debugger_disassemble_here()
disassemble clipboard: user.debugger_disassemble_clipboard()

View file

@ -1,6 +1,7 @@
from talon import Module
from talon import app, Module, Context, actions, ui, imgui, settings, app, registry
mod = Module()
mod.tag("generic_terminal", desc="Tag for enabling generic terminal commands")
@mod.action_class
@ -23,8 +24,6 @@ class Actions:
def terminal_run_last():
"""Repeats the last command"""
def terminal_rerun_search(command: str):
"""Searches through the previously executed commands"""
def terminal_kill_all():
"""kills the running command"""

View file

@ -0,0 +1,11 @@
tag: user.generic_terminal
-
lisa:
user.terminal_list_directories()
lisa all:
user.terminal_list_all_directories()
katie [<user.text>]: user.terminal_change_directory(text or "")
katie root: user.terminal_change_directory_root()
clear screen: user.terminal_clear_screen()
run last: user.terminal_run_last()
kill all: user.terminal_kill_all()

View file

@ -0,0 +1,35 @@
from talon import Context, Module, actions, settings, ui
mod = Module()
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",
)
@mod.action_class
class Actions:
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_lock():
"""Trigger the lock screen"""
key = settings.get("user.i3_mod_key")
actions.key(f"{key}-shift-x")

View file

@ -0,0 +1,100 @@
# NOTE: If you want to use i3wm you must enable the tag settings.talon. ex: `tag(): user.i3wm`
os: linux
tag: user.i3wm
-
settings():
user.i3_config_path = "~/.i3/config"
user.i3_mod_key = "super"
port <number_small>: user.system_command("i3-msg workspace {number_small}")
port ten: user.system_command("i3-msg workspace 10")
(port flip|flipper): user.system_command("i3-msg workspace back_and_forth")
port right: user.system_command("i3-msg workspace next")
port left: user.system_command("i3-msg workspace prev")
(win|window) left: user.system_command("i3-msg focus left")
(win|window) right: user.system_command("i3-msg focus right")
(win|window) up: user.system_command("i3-msg focus up")
(win|window) down: user.system_command("i3-msg focus down")
((win|window) kill|murder): user.system_command("i3-msg kill")
(win|window) stacking: user.system_command("i3-msg layout stacking")
(win|window) default: user.system_command("i3-msg layout toggle split")
(win|window) tabbed: user.system_command("i3-msg layout tabbed")
reload i three config: user.system_command("i3-msg reload")
restart i three: user.system_command("i3-msg restart")
(full screen|scuba): user.system_command("i3-msg fullscreen")
toggle floating: user.system_command("i3-msg floating toggle")
focus floating: user.system_command("i3-msg focus mode_toggle")
center window: user.system_command("i3-msg move position center")
resize mode: user.system_command('i3-msg mode "resize"')
focus parent: user.system_command("i3-msg focus parent")
focus child: user.system_command("i3-msg focus child")
# resize helpers
grow window:
user.system_command('i3-msg mode "resize"')
key(right:10)
key(down:10)
# escape resize mode
key(escape)
# center window
sleep(200ms)
user.system_command("i3-msg move position center")
# resize helpers
shrink window:
user.system_command('i3-msg mode "resize"')
key(left:10)
key(up:10)
# escape resize mode
key(escape)
# center window
sleep(200ms)
user.system_command("i3-msg move position center")
horizontal (shell|terminal):
user.system_command("i3-msg split h")
user.i3wm_shell()
vertical (shell|terminal):
user.system_command("i3-msg 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.system_command("i3-msg move container to workspace {number_small}")
(shuffle|move (win|window) [to] port ten): user.system_command("i3-msg move container to workspace 10")
(shuffle|move (win|window) [to] last port): user.system_command("i3-msg move container to workspace back_and_forth")
(shuffle|move (win|window) left): user.system_command("i3-msg move left")
(shuffle|move (win|window) right): user.system_command("i3-msg move right")
(shuffle|move (win|window) up): user.system_command("i3-msg move up")
(shuffle|move (win|window) down): user.system_command("i3-msg move down")
(win|window) horizontal: user.system_command("i3-msg split h")
(win|window) vertical: user.system_command("i3-msg split v")
make scratch: user.system_command("i3-msg move scratchpad")
[(show|hide)] scratch: user.system_command("i3-msg scratchpad show")
next scratch:
user.system_command("i3-msg scratchpad show")
user.system_command("i3-msg scratchpad show")
# 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_launch()
(launch shell|koopa): user.i3wm_shell()
new scratch (shell|window):
user.i3wm_shell()
sleep(200ms)
user.system_command("i3-msg move scratchpad")
user.system_command("i3-msg scratchpad show")

View file

@ -0,0 +1,206 @@
import os
import os.path
import requests
import time
from pathlib import Path
from talon import ctrl, ui, Module, Context, actions, clip
import tempfile
# Courtesy of https://github.com/anonfunc/talon-user/blob/master/apps/jetbrains.py
extendCommands = []
# 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-rubymine": 8661,
"jetbrains-rubymine-eap": 8661,
"jetbrains-studio": 8652,
"jetbrains-webstorm": 8663,
"RubyMine": 8661,
"RubyMine-EAP": 8661,
"PyCharm": 8658,
"pycharm64.exe": 8658,
"webstorm64.exe": 8663,
}
def _get_nonce(port, file_prefix):
file_name = file_prefix + str(port)
try:
with open(os.path.join(tempfile.gettempdir(), file_name), "r") as fh:
return fh.read()
except FileNotFoundError as e:
try:
home = str(Path.home())
with open(os.path.join(home, file_name), "r") as fh:
return fh.read()
except FileNotFoundError as eb:
print(f"Could not find {file_name} in tmp or home")
return None
except IOError as e:
print(e)
return None
def send_idea_command(cmd):
print("Sending {}".format(cmd))
active_app = ui.active_app()
bundle = active_app.bundle or active_app.name
port = port_mapping.get(bundle, None)
nonce = _get_nonce(port, ".vcidea_") or _get_nonce(port, "vcidea_")
print(f"sending {bundle} {port} {nonce}")
if port and nonce:
response = requests.get(
"http://localhost:{}/{}/{}".format(port, nonce, cmd), timeout=(0.05, 3.05)
)
response.raise_for_status()
return response.text
def get_idea_location():
return send_idea_command("location").split()
def idea_commands(commands):
command_list = commands.split(",")
print("executing jetbrains", commands)
global extendCommands
extendCommands = command_list
for cmd in command_list:
if cmd:
send_idea_command(cmd.strip())
time.sleep(0.1)
ctx = Context()
mod = Module()
mod.apps.jetbrains = "app.name: /jetbrains/"
mod.apps.jetbrains = "app.name: IntelliJ IDEA"
mod.apps.jetbrains = "app.name: PyCharm"
mod.apps.jetbrains = "app.name: RubyMine"
mod.apps.jetbrains = "app.name: RubyMine-EAP"
# windows
mod.apps.jetbrains = "app.name: idea64.exe"
mod.apps.jetbrains = "app.name: PyCharm64.exe"
mod.apps.jetbrains = "app.name: pycharm64.exe"
mod.apps.jetbrains = "app.name: webstorm64.exe"
mod.apps.jetbrains = """
os: mac
and app.bundle: com.jetbrains.pycharm
"""
@mod.action_class
class Actions:
def idea(commands: str):
"""Send a command to Jetbrains product"""
idea_commands(commands)
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("goto {} {}".format(original_line, original_column))
send_idea_command("action EditorPaste")
finally:
clip.set(old_clip)
global extendCommands
extendCommands = []
ctx.matches = r"""
app: jetbrains
"""
@ctx.action_class("win")
class win_actions:
def filename():
title = actions.win.title()
result = title.split(" ")
for word in result:
if "." in word:
return word
return ""
@ctx.action_class("edit")
class edit_actions:
def jump_line(n: int):
actions.user.idea("goto {} 0".format(n))
# 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("user")
class user_actions:
def tab_jump(number: int):
# depends on plugin GoToTabs
if number < 10:
actions.user.idea("action GoToTab{}".format(number))
def extend_until_line(line: int):
actions.user.idea("extend {}".format(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("goto {} 0".format(line_start))
actions.user.idea("action EditorSelectLine"),
else:
actions.user.idea("range {} {}".format(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 line_clone(line: int):
actions.user.idea("clone {}".format(line))

View file

@ -5,22 +5,80 @@ tag(): user.line_commands
tag(): user.multiple_cursors
tag(): user.splits
tag(): user.tabs
tag(): user.command_search
#talon app actions (+custom tab actions)
action(user.tab_final): user.idea("action GoToLastTab")
action(app.tab_next): user.idea("action NextTab")
action(app.tab_previous): user.idea("action PreviousTab")
action(app.tab_close): user.idea("action CloseContent")
action(app.tab_reopen): user.idea("action ReopenClosedTab")
#talon code actions
action(code.toggle_comment): user.idea("action CommentByLineComment")
#talon edit actions
action(edit.copy): user.idea("action EditorCopy")
action(edit.cut): user.idea("action EditorCut")
action(edit.delete): user.idea("action EditorBackSpace")
action(edit.paste): user.idea("action EditorPaste")
action(edit.find_next): user.idea("action FindNext")
action(edit.find_previous): user.idea("action FindPrevious")
action(edit.find): user.idea("action Find")
action(edit.line_clone): user.idea("action EditorDuplicate")
action(edit.line_swap_down): user.idea("action MoveLineDown")
action(edit.line_swap_up): user.idea("action MoveLineUp")
action(edit.indent_more): user.idea("action EditorIndentLineOrSelection")
action(edit.indent_less): user.idea("action EditorUnindentSelection")
action(edit.select_line): user.idea("action EditorSelectLine")
action(edit.select_word): user.idea("action EditorSelectWord")
action(edit.select_all): user.idea("action $SelectAll")
action(edit.file_start): user.idea("action EditorTextStart")
action(edit.file_end): user.idea("action EditorTextEnd")
action(edit.extend_file_start): user.idea("action EditorTextStartWithSelection")
action(edit.extend_file_end): user.idea("action EditorTextEndWithSelection")
# splits.py support begin
action(user.split_clear_all): user.idea("action UnsplitAll")
action(user.split_clear): user.idea("action Unsplit")
action(user.split_flip): user.idea("action ChangeSplitOrientation")
action(user.split_last): user.idea("action LastSplitter")
action(user.split_next): user.idea("action NextSplitter")
action(user.split_window_down): user.idea("action MoveTabDown")
action(user.split_window_horizontally): user.idea("action SplitHorizontally")
#action(user.split_window_left): user.idea("action MoveTabLeft")
action(user.split_window_right): user.idea("action MoveTabRight")
#action(user.split_window_up): user.idea("action MoveTabUp")
action(user.split_window_vertically): user.idea("action SplitVertically")
action(user.split_window): user.idea("action EditSourceInNewWindow")
# splits.py support end
# multiple_cursors.py support begin
action(user.multi_cursor_add_above): user.idea("action EditorCloneCaretAbove")
action(user.multi_cursor_add_below): user.idea("action EditorCloneCaretBelow")
action(user.multi_cursor_disable): key(escape)
action(user.multi_cursor_enable): key(shift-alt-insert)
action(user.multi_cursor_select_all_occurrences): user.idea("action SelectAllOccurrences")
action(user.multi_cursor_select_fewer_occurrences): user.idea("action UnselectPreviousOccurrence")
action(user.multi_cursor_select_more_occurrences): user.idea("action SelectNextOccurrence")
# 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")
(done | finish): user.idea("action EditorCompleteStatement")
# Copying
grab <number>: user.idea_grab(number)
action [<user.text>]: user.deprecate_command("2024-09-02", "action", "please")
# Actions
(action | please): user.idea("action GotoAction")
(action | please) <user.text>:
user.idea("action GotoAction")
insert(text)
# Refactoring
refactor: user.idea("action Refactorings.QuickListPopupAction")
refactor <user.text>:
user.idea("action Refactorings.QuickListPopupAction")
insert(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")
@ -44,9 +102,9 @@ 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)
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")
@ -70,7 +128,7 @@ insert template <user.text> [over]:
idea("action InsertLiveTemplate")
sleep(500ms)
insert(text)
create (template | snippet): user.idea("action SaveAsTemplate")
create (template|snippet): user.idea("action SaveAsTemplate")
# Recording
toggle recording: user.idea("action StartStopMacroRecording")
change (recording | recordings): user.idea("action EditMacros")
@ -109,9 +167,9 @@ create sibling <user.text> [over]:
insert(text)
create file: user.idea("action NewElement")
create file <user.text> [over]:
user.idea("action NewElement")
sleep(500ms)
insert(text)
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")
@ -126,8 +184,7 @@ 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 (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:
@ -175,7 +232,7 @@ toggle presentation [mode]: user.idea("action TogglePresentationMode")
toggle comment: code.toggle_comment()
# Quick popups
change scheme: user.idea("action QuickChangeScheme")
# Always javadoc
# Always javadoc
(toggle | pop) (doc | documentation): user.idea("action QuickJavaDoc")
(pop deaf | toggle definition): user.idea("action QuickImplementations")
pop type: user.idea("action ExpressionTypeInfo")
@ -202,80 +259,44 @@ continue: user.idea("action Resume")
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")
user.idea("action GotoNextError")
user.idea("action ShowIntentionActions")
fix last (error | air):
user.idea("action GotoPreviousError")
user.idea("action ShowIntentionActions")
user.idea("action GotoPreviousError")
user.idea("action ShowIntentionActions")
# Special Selects
select less: user.idea("action EditorUnSelectWord")
select (more | this): user.idea("action EditorSelectWord")
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")
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")
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")
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")
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")
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")
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 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")
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()

View file

@ -1,4 +1,4 @@
from talon import Context, Module
from talon import Module, Context
mod = Module()
mod.tag("kubectl", desc="tag for enabling kubectl commands in your terminal")

View file

@ -0,0 +1,68 @@
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:
insert("kubectl exec -it -- /bin/bash")
key("left:13")

View file

@ -0,0 +1,11 @@
from talon import ctrl, ui, Module, Context, actions, clip, app
ctx = Context()
mod = Module()
apps = mod.apps
apps.linear = """
app.name: Linear
"""
ctx.matches = r"""
app: linear
"""

View file

@ -0,0 +1,7 @@
app: linear
-
show cycle active: "gv"
show cycle upcoming: "gw"
(please | issue hunt) [<user.text>]:
key(cmd-k)
insert(user.text or "")

View file

@ -2,8 +2,8 @@ os: linux
-
show notifications: key(ctrl-`)
dismiss [notifications]: user.system_command("dunstctl close")
dismiss all [notifications]: user.system_command("dunstctl close-all")
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"')

View file

@ -0,0 +1,5 @@
os: linux
app.name: Gnome-terminal
-
tag(): terminal
tag(): user.git

View file

@ -0,0 +1,19 @@
os: linux
app: Guake
-
#comment or remove tags for command sets you don't want
#quake doesn't support the file_manager stuff
#tag(): user.file_manager
tag(): user.git
tag(): user.kubectl
tag(): user.tabs
tag(): terminal
action(app.tab_open):
key(ctrl-shift-t)
action(app.tab_close):
key(ctrl-shift-w)
action(app.tab_next):
key(ctrl-pagedown)
action(app.tab_previous):
key(ctrl-pageup)

View file

@ -10,12 +10,12 @@ quit: key(ctrl-q)
# Entries
[add] new entry: key(ctrl-n)
clone entry: key(ctrl-k)
(view | edit) entry: key(ctrl-e)
(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)
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)

View file

@ -5,24 +5,24 @@ show shortcuts: key("ctrl-/")
# Note that the order below matches Keyboard Shortcuts listings
# Navigation
(next | nav | navigate) [by] (sec | section): key("ctrl-t")
(prev | previous) (chat | conversation): key("alt-down")
next (chat | conversation): key("alt-up")
(prev | previous) unread: key("alt-shift-down")
(next|nav|navigate) [by] (sec|section): key("ctrl-t")
(prev|previous) (chat|conversation): key("alt-down")
next (chat|conversation): key("alt-up")
(prev|previous) unread: key("alt-shift-down")
next unread: key("alt-shift-up")
[open] (pref | preferences): key("ctrl-,")
[open] (pref|preferences): key("ctrl-,")
open conversation menu: key("ctrl-shift-l")
search: key("ctrl-f")
search chat: key("ctrl-shift-f")
focus (chat | composer): key("ctrl-shift-t")
focus (chat|composer): key("ctrl-shift-t")
open media: key("ctrl-shift-m")
open emoji: key("ctrl-shift-j")
open sticker: key("ctrl-shift-s")
record [voice] message: key("ctrl-shift-v")
archive chat: key("ctrl-shift-a")
unarchive chat: key("ctrl-shift-u")
(first | top) message: key("ctrl-up")
(last | bottom) message: key("ctrl-down")
(first|top) message: key("ctrl-up")
(last|bottom) message: key("ctrl-down")
close chat: key("ctrl-shift-c")
# Messages
@ -39,3 +39,4 @@ expand chat: key("ctrl-shift-x")
attach [file]: key("ctrl-u")
remove [link] preview: key("ctrl-p")
remove [link] attachment: key("ctrl-shift-p")

View file

@ -20,7 +20,7 @@ task add: "task add "
task add <user.text>: "task add {text}\n"
task undo: "task undo\n"
(tasks | task next): "task next\n"
(tasks|task next): "task next\n"
# task editing
task <number> edit$: "task {number} edit"

View file

@ -0,0 +1,46 @@
os: linux
tag: terminal
-
tag(): user.file_manager
#todo: generic tab commands
#tag(): tabs
action(edit.page_down):
key(shift-pagedown)
action(edit.page_up):
key(shift-pageup)
action(edit.paste):
key(ctrl-shift-v)
action(edit.copy):
key(ctrl-shift-c)
run last:
key(up)
key(enter)
rerun <user.text>:
key(ctrl-r)
insert(text)
rerun search:
key(ctrl-r)
kill all:
key(ctrl-c)
# XXX - these are specific to certain terminals only and should move into their
# own <term name>.talon file
action(edit.find):
key(ctrl-shift-f)
action(edit.word_left):
key(ctrl-w left)
action(edit.word_right):
key(ctrl-w right)
action(app.tab_open):
key(ctrl-shift-t)
action(app.tab_close):
key(ctrl-shift-w)
action(app.tab_next):
key(ctrl-pagedown)
action(app.tab_previous):
key(ctrl-pageup)
action(app.window_open):
key(ctrl-shift-n)
go tab <number>:
key("alt-{number}")

View file

@ -4,20 +4,22 @@ tag: user.tmux
mux: "tmux "
#session management
mux new session: insert("tmux new ")
mux new session:
insert('tmux new ')
mux sessions:
key(ctrl-b)
key(s)
mux name session:
key(ctrl-b)
key($)
mux kill session: insert("tmux kill-session -t ")
mux kill session:
insert('tmux kill-session -t ')
#window management
mux new window:
key(ctrl-b)
key(c)
mux window <number>:
key(ctrl-b)
key(ctrl-b )
key('{number}')
mux previous window:
key(ctrl-b)

View file

@ -0,0 +1,40 @@
os: mac
-
action(app.preferences):
key(cmd-,)
action(app.tab_close):
key(cmd-w)
#action(app.tab_detach):
# Move the current tab to a new window
action(app.tab_next):
key(cmd-alt-right)
action(app.tab_open):
key(cmd-t)
action(app.tab_previous):
key(cmd-alt-left)
action(app.tab_reopen):
key(cmd-shift-t)
action(app.window_close):
key(cmd-w)
action(app.window_hide):
key(cmd-m)
action(app.window_hide_others):
key(cmd-alt-h)
action(app.window_next):
key(cmd-`)
action(app.window_open):
key(cmd-n)
action(app.window_previous):
key(cmd-shift-`)

View file

@ -0,0 +1,17 @@
app: datagrip
-
run: key(cmd-enter)
run it:
key(cmd-enter)
sleep(50ms)
key(enter)
back:
key(alt-left)
fwack:
key(alt-right)
erase:
key(alt-backspace)
move up:
key(cmd-shift-up)
move down:
key(cmd-shift-down)

View file

@ -1,7 +1,26 @@
import contextlib
import time
from talon import Context, actions, ctrl, ui
from talon import actions, ctrl, Module, ui, Context
mod = Module()
@mod.action_class
class ModuleActions:
def desktop(number: int):
"change the current desktop"
def window_move_desktop_left():
"""move the current window to the desktop to the left"""
def window_move_desktop_right():
"""move the current window to the desktop to the right"""
def window_move_desktop(desktop_number: int):
"""move the current window to a different desktop"""
ctx = Context()
ctx.matches = r"""
@ -14,45 +33,33 @@ def _drag_window_mac(win=None):
if win is None:
win = ui.active_window()
fs = win.children.find(AXSubrole="AXFullScreenButton")[0]
rect = fs.AXFrame
x = rect.x + rect.width + 5
y = rect.y + rect.height / 2
previous_position = ctrl.mouse_pos()
rect = fs.AXFrame["$rect2d"]
x = rect["x"] + rect["width"] + 5
y = rect["y"] + rect["height"] / 2
ctrl.mouse_move(x, y)
ctrl.mouse_click(button=0, down=True)
yield
time.sleep(0.1)
ctrl.mouse_click(button=0, up=True)
ctrl.mouse_move(*previous_position)
@ctx.action_class("user")
@ctx.action_class("self")
class MacActions:
def desktop(number: int):
if number < 10:
actions.key(f"ctrl-{number}")
def desktop_next():
actions.key("ctrl-right")
def desktop_last():
actions.key("ctrl-left")
def desktop_show():
actions.key("ctrl-up")
actions.key("ctrl-{}".format(number))
def window_move_desktop_left():
with _drag_window_mac():
actions.user.desktop_last()
actions.key("ctrl-cmd-alt-left")
def window_move_desktop_right():
with _drag_window_mac():
actions.user.desktop_next()
actions.key("ctrl-cmd-alt-right")
def window_move_desktop(desktop_number: int):
# TODO: amethyst stuff should be pulled out into a separate file
if ui.apps(bundle="com.amethyst.Amethyst"):
actions.key(f"ctrl-alt-shift-{desktop_number}")
else:
with _drag_window_mac():
actions.user.desktop(desktop_number)
actions.key(f"ctrl-{desktop_number}")

View file

@ -1,7 +1,8 @@
desk <number_small>: user.desktop(number_small)
desk next: user.desktop_next()
desk last: user.desktop_last()
desk show: user.desktop_show()
# TODO: Once implementations exist for other platforms, maybe remove this
# restriction.
os: mac
-
desk <number>: user.desktop(number)
window move desk <number>: user.window_move_desktop(number)
window move desk left: user.window_move_desktop_left()
window move desk right: user.window_move_desktop_right()

View file

@ -0,0 +1,208 @@
os: mac
-
action(edit.copy):
key(cmd-c)
action(edit.cut):
key(cmd-x)
action(edit.delete):
key(backspace)
action(edit.delete_line):
edit.select_line()
edit.delete()
#action(edit.delete_paragraph):
#action(edit.delete_sentence):
action(edit.delete_word):
edit.select_word()
edit.delete()
action(edit.down):
key(down)
#action(edit.extend_again):
#action(edit.extend_column):
action(edit.extend_down):
key(shift-down)
action(edit.extend_file_end):
key(cmd-shift-down)
action(edit.extend_file_start):
key(cmd-shift-up)
action(edit.extend_left):
key(shift-left)
#action(edit.extend_line):
action(edit.extend_line_down):
key(shift-down)
action(edit.extend_line_end):
key(cmd-shift-right)
action(edit.extend_line_start):
key(cmd-shift-left)
action(edit.extend_line_up):
key(shift-up)
action(edit.extend_page_down):
key(cmd-shift-pagedown)
action(edit.extend_page_up):
key(cmd-shift-pageup)
#action(edit.extend_paragraph_end):
#action(edit.extend_paragraph_next()):
#action(edit.extend_paragraph_previous()):
#action(edit.extend_paragraph_start()):
action(edit.extend_right):
key(shift-right)
#action(edit.extend_sentence_end):
#action(edit.extend_sentence_next):
#action(edit.extend_sentence_previous):
#action(edit.extend_sentence_start):
action(edit.extend_up):
key(shift-up)
action(edit.extend_word_left):
key(shift-alt-left)
action(edit.extend_word_right):
key(shift-alt-right)
action(edit.file_end):
key(cmd-down cmd-left)
action(edit.file_start):
key(cmd-up cmd-left)
action(edit.find):
key(cmd-f)
#actions.insert(text)
action(edit.find_next):
key(cmd-g)
action(edit.find_previous):
key(cmd-shift-g)
action(edit.indent_less):
key(cmd-left delete)
action(edit.indent_more):
key(cmd-left tab)
#action(edit.jump_column(n: int)
#action(edit.jump_line(n: int)
action(edit.left):
key(left)
action(edit.line_down):
key(down home)
action(edit.line_end):
key(cmd-right)
action(edit.line_insert_down):
key(end enter)
action(edit.line_insert_up):
key(cmd-left enter up)
action(edit.line_start):
key(cmd-left)
action(edit.line_up):
key(up cmd-left)
#action(edit.move_again):
action(edit.page_down):
key(pagedown)
action(edit.page_up):
key(pageup)
#action(edit.paragraph_end):
#action(edit.paragraph_next):
#action(edit.paragraph_previous):
#action(edit.paragraph_start):
action(edit.paste):
key(cmd-v)
action(edit.paste_match_style):
key(cmd-alt-shift-v)
action(edit.print):
key(cmd-p)
action(edit.redo):
key(cmd-shift-z)
action(edit.right):
key(right)
action(edit.save):
key(cmd-s)
action(edit.save_all):
key(cmd-shift-s)
action(edit.select_all):
key(cmd-a)
action(edit.select_line):
key(cmd-right cmd-shift-left)
#action(edit.select_lines(a: int, b: int)):
action(edit.select_none):
key(right)
#action(edit.select_paragraph):
#action(edit.select_sentence):
action(edit.select_word):
edit.word_left()
edit.extend_word_right()
#action(edit.selected_text): -> str
#action(edit.sentence_end):
#action(edit.sentence_next):
#action(edit.sentence_previous):
#action(edit.sentence_start):
action(edit.undo):
key(cmd-z)
action(edit.up):
key(up)
action(edit.word_left):
key(alt-left)
action(edit.word_right):
key(alt-right)
action(edit.zoom_in):
key(cmd-=)
action(edit.zoom_out):
key(cmd--)
action(edit.zoom_reset):
key(cmd-0)

View file

@ -1,8 +1,10 @@
import os
from talon import Context, actions, ui
from talon import Context, Module, actions, imgui, settings, ui
from talon.experimental.locate import locate
from talon.mac import applescript
import os
mod = Module()
ctx = Context()
ctx.matches = r"""
app: finder
@ -12,10 +14,7 @@ directories_to_exclude = {}
@ctx.action_class("user")
class UserActions:
def file_manager_open_parent():
actions.key("cmd-up")
class user_actions:
def file_manager_current_path():
title = ui.active_window().title
@ -75,3 +74,10 @@ class UserActions:
"""selects the file"""
actions.key("home")
actions.insert(path)
@mod.action_class
class Actions:
def resize_finder_column():
"""Move mouse to resize a finder column"""
print(locate("templates/finder-resize.png"))

View file

@ -2,7 +2,18 @@ os: mac
app: finder
-
tag(): user.file_manager
tag(): user.tabs
action(user.file_manager_open_parent):
key(cmd-up)
action(user.file_manager_go_forward):
key("cmd-]")
action(user.file_manager_go_back):
key("cmd-[")
re size column: user.resize_finder_column()
preferences: key(cmd-,)
options: key(cmd-j)
search: key(cmd-alt-f)

View file

@ -1,31 +1,16 @@
from talon import Context, Module, actions
from talon import Context, Module, actions, imgui, settings, ui
import os
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:
class user_actions:
# def file_manager_current_path():
# title = ui.active_window().title
@ -70,12 +55,32 @@ class UserActions:
# """selects the file"""
# actions.insert(path)
def tab_jump(number: int):
actions.key(f"cmd-{number}")
def terminal_list_directories():
actions.insert("ls")
actions.key("enter")
def tab_final():
actions.key("cmd-9")
def terminal_list_all_directories():
actions.insert("ls -a")
actions.key("enter")
def terminal_change_directory(path: str):
actions.insert("cd {}".format(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")

View file

@ -4,8 +4,7 @@ app: iterm2
tag(): terminal
# todo: filemanager support
#tag(): user.file_manager
tag(): user.generic_unix_shell
tag(): user.generic_terminal
tag(): user.git
tag(): user.kubectl
tag(): user.tabs
tag(): user.readline

View file

@ -0,0 +1,11 @@
from talon import ctrl, ui, Module, Context, actions, clip, app
ctx = Context()
mod = Module()
apps = mod.apps
apps.preview = """
app.name: Preview
"""
ctx.matches = r"""
app: preview
"""

View file

@ -0,0 +1,9 @@
app: preview
-
<user.teleport> page <number>:
key(cmd-alt-g)
"{number}"
key(enter)
add text [<user.text>]:
key(cmd-ctrl-t:2)
insert(text or "")

View file

@ -0,0 +1,127 @@
os: mac
app: RStudio
-
run that: key("cmd-enter")
run document: key("cmd-alt-r")
run from top: key("cmd-alt-b")
run to end: key("cmd-alt-e")
run (function|funk): key("cmd-alt-f")
run section: key("cmd-alt-t")
run previous chunks: key("cmd-alt-p")
run chunk: key("cmd-alt-c")
run next chunk: key("cmd-alt-n")
run all: key("cmd-shift-s")
run knitter: key("cmd-shift-k")
run profiler: key("cmd-shift-alt-p")
# Moving around and formatting
jump back: key("cmd-f9")
jump forward: key("cmd-f10")
close all tabs: key("cmd-shift-w")
indent lines: key("cmd-i")
toggle comment: key("cmd-shift-c")
reformat comment: key("cmd-shift-/")
reformat R code: key("cmd-shift-a")
line up: key("alt-up")
line down: key("alt-down")
duplicate line up: key("cmd-alt-up")
duplicate line [down]: key("cmd-alt-down")
select to paren: key("ctrl-shift-e")
select to matching paren: key("ctrl-shift-alt-e")
jump to matching: key("ctrl-p")
expand selection: key("shift-alt-cmd-up")
reduce selection: key("shift-alt-cmd-down")
add cursor up: key("ctrl-alt-up")
add cursor down: key("ctrl-alt-down")
move active cursor up: key("ctrl-alt-shift-up")
move active cursor down: key("ctrl-alt-shift-down")
delete line: key("cmd-d")
delete word left: key("alt-backspace")
delete word right: key("alt-delete")
assign that: key("alt--")
pipe that: key("cmd-shift-m")
insert knitter chunk: key("cmd-alt-i")
# Folding
fold that: key("cmd-alt-l")
unfold that: key("cmd-shift-alt-l")
fold all: key("cmd-alt-o")
unfold all: key("cmd-shift-alt-o")
# Find and replace
find and replace: key("cmd-f")
find next: key("cmd-g")
find previous: key("cmd-shift-g")
find with selection: key("cmd-e")
find in files: key("cmd-shift-f")
run replace: key("cmd-shift-j")
run spell check: key("f7")
# Navigation and panels
go to source: key("ctrl-1")
go to console: key("ctrl-2")
go to help: key("ctrl-3")
go to history: key("ctrl-4")
go to files: key("ctrl-5")
go to (plots|plot): key("ctrl-6")
go to packages: key("ctrl-7")
go to environment: key("ctrl-8")
go to git: key("ctrl-9")
go to build: key("ctrl-0")
go to terminal: key("alt-shift-t")
go to omni: key("ctrl-.")
go to line: key("cmd-shift-alt-g")
go to section: key("cmd-shift-alt-j")
go to tab: key("ctrl-shift-.")
go to previous tab: key("ctrl-f11")
go to next tab: key("ctrl-f12")
go to first tab: key("ctrl-shift-f11")
go to last tab: key("ctrl-shift-f12")
zoom source: key("ctrl-shift-1")
(zoom|show) all: key("ctrl-shift-0")
help that: key("f1")
define that: key("f2")
previous plot: key("cmd-alt-f11")
next plot: key("cmd-alt-f12")
# devtools, package development, and session management
restart R session: key("cmd-shift-f10")
dev tools build: key("cmd-shift-b")
dev tools load all: key("cmd-shift-l")
dev tools test: key("cmd-shift-t")
dev tools check: key("cmd-shift-e")
dev tools document: key("cmd-shift-d")
# Debugging
toggle breakpoint: key("shift-f9")
debug next: key("f10")
debug step into (function|funk): key("shift-f4")
debug finish (function|funk): key("shift-f6")
debug continue: key("shift-f5")
debug stop: key("shift-f8")
# Git/SVN
run git diff: key("ctrl-alt-d")
run git commit: key("ctrl-alt-m")
# Other shortcuts that could be enabled
# run line and stay: key("alt-enter")
# run and echo all: key("cmd-shift-enter")
# extract (function|funk): key("cmd-alt-x")
# extract variable: key("cmd-alt-v")
# new terminal: key("shift-alt-t")
# rename current terminal: key("shift-alt-r")
# clear current terminal: key("ctrl-shift-l")
# previous terminal: key("ctrl-alt-f11")
# next terminal: key("ctrl-alt-f12")
# clear console: key("ctrl-l")
# popup history: key("cmd-up")
# change working directory: key("ctrl-shift-h")
# new document: key("cmd-shift-n")
# new document (chrome only): key("cmd-shift-alt-n")
# insert code section: key("cmd-shift-r")
# scroll diff view: key("ctrl-up/down")
# sync editor & pdf preview: key("cmd-f8")

View file

@ -0,0 +1,32 @@
from talon import ctrl, ui, Module, Context, actions, clip, app
ctx = Context()
mod = Module()
apps = mod.apps
mod.apps.safari = """
os: mac
and app.bundle: com.apple.Safari
"""
ctx.matches = r"""
app: safari
"""
@ctx.action_class("user")
class user_actions:
def tab_jump(number: int):
if number < 9:
actions.key("cmd-{}".format(number))
def tab_final():
actions.key("cmd-9")
@ctx.action_class("browser")
class browser_actions:
def go(url: str):
actions.browser.focus_address()
actions.sleep("50ms")
actions.insert(url)
actions.key("enter")

View file

@ -0,0 +1,68 @@
app: safari
-
tag(): browser
tag(): user.tabs
#action(browser.address):
action(browser.bookmark):
key(cmd-d)
action(browser.bookmark_tabs):
key(cmd-shift-d)
action(browser.bookmarks):
key(cmd-alt-b)
#action(browser.bookmarks_bar):
# key(ctrl-shift-b)
action(browser.focus_address):
key(cmd-l)
#action(browser.focus_page):
action(browser.focus_search):
browser.focus_address()
action(browser.go_blank):
key(cmd-n)
action(browser.go_back):
key(cmd-left)
action(browser.go_forward):
key(cmd-right)
action(browser.go_home):
key(cmd-shift-h)
action(browser.open_private_window):
key(cmd-shift-n)
action(browser.reload):
key(cmd-r)
action(browser.reload_hard):
key(cmd-shift-r)
#action(browser.reload_hardest):
#action(browser.show_clear_cache):
# key(cmd-shift-delete)
action(browser.show_downloads):
key(cmd-shift-j)
action(browser.show_extensions):
key(ctrl-shift-a)
action(browser.show_history):
key(cmd-y)
action(browser.submit_form):
key(enter)
#action(browser.title)
action(browser.toggle_dev_tools):
key(cmd-alt-i)

View file

@ -1,9 +1,6 @@
from talon import Context, Module, actions, imgui, settings, ui
import os
from talon import Context, actions, ui
# TODO: fit this to terminal.py
ctx = Context()
ctx.matches = r"""
app: apple_terminal
@ -12,21 +9,11 @@ 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:
class user_actions:
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)
@ -44,16 +31,10 @@ class UserActions:
def file_manager_open_directory(path: str):
"""opens the directory that's already visible in the view"""
actions.insert("cd ")
path = f'"{path}"'
path = '"{}"'.format(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")
actions.user.file_manager_refresh_title()
def file_manager_select_directory(path: str):
"""selects the directory"""
@ -61,7 +42,7 @@ class UserActions:
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}"'
name = '"{}"'.format(name)
actions.insert("mkdir " + name)
@ -74,17 +55,33 @@ class UserActions:
"""selects the file"""
actions.insert(path)
def file_manager_refresh_title():
return
def terminal_list_directories():
actions.insert("ls")
actions.key("enter")
def terminal_list_all_directories():
actions.insert("ls -a")
actions.key("enter")
@ctx.action_class("app")
class app_actions:
# other tab functions should already be implemented in
# code/platforms/mac/app.py
def terminal_change_directory(path: str):
actions.insert("cd {}".format(path))
if path:
actions.key("enter")
def tab_previous():
actions.key("ctrl-shift-tab")
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")
def tab_next():
actions.key("ctrl-tab")

View file

@ -0,0 +1,35 @@
app: apple_terminal
-
#comment or remove tags for command sets you don't want
tag(): user.file_manager
tag(): user.generic_terminal
tag(): user.git
tag(): user.kubectl
tag(): user.tabs
tag(): terminal
action(user.file_manager_open_parent):
insert("cd ..")
key(enter)
action(app.tab_open):
key(cmd-t)
action(app.tab_close):
key(cmd-w)
action(app.tab_next):
key(ctrl-tab)
action(app.tab_previous):
key(ctrl-shift-tab)
action(app.window_open):
key(cmd-n)
action(edit.page_down):
key(command-pagedown)
action(edit.page_up):
key(command-pageup)
rerun search:
key(ctrl-r)
suspend:
key(ctrl-z)
resume:
insert("fg")
key(enter)

View file

@ -0,0 +1,143 @@
from typing import Dict, Optional
import webbrowser
from talon import ctrl, ui, Module, Context, actions, clip, app
from dataclasses import dataclass
from things3.things3 import Things3
from ...code.create_spoken_forms import create_spoken_forms
import io
import csv
ctx = Context()
mod = Module()
apps = mod.apps
apps.things3 = """
app.name: Things
"""
ctx.matches = r"""
app: things3
"""
mod.list("things_tag", desc="Tags in Things")
mod.list("things_tag_with_shortcut", desc="Tags in Things within an assigned shortcut")
mod.list("things_project", desc="Areas and projects in Things")
things = Things3()
@dataclass
class Tag:
uuid: str
title: str
shortcut: Optional[str]
@dataclass
class Project:
uuid: str
title: str
raw_areas = things.get_areas()
raw_projects = things.get_projects()
sql_query = f"""
SELECT TAG.title, TAG.shortcut, TAG.uuid
FROM {things.TABLE_TAG} AS TAG
"""
tags = [Tag(**raw_tag) for raw_tag in things.execute_query(sql_query)]
projects = [
Project(uuid=raw_project["uuid"], title=raw_project["title"])
for raw_project in raw_areas + raw_projects
]
tag_map: Dict[str, Tag] = {tag.uuid: tag for tag in tags}
project_map = {project.uuid: project for project in projects}
ctx.lists["self.things_tag"] = {
spoken_form: tag.uuid
for tag in tags
for spoken_form in create_spoken_forms(tag.title)
}
ctx.lists["self.things_tag_with_shortcut"] = {
spoken_form: tag.uuid
for tag in tags
if tag.shortcut is not None
for spoken_form in create_spoken_forms(tag.title)
}
things_projects = {
spoken_form: project.uuid
for project in projects
for spoken_form in create_spoken_forms(project.title)
}
print(things_projects)
ctx.lists["self.things_project"] = things_projects
@mod.action_class
class Actions:
def tag_todo(things_tags: str):
"""Tag todo with a list of tags"""
tag_list = [tag_map[tag_uuid] for tag_uuid in things_tags.split(",")]
tags_with_shortcuts = [tag for tag in tag_list if tag.shortcut is not None]
tags_without_shortcuts = [tag for tag in tag_list if tag.shortcut is None]
for tag in tags_with_shortcuts:
actions.key(f"ctrl-{tag.shortcut}")
for tag in tags_without_shortcuts:
actions.key(f"cmd-shift-t")
actions.insert(tag.title)
actions.key("enter")
def filter_by_tag(things_tags: str):
"""Tag todo with a list of tags"""
tag_list = [tag_map[tag_uuid] for tag_uuid in things_tags.split(",")]
for tag in tag_list:
if tag.shortcut is None:
raise Exception("Can only filter by tags with assigned shortcuts")
actions.key(f"ctrl-alt-{tag.shortcut}")
def show_tag(things_tag: str):
"""Show a particular tag in things"""
tag = tag_map[things_tag]
webbrowser.open(f"things:///show?id={tag.uuid}")
def show_things_list(things_project: str):
"""Show a list in things"""
project = project_map[things_project]
webbrowser.open(f"things:///show?id={project.uuid}")
def move_todo(project: str):
"""Move todo to a particular list"""
try:
project = project_map[project].title
except KeyError:
pass
actions.key("cmd-shift-m")
actions.insert(project)
actions.key("enter")
@mod.capture(rule="{self.things_tag}+")
def things_tags(m) -> str:
"One or more Things tags"
return ",".join(m.things_tag_list)
@mod.capture(rule="{self.things_tag_with_shortcut}+")
def things_tags_with_shortcut(m) -> str:
"One or more Things tags"
return ",".join(m.things_tag_with_shortcut_list)
@mod.capture(rule="{self.things_project}+")
def things_projects(m) -> str:
"One or more Things projects"
return to_csv_row_string(m.things_project_list)
def to_csv_row_string(row_elements: str) -> str:
output = io.StringIO()
writer = csv.writer(output, quoting=csv.QUOTE_MINIMAL)
writer.writerow(row_elements)
return output.getvalue()

View file

@ -0,0 +1,51 @@
app: things3
-
tag(): user.todo_list
new task: key(cmd-n)
action(user.mark_complete): key(cmd-.)
action(user.mark_cancelled): key(cmd-alt-.)
action(user.show_inbox): key(cmd-1)
action(user.show_today): key(cmd-2)
action(user.show_upcoming): key(cmd-3)
action(user.show_anytime): key(cmd-4)
action(user.show_someday): key(cmd-5)
action(user.show_logbook): key(cmd-6)
show tag {user.things_tag}: user.show_tag(things_tag)
show list {user.things_project}: user.show_things_list(things_project)
follow link: key(cmd-alt-enter)
tag this <user.things_tags>: user.tag_todo(things_tags)
move this [to] {user.things_project}: user.move_todo(things_project)
move this [to] inbox: user.move_todo("Inbox")
do this today: key(cmd-t)
do this evening: key(cmd-e)
do this (anytime | any time): key(cmd-r)
do this someday: key(cmd-o)
do this <user.text>:
key(cmd-s)
insert(text)
key(enter)
deadline <user.text>:
key(cmd-shift-d)
insert(text)
key(enter)
clear deadline:
key(cmd-shift-d backspace enter)
filter [tag] <user.things_tags>: user.filter_by_tag(things_tags)
clear filter: key(ctrl-escape)
action(user.dental_click): key(cmd-enter)
add checklist: key(cmd-shift-c)
drag [this] way up: key(cmd-alt-up)
drag [this] way down: key(cmd-alt-down)
drag [this] up: key(cmd-up)
drag [this] down: key(cmd-down)

View file

@ -2,66 +2,64 @@ os: mac
app: slack
-
tag(): user.messaging
tag(): user.emoji
# Workspace
workspace <number>: key("cmd-{number}")
action(user.messaging_workspace_previous): key(cmd-shift-[)
action(user.messaging_workspace_next): key(cmd-shift-])
# Channel
(slack | lack) [channel] info: key(cmd-shift-i)
# Navigation
focus (move | next): key(ctrl-`)
(section | zone) [next]: key(f6)
(section | zone) (previous | last): key(shift-f6)
action(user.messaging_open_channel_picker): key(cmd-k)
action(user.messaging_channel_previous): key(alt-up)
action(user.messaging_channel_next): key(alt-down)
action(user.messaging_unread_previous): key(alt-shift-up)
action(user.messaging_unread_next): key(alt-shift-down)
# Navigation
(move | next) focus: key(ctrl-`)
[next] (section | zone): key(f6)
(previous | last) (section | zone): key(shift-f6)
(slack | lack) [direct] messages: key(cmd-shift-k)
(slack | lack) threads: key(cmd-shift-t)
(slack | lack) (history [next] | back | backward): key(cmd-[)
(slack | lack) forward: key(cmd-])
(element | bit) [next]: key(tab)
(element | bit) (previous | last): key(shift-tab)
[next] (element | bit): key(tab)
(previous | last) (element | bit): key(shift-tab)
(slack | lack) (my stuff | activity): key(cmd-shift-m)
(slack | lack) directory: key(cmd-shift-e)
(slack | lack) (starred [items] | stars): key(cmd-shift-s)
(slack | lack) unread [messages]: key(cmd-shift-a)
(slack | lack) unread [messages]: key(cmd-j)
(go | undo | toggle) full: key(ctrl-cmd-f)
# Messaging
action(user.messaging_open_search): key(cmd-f)
# Messaging
grab left: key(shift-up)
grab right: key(shift-down)
add line: key(shift-enter)
(slack | lack) (slap | slaw | slapper): key(cmd-right shift-enter)
(slack | lack) (react | reaction): key(cmd-shift-\)
(slack | lack) (react | reaction): key(cmd-shift-\\)
(insert command | commandify): key(cmd-shift-c)
insert link: key(cmd-shift-u)
insert code: key(cmd-shift-alt-c)
insert code:
insert("``````")
key(left left left)
key(shift-enter)
key(shift-enter)
key(up)
(slack | lack) (bull | bullet | bulleted) [list]: key(cmd-shift-8)
(slack | lack) (number | numbered) [list]: key(cmd-shift-7)
(slack | lack) (quotes | quotation): key(cmd-shift->)
bold: key(cmd-b)
(italic | italicize): key(cmd-i)
(strike | strikethrough): key(cmd-shift-x)
action(user.messaging_mark_workspace_read): key(shift-esc)
action(user.messaging_mark_channel_read): key(esc)
(clear | scrap | scratch): key(cmd-a backspace)
# Files and Snippets
action(user.messaging_upload_file): key(cmd-u)
(slack | lack) snippet: key(cmd-shift-enter)
# Calls
# Calls
([toggle] mute | unmute): key(m)
(slack | lack) huddle: key(cmd-shift-h)
(slack | lack) ([toggle] video): key(v)
(slack | lack) invite: key(a)
# Miscellaneous
# Miscellaneous
(slack | lack) shortcuts: key(cmd-/)
emote <user.text>: "{text}"
toggle left sidebar: key(cmd-shift-d)
toggle right sidebar: key(cmd-.)
# DEPRECATED
(move | next) focus:
app.notify("please use the voice command 'focus next' instead of 'next focus'")
key(ctrl-`)
[next] (section | zone):
app.notify("please use the voice command 'section next' instead of 'next section'")
key(f6)
(previous | last) (section | zone):
app.notify("please use the voice command 'section last' instead of 'last section'")
key(shift-f6)
[next] (element | bit):
app.notify("please use the voice command 'element next' instead of 'next element'")
key(tab)
(previous | last) (element | bit):
app.notify("please use the voice command 'element last' instead of 'last element'")
key(shift-tab)

View file

@ -0,0 +1,15 @@
from talon import Module
mod = Module()
apps = mod.apps
apps.slack = "app.name: Slack"
mod.apps.slack = """
os: windows
and app.name: slack.exe
os: windows
and app.exe: slack.exe
"""
apps.slack = """
os: mac
and app.bundle: com.tinyspeck.slackmacgap
"""

View file

@ -4,63 +4,64 @@ app: slack
#todo: some sort of plugin, consolidate with teams or something?
-
tag(): user.messaging
tag(): user.emoji
# Workspaces
workspace <number>: key("ctrl-{number}")
action(user.messaging_workspace_previous): key(ctrl-shift-tab)
action(user.messaging_workspace_next): key(ctrl-tab)
# Channel
(slack | lack) [channel] info: key(ctrl-shift-i)
action(user.messaging_open_channel_picker): key(ctrl-k)
action(user.messaging_channel_previous): key(alt-up)
action(user.messaging_channel_next): key(alt-down)
action(user.messaging_unread_previous): key(alt-shift-up)
action(user.messaging_unread_next): key(alt-shift-down)
# Navigation
focus (move | next): key(ctrl-`)
(section | zone) [next]: key(f6)
(section | zone) (previous | last): key(shift-f6)
(move | next) focus: key(ctrl-`)
[next] (section | zone): key(f6)
(previous | last) (section | zone): key(shift-f6)
(slack | lack) [direct] messages: key(ctrl-shift-k)
(slack | lack) threads: key(ctrl-shift-t)
(slack | lack) (history [next] | back | backward): key(alt-left)
(slack | lack) forward: key(alt-right)
(element | bit) [next]: key(tab)
(element | bit) (previous | last): key(shift-tab)
[next] (element | bit): key(tab)
(previous | last) (element | bit): key(shift-tab)
(slack | lack) (my stuff | activity): key(ctrl-shift-m)
(slack | lack) directory: key(ctrl-shift-e)
(slack | lack) (starred [items] | stars): key(ctrl-shift-s)
(slack | lack) unread [messages]: key(ctrl-shift-a)
(slack | lack) unread [messages]: key(ctrl-j)
#(go | undo | toggle) full: key(ctrl-cmd-f)
action(user.messaging_open_search): key(ctrl-f)
# Messaging
grab left: key(shift-up)
grab right: key(shift-down)
add line: key(shift-enter)
#"(slack | lack) (slap | slaw | slapper): [key(cmd-right) key(shift-enter")],
(slack | lack) (react | reaction): key(ctrl-shift-\)
(slack | lack) (react | reaction): key(ctrl-shift-\\)
(insert command | commandify): key(ctrl-shift-c)
insert code: insert("```")
insert code:
insert("``````")
key(left left left)
key(shift-enter)
key(shift-enter)
key(up)
(slack | lack) (bull | bullet | bulleted) [list]: key(ctrl-shift-8)
(slack | lack) (number | numbered) [list]: key(ctrl-shift-7)
(slack | lack) (quotes | quotation): key(ctrl-shift-9)
bold: key(ctrl-b)
(italic | italicize): key(ctrl-i)
(strike | strikethrough): key(ctrl-shift-x)
action(user.messaging_mark_workspace_read): key(shift-esc)
action(user.messaging_mark_channel_read): key(esc)
(clear | scrap | scratch): key(ctrl-a backspace)
# Files and Snippets
action(user.messaging_upload_file): key(ctrl-u)
(slack | lack) snippet: key(ctrl-shift-enter)
# Calls
# Calls
([toggle] mute | unmute): key(m)
(slack | lack) ([toggle] video): key(v)
(slack | lack) invite: key(a)
# Miscellaneous
# Miscellaneous
(slack | lack) shortcuts: key(ctrl-/)
emote <user.text>: "{text}"
toggle left sidebar: key(ctrl-shift-d)
toggle right sidebar: key(ctrl-.)
# DEPRECATED
(move | next) focus:
app.notify("please use the voice command 'focus next' instead of 'next focus'")
key(ctrl-`)
[next] (section | zone):
app.notify("please use the voice command 'section next' instead of 'next section'")
key(f6)
(previous | last) (section | zone):
app.notify("please use the voice command 'section last' instead of 'last section'")
key(shift-f6)
[next] (element | bit):
app.notify("please use the voice command 'element next' instead of 'next element'")
key(tab)
(previous | last) (element | bit):
app.notify("please use the voice command 'element last' instead of 'last element'")
key(shift-tab)

View file

@ -1,6 +1,4 @@
app: microsoft_teams
os: windows
os: linux
-
# Shortcut reference
@ -12,12 +10,19 @@ show shortcuts: key(ctrl-.)
show commands: key(ctrl-/)
open filter: key(ctrl-shift-f)
go to: key(ctrl-g)
open (apps | applications): key(ctrl-`)
open (apps|applications): key(ctrl-`)
[start] new chat: key(ctrl-n)
open settings: key(ctrl-,)
open help: key(f1)
close: key(escape)
#zoom in: key(ctrl-=)
#zoom out: key(ctrl--)
#reset zoom: key(ctrl-0)
action(edit.zoom_in): key(ctrl-=)
action(edit.zoom_out): key(ctrl--)
action(edit.zoom_reset): key(ctrl-0)
# navigations
open activity: key(ctrl-1)
open chat: key(ctrl-2)
@ -26,11 +31,11 @@ open calendar: key(ctrl-4)
open planner: key(ctrl-5)
open calls: key(ctrl-6)
open files: key(ctrl-7)
[go] [to] (prev | previous) [list] item: key(alt-up)
[go] [to] (prev|previous) [list] item: key(alt-up)
[go] [to] next [list] item: key(alt-down)
move [selected] team up: key(ctrl-shift-up)
move [selected] team down: key(ctrl-shift-down)
[go] [to] (prev | previous) section: key(ctrl-shift-f6)
[go] [to] (prev|previous) section: key(ctrl-shift-f6)
[go] [to] next section: key(ctrl-f6)
# messaging
@ -55,11 +60,11 @@ decline screen share: key(ctrl-shift-d)
accept screen share: key(ctrl-shift-a)
schedule [a] meeting: key(alt-shift-n)
go to current time: key(alt-.)
go to (prev | previous) (day | week): key(ctrl-alt-left)
go to next (day | week): key(ctrl-alt-right)
go to (prev|previous) (day|week): key(ctrl-alt-left)
go to next (day|week): key(ctrl-alt-right)
view day: key(ctrl-alt-1)
view work week: key(ctrl-alt-2)
view week: key(ctrl-alt-3)
(safe | send) meeting request: key(ctrl-s)
(safe|send) meeting request: key(ctrl-s)
join [from] meeting [details]: key(alt-shift-j)
go to suggested time: key(alt-shift-s)

View file

@ -1,6 +1,5 @@
# vs title tracking requires an extension
# https://marketplace.visualstudio.com/items?itemName=mayerwin.RenameVisualStudioWindowTitle
# https://github.com/mayerwin/vs-customize-window-title (VS 2022 support in releases)
# I currently configure the extension as below
# Document (no solution) open: [documentName] - [ideName]
# No document or solution open: [idleName]
@ -8,7 +7,8 @@
# Solution in design mode: [documentName] - [parentPath]\[solutionName] - [ideName]
# Solution in running mode: [documentName] - [parentPath]\[solutionName] (Running) - [ideName]
from talon import Context, Module, actions
from talon import Context, actions, ui, Module, app, clip
from typing import List, Union
# is_mac = app.platform == "mac"
@ -18,8 +18,6 @@ mod = Module()
apps = mod.apps
apps.visual_studio = """
os: windows
and app.name: Microsoft Visual Studio 2022
os: windows
and app.name: Microsoft Visual Studio 2019
os: windows
and app.name: devenv.exe
@ -30,55 +28,29 @@ ctx.matches = r"""
app: visual_studio
"""
from talon import Context, actions
ctx = Context()
ctx.matches = r"""
os: windows
app: visual_studio
"""
@ctx.action_class("win")
class win_actions:
def filename():
title = actions.win.title()
# this doesn't seem to be necessary on VSCode for Mac
# if title == "":
# title = ui.active_window().doc
result = title.split("-")[0].rstrip()
@ctx.action_class("app")
class AppActions:
# talon app actions
def tab_close():
actions.key("ctrl-f4")
if "." in result:
# print(result)
return result
def tab_next():
actions.key("ctrl-tab")
def tab_previous():
actions.key("ctrl-shift-tab")
def tab_reopen():
actions.key("ctrl-1 ctrl-r enter")
@ctx.action_class("code")
class CodeActions:
# talon code actions
def toggle_comment():
actions.key("ctrl-k ctrl-/")
return ""
@ctx.action_class("edit")
class EditActions:
# talon edit actions
def indent_more():
actions.key("tab")
def indent_less():
actions.key("shift-tab")
def save_all():
actions.key("ctrl-shift-s")
def find_next():
actions.key("enter")
def find_previous():
actions.key("shift-enter")
class edit_actions:
def find(text: str):
actions.key("ctrl-f")
actions.insert(text)
def line_swap_up():
actions.key("alt-up")
@ -96,25 +68,21 @@ class EditActions:
actions.key("enter")
@ctx.action_class("win")
class WinActions:
def filename():
title = actions.win.title()
# this doesn't seem to be necessary on VSCode for Mac
# if title == "":
# title = ui.active_window().doc
result = title.split("-")[0].rstrip()
if "." in result:
# print(result)
return result
return ""
@ctx.action_class("user")
class UserActions:
class user_actions:
# snippet.py support beginHelp close
def snippet_search(text: str):
"""TEST"""
actions.key("ctrl-k ctrl-x")
# def snippet_insert(text: str):
# """Inserts a snippet"""
# def snippet_create():
# """Triggers snippet creation"""
# snippet.py support end
# def select_word(verb: str):
# actions.key("ctrl-w")
# actions.user.perform_selection_action(verb)
@ -169,6 +137,19 @@ class UserActions:
# find_and_replace.py support begin
def find(text: str):
"""Triggers find in current editor"""
actions.key("ctrl-f")
if text:
actions.insert(text)
def find_next():
actions.key("enter")
def find_previous():
actions.key("shift-enter")
def find_everywhere(text: str):
"""Triggers find across project"""
actions.key("ctrl-shift-f")
@ -223,26 +204,3 @@ class UserActions:
# find_and_replace.py support end
# multiple_cursor.py support begin
# note: visual studio has no explicit mode for multiple cursors; requires https://marketplace.visualstudio.com/items?itemName=VaclavNadrasky.MultiCaretBooster
def multi_cursor_add_above():
actions.key("shift-alt-up")
def multi_cursor_add_below():
actions.key("shift-alt-down")
# action(user.multi_cursor_add_to_line_ends): does not exist :(
def multi_cursor_disable():
actions.key("escape")
def multi_cursor_enable():
actions.skip()
def multi_cursor_select_all_occurrences():
actions.key("shift-alt-;")
def multi_cursor_select_fewer_occurrences():
actions.key("shift-alt-k")
def multi_cursor_select_more_occurrences():
actions.key("shift-alt->")

View file

@ -1,10 +1,37 @@
os: windows
app: visual_studio
app: Microsoft Visual Studio 2019
app: devenv.exe
-
tag(): user.tabs
tag(): user.line_commands
tag(): user.find_and_replace
tag(): user.snippets
tag(): user.multiple_cursors
#talon app actions
action(app.tab_close): key(ctrl-f4)
action(app.tab_next): key(ctrl-tab)
action(app.tab_previous): key(ctrl-shift-tab)
action(app.tab_reopen): key(ctrl-1 ctrl-r enter)
#talon code actions
action(code.toggle_comment): key(ctrl-k ctrl-/)
#talon edit actions
action(edit.indent_more): key(tab)
action(edit.indent_less): key(shift-tab)
action(edit.save_all): key(ctrl-shift-s)
#multiple_cursor.py support begin
#note: visual studio has no explicit mode for multiple cursors; requires https://marketplace.visualstudio.com/items?itemName=VaclavNadrasky.MultiCaretBooster
action(user.multi_cursor_add_above): key(shift-alt-up)
action(user.multi_cursor_add_below): key(shift-alt-down)
#action(user.multi_cursor_add_to_line_ends): does not exist :(
action(user.multi_cursor_disable): key(escape)
action(user.multi_cursor_enable): skip()
action(user.multi_cursor_select_all_occurrences): key(shift-alt-;)
action(user.multi_cursor_select_fewer_occurrences): key(shift-alt-k)
action(user.multi_cursor_select_more_occurrences): key(shift-alt->)
#multiple_cursor.py support end
# Panels
@ -92,3 +119,4 @@ debug step out [of]: key(f10)
debug start: key(f5)
debug stopper: key(shift-f5)
debug continue: key(f5)
#debug restart:

View file

@ -0,0 +1,5 @@
# VSCode support
Assumes that you have the [Run Command by
Id](https://marketplace.visualstudio.com/items?itemName=pokey.run-command-by-id)
extension installed.

View file

@ -0,0 +1,167 @@
import requests
import time
import json
from typing import Any
from talon import Module, actions, app
from pathlib import Path
from tempfile import gettempdir
is_mac = app.platform == "mac"
mod = Module()
class NotSet:
def __repr__(self):
return "<argument not set>"
def run_vscode_command(
command: str,
*args: str,
wait_for_finish: bool = False,
expect_response: bool = False,
decode_json_arguments: bool = False,
):
"""Execute command via vscode command server."""
# NB: This is a hack to work around the fact that talon doesn't support
# variable argument lists
args = list(
filter(
lambda x: x is not NotSet,
args,
)
)
if decode_json_arguments:
args = [json.loads(arg) for arg in args]
port_file_path = Path(gettempdir()) / "vscode-port"
original_contents = port_file_path.read_text()
# Issue command to VSCode telling it to update the port file. Because only
# the active VSCode instance will accept keypresses, we can be sure that
# the active VSCode instance will be the one to write the port.
if is_mac:
actions.key("cmd-shift-alt-p")
else:
actions.key("ctrl-shift-alt-p")
# Wait for the VSCode instance to update the port file. This generally
# happens within the first millisecond, but we give it 3 seconds just in
# case.
start_time = time.monotonic()
new_contents = port_file_path.read_text()
sleep_time = 0.0005
while True:
if new_contents != original_contents:
try:
decoded_contents = json.loads(new_contents)
# If we're successful, we break out of the loop
break
except ValueError:
# If we're not successful, we keep waiting; we assume it was a
# partial write from VSCode
pass
time.sleep(sleep_time)
sleep_time *= 2
if time.monotonic() - start_time > 3.0:
raise Exception("Timed out waiting for VSCode to update port file")
new_contents = port_file_path.read_text()
port = decoded_contents["port"]
response = requests.post(
f"http://localhost:{port}/execute-command",
json={
"commandId": command,
"args": args,
"waitForFinish": wait_for_finish,
"expectResponse": expect_response,
},
timeout=(0.05, 3.05),
)
response.raise_for_status()
actions.sleep("25ms")
if expect_response:
return response.json()
@mod.action_class
class Actions:
def vscode(
command: str,
arg1: Any = NotSet,
arg2: Any = NotSet,
arg3: Any = NotSet,
arg4: Any = NotSet,
arg5: Any = NotSet,
):
"""Execute command via vscode command server."""
run_vscode_command(
command,
arg1,
arg2,
arg3,
arg4,
arg5,
)
def vscode_and_wait(
command: str,
arg1: Any = NotSet,
arg2: Any = NotSet,
arg3: Any = NotSet,
arg4: Any = NotSet,
arg5: Any = NotSet,
):
"""Execute command via vscode command server and wait for command to finish."""
run_vscode_command(
command,
arg1,
arg2,
arg3,
arg4,
arg5,
wait_for_finish=True,
)
def vscode_json_and_wait(
command: str,
arg1: Any = NotSet,
arg2: Any = NotSet,
arg3: Any = NotSet,
arg4: Any = NotSet,
arg5: Any = NotSet,
):
"""Execute command via vscode command server and wait for command to finish."""
run_vscode_command(
command,
arg1,
arg2,
arg3,
arg4,
arg5,
wait_for_finish=True,
decode_json_arguments=True,
)
def vscode_get(
command: str,
arg1: Any = NotSet,
arg2: Any = NotSet,
arg3: Any = NotSet,
arg4: Any = NotSet,
arg5: Any = NotSet,
) -> Any:
"""Execute command via vscode command server and return command output."""
return run_vscode_command(
command,
arg1,
arg2,
arg3,
arg4,
arg5,
expect_response=True,
)

View file

@ -0,0 +1,77 @@
from user.pokey_talon.code.terms import SELECT, TELEPORT, DELETE, FIND
from talon import Context, actions, ui, Module, app, clip
mod = Module()
ctx = Context()
ctx.matches = r"""
app: vscode
"""
# TODO A lot of these could be supported by supporting a proper "pop back"
# Would basically use the same logic that is used for updating token ranges
mod.list("simple_cursorless_action", desc="Supported actions for cursorless navigation")
ctx.lists["self.simple_cursorless_action"] = {
# Accepts any single extent
"spring": "setSelection",
SELECT: "setSelection",
"pree": "setSelectionBefore",
"post": "setSelectionAfter",
DELETE: "delete",
"clear": "clear",
# "sort": "sortLines",
# "join": "joinLines",
# "float": "insertEmptyLineBelow",
# "drop": "insertEmptyLineBelow",
# Sort children?? (would need to sort only named ones to avoid commas)
# Reverse children
# "cut": "cut",
# "copy": "copy",
# FIND: "findInFile",
# f"{FIND} last": "findBackwardsInFile",
# f"{FIND} all": "findAll",
# "fold": "fold",
# "stack": "addCursorAt",
# "cursor all": "addCursorToAllLines",
# "remove cursor": "removeCursor",
# "tab": "indent",
# "retab": "dedent",
# "comment": "comment",
# "github open": "openInGithub",
# "smear": "cloneLineDown",
# # Accepts only single token
# "rename": "rename",
# "ref show": "showReferences",
# "def show": "showDefinition",
# "hover show": "showHover",
# "act up": "scrollToTop",
# "act eat": "scrollToMid",
# "act down": "scrollToBottom",
# "breakpoint": "addBreakPoint",
# # Accepts position
# "paste": "paste",
}
{
# Require 2 extents of any kind, but prob best to assume second extend is
# same type as first, and need to explicitly say "token" if you want to use
# a token for the second one if the first is not
# Note: these should actually be of the form "swap <range> with"
"swap": "swap",
# Require 1 extent of any kind and 1 position, but prob best to assume
# the position is same type as extent, and need to explicitly say "token"
# if you want to use a token for the second one if the first is not
"use": "use",
# Require 1 extent of any kind, and 1 format string (eg "camel foo bar",
# "phrase hello world" etc, "spell air bat cap")
# Note: these should actually be of the form "replace <range> with"
# Could also except a second extent, and that would replace it with that
# extent
"replace with": "replaceWith",
# Require 1 extent of any kind, and 1 format type (eg camel, uppercase,
# phrase etc)
# Note: these should actually be of the form "reformat <range> as"
"reformat as": "reformatAs",
}
"<user.search_engine>"
"phones"

View file

@ -0,0 +1,27 @@
from talon import Context, actions, ui, Module, app, clip
import json
from typing import Any
from ..command_client import NotSet
mod = Module()
@mod.action_class
class Actions:
def cursorless_single_target_command(
action: str,
target: str,
arg1: Any = NotSet,
arg2: Any = NotSet,
arg3: Any = NotSet,
):
"""Execute single-target cursorlses command"""
actions.user.vscode_and_wait(
"cursorless.command",
action,
[json.loads(target)],
arg1,
arg2,
arg3,
)

View file

@ -0,0 +1,35 @@
app: vscode
-
{self.simple_cursorless_action} <user.cursorless_arg>:
user.cursorless_single_target_command(simple_cursorless_action, cursorless_arg)
drink <user.cursorless_arg>:
user.cursorless_single_target_command("setSelection", cursorless_arg)
user.new_line_above()
pour <user.cursorless_arg>:
user.cursorless_single_target_command("setSelection", cursorless_arg)
user.new_line_below()
funk wrap <user.cursorless_arg> with <user.code_functions>:
user.cursorless_single_target_command("wrap", cursorless_arg, "{code_functions}(", ")")
square wrap <user.cursorless_arg>:
user.cursorless_single_target_command("wrap", cursorless_arg, "[", "]")
round wrap <user.cursorless_arg>:
user.cursorless_single_target_command("wrap", cursorless_arg, "(", ")")
curly wrap <user.cursorless_arg>:
user.cursorless_single_target_command("wrap", cursorless_arg, "{", "}")
(diamond | angle) wrap <user.cursorless_arg>:
user.cursorless_single_target_command("wrap", cursorless_arg, "<", ">")
quad wrap <user.cursorless_arg>:
user.cursorless_single_target_command("wrap", cursorless_arg, "\"", "\"")
twin wrap <user.cursorless_arg>:
user.cursorless_single_target_command("wrap", cursorless_arg, "'", "'")
action(user.dental_click): user.vscode("cursorless.toggleDecorations")

View file

@ -0,0 +1,42 @@
import json
from .target import BASE_TARGET, cursor_mark
from talon import Context, actions, ui, Module, app, clip
mod = Module()
@mod.capture(
rule=(
"<user.cursorless_target> | "
"through <user.cursorless_target> | "
"[range] <user.cursorless_target> through <user.cursorless_target>"
)
)
def cursorless_range(m) -> str:
if "through" in m:
end = json.loads(m[-1])
if m[0] == "through":
start = BASE_TARGET.copy()
else:
start = json.loads(m.cursorless_target_list[0])
return json.dumps(
{
"type": "range",
"start": start,
"end": end,
}
)
return m[0]
@mod.capture(rule=("<user.cursorless_range> (and <user.cursorless_range>)*"))
def cursorless_arg(m) -> str:
if len(m.cursorless_range_list) == 1:
return m.cursorless_range
return json.dumps(
{
"type": "list",
"elements": [json.loads(match) for match in m.cursorless_range_list],
}
)

View file

@ -0,0 +1,344 @@
from ....code.terms import SELECT, TELEPORT, DELETE, FIND
from enum import Enum
from dataclasses import dataclass
from ....code.keys import symbol_key_words
import json
from talon import Context, actions, ui, Module, app, clip
ctx = Context()
mod = Module()
ctx.matches = r"""
app: vscode
"""
mod.list("symbol_color", desc="Supported symbol colors for token jumping")
ctx.lists["self.symbol_color"] = {
"gray": "default",
"blue": "blue",
"green": "green",
"rose": "red",
"squash": "yellow",
"plum": "mauve",
}
CONNECTIVES = {"at", "of", "in", "containing"}
BASE_TARGET = {"type": "primitive"}
@mod.capture(
rule=(
"[{user.cursorless_position}] "
"[{user.cursorless_pair_surround_type}] "
"[{user.cursorless_selection_type} [of | in | containing]] "
"[<user.cursorless_range_transformation>] "
"[<user.cursorless_indexer> [at]]"
"(<user.decorated_symbol> | {user.cursorless_mark} | {user.unmarked_core} | <user.cursorless_surrounding_pair> | <user.cursorless_containing_scope> | <user.cursorless_indexer>)"
"[<user.cursorless_indexer> | {user.cursorless_matching}]"
)
)
def cursorless_target(m) -> str:
"""Supported extents for cursorless navigation"""
object = BASE_TARGET.copy()
for capture in m:
if capture in CONNECTIVES:
continue
for key, value in json.loads(capture).items():
if (
key in object
and key == SELECTION_TYPE_KEY
and ranked_selection_types[value] < ranked_selection_types[object[key]]
):
continue
object[key] = value
return json.dumps(object)
@dataclass
class ModifierTerm:
term: str
info: dict
@property
def value(self):
return json.dumps(self.info)
def make_simple_transformation(type: str):
return {"transformation": {"type": type}}
matching_transformation = ModifierTerm(
"matching", make_simple_transformation("matchingPairSymbol")
)
mod.list("cursorless_matching", desc="Supported symbol extent types")
ctx.lists["self.cursorless_matching"] = {
matching_transformation.term: matching_transformation.value
}
containing_scope_type_map = {
"arg": "argumentOrParameter",
"arrow": "arrowFunction",
"class": "class",
"funk": "namedFunction",
"if": "ifStatement",
"lambda": "arrowFunction",
"map": "dictionary",
"pair": "pair",
"value": "pairValue",
"key": "pairKey",
}
containing_scope_types = {
term: {
"transformation": {
"type": "containingScope",
"scopeType": containing_scope_type,
}
}
for term, containing_scope_type in containing_scope_type_map.items()
}
mod.list("containing_scope_type", desc="Supported symbol extent types")
ctx.lists["self.containing_scope_type"] = {
key: json.dumps(value) for key, value in containing_scope_types.items()
}
SELECTION_TYPE_KEY = "selectionType"
@dataclass
class SelectionType:
singular: str
plural: str
json_name: str
rank: int
@property
def json_repr(self):
return {SELECTION_TYPE_KEY: self.json_name}
TOKEN = SelectionType("token", "tokens", "token", 0)
LINE = SelectionType("line", "lines", "line", 1)
BLOCK = SelectionType("block", "blocks", "block", 2)
SELECTION_TYPES = [
TOKEN,
LINE,
BLOCK,
]
ranked_selection_types = {
selection_type.json_name: selection_type.rank for selection_type in SELECTION_TYPES
}
cursor_mark = {"mark": {"type": "cursor"}}
marks = {
"here": cursor_mark,
"this": cursor_mark,
**{
f"this {selection_type.singular}": {**selection_type.json_repr, **cursor_mark}
for selection_type in SELECTION_TYPES
},
**{
f"these {selection_type.plural}": {**selection_type.json_repr, **cursor_mark}
for selection_type in SELECTION_TYPES
},
"change": {"mark": {"type": "lastEditRange"}},
"last cursor": {"mark": {"type": "lastCursorPosition"}},
**{
f"this {containing_scope_type}": {**cursor_mark, **value}
for containing_scope_type, value in containing_scope_types.items()
},
}
mod.list("cursorless_mark", desc="Types of marks")
ctx.lists["self.cursorless_mark"] = {
key: json.dumps(value) for key, value in marks.items()
}
unmarked_cores = {
**containing_scope_types,
**{
selection_type.singular: selection_type.json_repr
for selection_type in SELECTION_TYPES
},
matching_transformation.term: matching_transformation.info,
}
mod.list("unmarked_core", desc="Core terms whose mark must be inferred")
ctx.lists["self.unmarked_core"] = {
key: json.dumps(value) for key, value in unmarked_cores.items()
}
positions = {
"after": {"position": "after"},
"before": {"position": "before"},
"start of": {"position": "before", "insideOutsideType": "inside"},
"end of": {"position": "after", "insideOutsideType": "inside"},
"above": {"position": "before", **LINE.json_repr},
"below": {"position": "after", **LINE.json_repr},
}
mod.list("cursorless_position", desc="Types of positions")
ctx.lists["self.cursorless_position"] = {
key: json.dumps(value) for key, value in positions.items()
}
selection_type_map = {}
for selection_type in SELECTION_TYPES:
selection_type_map[selection_type.singular] = selection_type.json_repr
selection_type_map[selection_type.plural] = selection_type.json_repr
mod.list("cursorless_selection_type", desc="Types of selection_types")
ctx.lists["self.cursorless_selection_type"] = {
key: json.dumps(value) for key, value in selection_type_map.items()
}
@mod.capture(rule="[at] [{user.symbol_color}] <user.any_alphanumeric_key>")
def decorated_symbol(m) -> str:
"""A decorated symbol"""
try:
symbol_color = m.symbol_color
except AttributeError:
symbol_color = "default"
character = m.any_alphanumeric_key
return json.dumps(
{
"mark": {
"type": "decoratedSymbol",
"symbolColor": symbol_color,
"character": character,
}
}
)
mod.list("cursorless_sub_component_type", desc="Supported subcomponent types")
ctx.lists["self.cursorless_sub_component_type"] = {
"small": "subtoken",
"subtoken": "subtoken",
"subtokens": "subtoken",
"subword": "subtoken",
"subwords": "subtoken",
"car": "character",
"cars": "character",
"character": "character",
"characters": "character",
"letter": "character",
"letters": "character",
}
@mod.capture(
rule=(
"<user.ordinals> [through <user.ordinals>] {user.cursorless_sub_component_type}"
)
)
def cursorless_indexer(m) -> str:
"""Supported extents for cursorless navigation"""
return json.dumps(
{
"transformation": {
"type": "subpiece",
"pieceType": m.cursorless_sub_component_type,
"startIndex": m.ordinals_list[0],
"endIndex": m.ordinals_list[-1] + 1,
}
}
)
pair_symbols = {
"[": "squareBrackets",
"]": "squareBrackets",
"{": "curlyBrackets",
"}": "curlyBrackets",
"<": "angleBrackets",
">": "angleBrackets",
"(": "parentheses",
")": "parentheses",
'"': "doubleQuotes",
"'": "singleQuotes",
}
mod.list("pair_symbol", desc="A pair symbol")
ctx.lists["self.pair_symbol"] = {
phrase: pair_symbols[character]
for phrase, character in symbol_key_words.items()
if character in pair_symbols
}
cursorless_pair_surround_types = {
"out": {"insideOutsideType": "outside"},
"outer": {"insideOutsideType": "outside"},
"outside": {"insideOutsideType": "outside"},
"in": {"insideOutsideType": "inside"},
"inner": {"insideOutsideType": "inside"},
"inside": {"insideOutsideType": "inside"},
}
mod.list("cursorless_pair_surround_type", desc="Supported pair surround types")
ctx.lists["self.cursorless_pair_surround_type"] = {
key: json.dumps(value) for key, value in cursorless_pair_surround_types.items()
}
@mod.capture(rule=("{user.cursorless_pair_surround_type} {user.pair_symbol}"))
def cursorless_surrounding_pair(m) -> str:
"""Supported extents for cursorless navigation"""
return json.dumps(
{
"transformation": {
"type": "surroundingPair",
"delimiter": m.pair_symbol,
}
** json.loads(m.cursorless_pair_surround_type),
}
)
simple_transformations = [
matching_transformation,
]
mod.list("cursorless_simple_transformations", desc="simple transformations")
ctx.lists["self.cursorless_simple_transformations"] = {
transformation.term: transformation.value
for transformation in simple_transformations
}
@mod.capture(rule=("[every] {user.containing_scope_type} [containing]"))
def cursorless_containing_scope(m) -> str:
"""Supported extents for cursorless navigation"""
if m[0] in ["every"]:
current_target = json.loads(m.containing_scope_type)
current_target["transformation"]["includeSiblings"] = True
return json.dumps(current_target)
return m.containing_scope_type
@mod.capture(
rule=(
"<user.cursorless_surrounding_pair> |"
"{user.cursorless_simple_transformations} |"
"<user.cursorless_containing_scope>"
)
)
def cursorless_range_transformation(m) -> str:
"""Supported positions for cursorless navigation"""
return str(m)

View file

@ -0,0 +1,19 @@
app: vscode
-
# (<user.select> | spring) [{user.symbol_color}] <user.any_alphanumeric_key>:
# user.vscode_and_wait("decorative-navigation.selectToken", symbol_color or "default", any_alphanumeric_key)
# sleep(50ms)
# pree [{user.symbol_color}] <user.any_alphanumeric_key>:
# user.vscode("decorative-navigation.selectToken", symbol_color or "default", any_alphanumeric_key)
# key(left)
# post [{user.symbol_color}] <user.any_alphanumeric_key>:
# user.vscode("decorative-navigation.selectToken", symbol_color or "default", any_alphanumeric_key)
# key(right)
# def show [{user.symbol_color}] <user.any_alphanumeric_key>:
# user.vscode("decorative-navigation.selectToken", symbol_color or "default", any_alphanumeric_key)
# user.vscode("editor.action.revealDefinition")
# action(user.dental_click): user.vscode("decorative-navigation.toggleDecorations")

View file

@ -0,0 +1,49 @@
app: vscode
-
# <user.select> line up: user.vscode("metaGo.selectLineUp")
# <user.select> line: user.vscode("metaGo.selectLineDown")
bracket switch: user.vscode("metaGo.changeSurroundingPair")
# <user.teleport> to: user.vscode("metaGo.gotoSmart")
# <user.teleport> word <word>: user.jump("metaGo.gotoSmart", word)
# <user.select> before: user.vscode("metaGo.gotoBefore")
# <user.select> after: user.vscode("metaGo.gotoAfter")
razor: user.vscode("metaGo.gotoEmptyLineUp")
dropper: user.vscode("metaGo.gotoEmptyLineDown")
# <user.teleport> bracket: user.vscode("metaGo.jumpToBracket")
# <user.teleport> very:
# key(cmd-shift-. enter)
# <user.select> to: user.vscode("metaGo.selectSmart")
# tasty: user.vscode("metaGo.selectBefore")
# toasty: user.vscode("metaGo.selectAfter")
<user.select> upper: user.vscode("metaGo.selectEmptyLineUp")
<user.select> downer: user.vscode("metaGo.selectEmptyLineDown")
<user.delete> downer:
user.vscode("metaGo.selectEmptyLineDown")
key(backspace)
<user.delete> upper:
user.vscode("metaGo.selectEmptyLineUp")
key(backspace)
# <user.select> outside: user.vscode("metaGo.inSurroundingPairSelectionWithPairs")
# <user.select> inside <user.symbol_key>:
# user.vscode("metaGo.inSurroundingPairSelection")
# key(symbol_key)
# sleep(25ms)
# cursor add: user.vscode("metaGo.addCursorSmart")
# cursor add before: user.vscode("metaGo.addCursorBefore")
# cursor add after: user.vscode("metaGo.addCursorAfter")
act up: user.vscode("metaGo.scrollCurrentLineToTop")
act eat: user.vscode("metaGo.scrollCurrentLineToMiddle")
act down: user.vscode("metaGo.scrollCurrentLineToBottom")
<user.select> right big: user.vscode("metaGo.cursorSpaceWordRightSelect")
<user.select> left big: user.vscode("metaGo.cursorSpaceWordLeftSelect")
tug big: user.vscode("metaGo.cursorSpaceWordLeft")
push big: user.vscode("metaGo.cursorSpaceWordRight")
swap anchor: user.vscode("metaGo.selectionSwitchActiveWithAnchor")

View file

@ -0,0 +1,43 @@
from talon import Context, actions, ui, Module, app
# from user.knausj_talon.code.snippet_watcher import snippet_watcher
import os
ctx = Context()
ctx.matches = r"""
app: vscode
mode: user.csharp
mode: command
and code.language: csharp
"""
# short name -> ide clip name
ctx.lists["user.snippets"] = {
"class": "class",
"else": "else",
"for each": "foreach",
"if": "if",
"try except": "try",
"try finally": "tryf",
"while": "while",
# "class funky": "def(class method)",
# "class static funky": "def(class static method)",
# "for": "for",
# "funky": "def",
}
# def update_list(watch_list):
# ctx.lists["user.snippets"] = watch_list
# # there's probably a way to do this without
# snippet_path = None
# if app.platform == "windows":
# snippet_path = os.path.expandvars(r"%AppData%\Code\User\snippets")
# elif app.platform == "mac":
# snippet_path = os.path.expanduser(
# "~/Library/Application Support/Code/User/snippets"
# )
# if snippet_path:
# watcher2 = snippet_watcher({snippet_path: ["csharp.json",],}, update_list,)
# print("reloaded!")

View file

@ -0,0 +1,44 @@
from talon import Context, actions, ui, Module, app
# from user.knausj_talon.code.snippet_watcher import snippet_watcher
import os
ctx = Context()
ctx.matches = r"""
app: vscode
mode: user.python
mode: command
and code.language: python
"""
# short name -> ide clip name
ctx.lists["user.snippets"] = {
"class funky": "def(class method)",
"class static funky": "def(class static method)",
"class": "class",
"else if": "elif",
"for": "for",
"funky": "def",
"if else": "if/else",
"if": "if",
"lambda": "lambda",
"try except": "try/except",
"while": "while",
"with": "with",
}
# def update_list(watch_list):
# ctx.lists["user.snippets"] = watch_list
# # there's probably a way to do this without
# snippet_path = None
# if app.platform == "windows":
# snippet_path = os.path.expandvars(r"%AppData%\Code\User\snippets")
# elif app.platform == "mac":
# snippet_path = os.path.expanduser(
# "~/Library/Application Support/Code/User/snippets"
# )
# if snippet_path:
# watcher = snippet_watcher({snippet_path: ["python.json",],}, update_list,)

View file

@ -0,0 +1,223 @@
from talon import Context, actions, ui, Module, app, clip
is_mac = app.platform == "mac"
ctx = Context()
mod = Module()
mod.apps.vscode = """
os: mac
and app.bundle: com.microsoft.VSCode
"""
mod.apps.vscode = """
os: linux
and app.name: Code
os: linux
and app.name: code-oss
"""
mod.apps.vscode = """
os: windows
and app.name: Visual Studio Code
os: windows
and app.exe: Code.exe
"""
ctx.matches = r"""
app: vscode
"""
@ctx.action_class("win")
class win_actions:
def filename():
title = actions.win.title()
# this doesn't seem to be necessary on VSCode for Mac
# if title == "":
# title = ui.active_window().doc
if is_mac:
result = title.split("")[0]
else:
result = title.split(" - ")[0]
if "." in result:
return result
return ""
@ctx.action_class("edit")
class edit_actions:
def find(text: str):
if is_mac:
actions.key("cmd-f")
else:
actions.key("ctrl-f")
actions.insert(text)
def line_swap_up():
actions.key("alt-up")
def line_swap_down():
actions.key("alt-down")
def line_clone():
actions.key("shift-alt-down")
def jump_line(n: int):
actions.user.vscode("workbench.action.gotoLine")
actions.insert(str(n))
actions.key("enter")
actions.edit.line_start()
@mod.action_class
class Actions:
def vscode_terminal(number: int):
"""Activate a terminal by number"""
actions.user.vscode(f"workbench.action.terminal.focusAtIndex{number}")
@ctx.action_class("user")
class user_actions:
# snippet.py support beginHelp close
def snippet_search(text: str):
actions.user.vscode("editor.action.insertSnippet")
actions.insert(text)
def snippet_insert(text: str):
"""Inserts a snippet"""
actions.user.vscode("editor.action.insertSnippet")
actions.insert(text)
actions.key("enter")
def snippet_create():
"""Triggers snippet creation"""
actions.user.vscode("workbench.action.openSnippets")
# snippet.py support end
def tab_jump(number: int):
if number < 10:
if is_mac:
actions.key("ctrl-{}".format(number))
else:
actions.key("alt-{}".format(number))
def tab_final():
if is_mac:
actions.key("ctrl-0")
else:
actions.key("alt-0")
# splits.py support begin
def split_number(index: int):
"""Navigates to a the specified split"""
if index < 9:
if is_mac:
actions.key("cmd-{}".format(index))
else:
actions.key("ctrl-{}".format(index))
# splits.py support end
# find_and_replace.py support begin
def find(text: str):
"""Triggers find in current editor"""
if is_mac:
actions.key("cmd-f")
else:
actions.key("ctrl-f")
if text:
actions.insert(text)
def find_next():
actions.user.vscode("editor.action.nextMatchFindAction")
def find_previous():
actions.user.vscode("editor.action.previousMatchFindAction")
def find_everywhere(text: str):
"""Triggers find across project"""
if is_mac:
actions.key("cmd-shift-f")
else:
actions.key("ctrl-shift-f")
if text:
actions.insert(text)
def find_toggle_match_by_case():
"""Toggles find match by case sensitivity"""
if is_mac:
actions.key("alt-cmd-c")
else:
actions.key("alt-c")
def find_toggle_match_by_word():
"""Toggles find match by whole words"""
if is_mac:
actions.key("cmd-alt-w")
else:
actions.key("alt-w")
def find_toggle_match_by_regex():
"""Toggles find match by regex"""
if is_mac:
actions.key("cmd-alt-r")
else:
actions.key("alt-r")
def replace(text: str):
"""Search and replaces in the active editor"""
if is_mac:
actions.key("alt-cmd-f")
else:
actions.key("ctrl-h")
if text:
actions.insert(text)
def replace_everywhere(text: str):
"""Search and replaces in the entire project"""
if is_mac:
actions.key("cmd-shift-h")
else:
actions.key("ctrl-shift-h")
if text:
actions.insert(text)
def replace_confirm():
"""Confirm replace at current position"""
if is_mac:
actions.key("shift-cmd-1")
else:
actions.key("ctrl-shift-1")
def replace_confirm_all():
"""Confirm replace all"""
if is_mac:
actions.key("cmd-enter")
else:
actions.key("ctrl-alt-enter")
def select_previous_occurrence(text: str):
actions.edit.find(text)
actions.sleep("100ms")
actions.key("shift-enter esc")
def select_next_occurrence(text: str):
actions.edit.find(text)
actions.sleep("100ms")
actions.key("esc")
def select_next_token():
actions.edit.find("")
actions.key("enter")
actions.key("enter")
actions.key("esc")
# find_and_replace.py support end

View file

@ -0,0 +1,387 @@
#custom vscode commands go here
app: vscode
-
tag(): user.find_and_replace
tag(): user.line_commands
tag(): user.multiple_cursors
tag(): user.snippets
tag(): user.splits
tag(): user.tabs
# TODO remove this once implemented in cursorless
cut line:
key(cmd-x)
action(edit.select_line):
key(ctrl-e cmd-shift-left)
<user.delete> line:
user.vscode_and_wait("editor.action.deleteLines")
action(user.new_line_below):
user.vscode_and_wait("editor.action.insertLineAfter")
action(user.new_line_above):
user.vscode_and_wait("editor.action.insertLineBefore")
settings():
key_wait = 1
#talon app actions
action(app.tab_close): user.vscode("workbench.action.closeActiveEditor")
action(app.tab_next): user.vscode("workbench.action.nextEditorInGroup")
action(app.tab_previous): user.vscode("workbench.action.previousEditorInGroup")
action(app.tab_reopen): user.vscode("workbench.action.reopenClosedEditor")
action(app.window_close): user.vscode("workbench.action.closeWindow")
action(app.window_open): user.vscode("workbench.action.newWindow")
<user.teleport> last: user.vscode("workbench.action.openPreviousRecentlyUsedEditorInGroup")
<user.teleport> next: user.vscode("workbench.action.openNextRecentlyUsedEditorInGroup")
#talon code actions
action(code.toggle_comment): user.vscode("editor.action.commentLine")
#talon edit actions
action(edit.indent_more): user.vscode("editor.action.indentLines")
action(edit.indent_less): user.vscode("editor.action.outdentLines")
action(edit.save_all): user.vscode("workbench.action.files.saveAll")
# splits.py support begin
action(user.split_clear_all):
user.vscode("workbench.action.editorLayoutSingle")
action(user.split_clear):
user.vscode("workbench.action.joinTwoGroups")
action(user.split_flip):
user.vscode("workbench.action.toggleEditorGroupLayout")
action(user.split_last):
user.vscode("workbench.action.focusLeftGroup")
action(user.split_next):
user.vscode_and_wait("workbench.action.focusRightGroup")
action(user.split_window_down):
user.vscode("workbench.action.moveEditorToBelowGroup")
action(user.split_window_horizontally):
user.vscode("workbench.action.splitEditorOrthogonal")
action(user.split_window_left):
user.vscode("workbench.action.moveEditorToLeftGroup")
action(user.split_window_right):
user.vscode("workbench.action.moveEditorToRightGroup")
action(user.split_window_up):
user.vscode("workbench.action.moveEditorToAboveGroup")
action(user.split_window_vertically):
user.vscode("workbench.action.splitEditor")
action(user.split_window):
user.vscode("workbench.action.splitEditor")
cross:
# user.vscode("vscode-neovim.escape")
# sleep(25ms)
user.split_next()
# key(a)
# splits.py support end
#multiple_cursor.py support begin
#note: vscode has no explicit mode for multiple cursors
action(user.multi_cursor_add_above):
user.vscode("editor.action.insertCursorAbove")
action(user.multi_cursor_add_below):
user.vscode("editor.action.insertCursorBelow")
action(user.multi_cursor_add_to_line_ends):
user.vscode("editor.action.insertCursorAtEndOfEachLineSelected")
action(user.multi_cursor_disable): key(escape)
action(user.multi_cursor_enable): skip()
action(user.multi_cursor_select_all_occurrences):
user.vscode("editor.action.selectHighlights")
action(user.multi_cursor_select_fewer_occurrences):
user.vscode("cursorUndo")
action(user.multi_cursor_select_more_occurrences):
user.vscode("editor.action.addSelectionToNextFindMatch")
#multiple_cursor.py support end
please [<user.text>]:
user.vscode("workbench.action.showCommands")
insert(user.text or "")
# Sidebar
bar explore: user.vscode("workbench.view.explorer")
bar extensions: user.vscode("workbench.view.extensions")
bar outline: user.vscode("outline.focus")
bar run: user.vscode("workbench.view.debug")
bar source: user.vscode("workbench.view.scm")
side dog: user.vscode("workbench.action.toggleSidebarVisibility")
search next: user.vscode("search.action.focusNextSearchResult")
search last: user.vscode("search.action.focusPreviousSearchResult")
symbol hunt [<user.text>]:
user.vscode("workbench.action.gotoSymbol")
sleep(50ms)
insert(text or "")
symbol last: user.vscode("gotoNextPreviousMember.previousMember")
symbol next: user.vscode("gotoNextPreviousMember.nextMember")
# <user.teleport> symbol: user.vscode_and_wait("semantic-movement.jumpToContainingSymbol")
# <user.teleport> funk: user.vscode_and_wait("semantic-movement.jumpToContainingFunction")
# <user.teleport> named funk: user.vscode_and_wait("semantic-movement.jumpToContainingNamedFunction")
# <user.teleport> class: user.vscode_and_wait("semantic-movement.jumpToContainingClass")
# <user.select> symbol: user.vscode_and_wait("semantic-movement.selectContainingSymbol")
# <user.select> funk: user.vscode_and_wait("semantic-movement.selectContainingFunction")
# <user.select> named funk: user.vscode_and_wait("semantic-movement.selectContainingNamedFunction")
# <user.select> class: user.vscode_and_wait("semantic-movement.selectContainingClass")
# Panels
panel control: user.vscode("workbench.panel.repl.view.focus")
panel output: user.vscode("workbench.panel.output.focus")
panel problems: user.vscode("workbench.panel.markers.view.focus")
low dog: user.vscode("workbench.action.togglePanel")
panel terminal: user.vscode("workbench.panel.terminal.focus")
pan edit: user.vscode("workbench.action.focusActiveEditorGroup")
# Settings
show settings: user.vscode("workbench.action.openGlobalSettings")
show shortcuts: user.vscode("workbench.action.openGlobalKeybindings")
show snippets: user.vscode("workbench.action.openSnippets")
# Display
centered switch: user.vscode("workbench.action.toggleCenteredLayout")
fullscreen switch: user.vscode("workbench.action.toggleFullScreen")
theme switch: user.vscode("workbench.action.selectTheme")
wrap switch: user.vscode("editor.action.toggleWordWrap")
zen switch: user.vscode("workbench.action.toggleZenMode")
# File Commands
<user.find> dock [<user.text>] [{user.file_extension}]:
user.vscode("workbench.action.quickOpen")
sleep(50ms)
insert(text or "")
insert(file_extension or "")
sleep(300ms)
<user.teleport> dock [<user.text>] [{user.file_extension}]:
user.vscode("workbench.action.quickOpen")
sleep(50ms)
insert(text or "")
insert(file_extension or "")
sleep(300ms)
key(enter)
file copy path:
user.vscode("copyFilePath")
file create sibling <user.format_text>* [<user.word>] [{user.file_extension}]:
user.vscode_and_wait("explorer.newFile")
sleep(500ms)
user.insert_many(format_text_list or "")
user.insert_formatted(user.word or "", "NOOP")
insert(file_extension or "")
file create: user.vscode("workbench.action.files.newUntitledFile")
file rename:
user.vscode("fileutils.renameFile")
sleep(150ms)
file move:
user.vscode("fileutils.moveFile")
sleep(150ms)
file open folder:
user.vscode("revealFileInOS")
file reveal: user.vscode("workbench.files.action.showActiveFileInExplorer")
save ugly:
user.vscode("workbench.action.files.saveWithoutFormatting")
file clone:
user.vscode("fileutils.duplicateFile")
sleep(150ms)
action(edit.save):
key(cmd-s)
sleep(50ms)
# Language Features
suggest show: user.vscode("editor.action.triggerSuggest")
hint show: user.vscode("editor.action.triggerParameterHints")
def show: user.vscode("editor.action.revealDefinition")
definition peek: user.vscode("editor.action.peekDefinition")
definition side: user.vscode("editor.action.revealDefinitionAside")
references show: user.vscode("editor.action.goToReferences")
ref show: user.vscode("references-view.find")
format that: user.vscode("editor.action.formatDocument")
format selection: user.vscode("editor.action.formatSelection")
imports fix: user.vscode("editor.action.organizeImports")
problem next: user.vscode("editor.action.marker.nextInFiles")
problem last: user.vscode("editor.action.marker.prevInFiles")
problem fix: user.vscode("problems.action.showQuickFixes")
rename that: user.vscode("editor.action.rename")
refactor that: user.vscode("editor.action.refactor")
whitespace trim: user.vscode("editor.action.trimTrailingWhitespace")
language switch: user.vscode("workbench.action.editor.changeLanguageMode")
refactor rename: user.vscode("editor.action.rename")
refactor this: user.vscode("editor.action.refactor")
ref next:
user.vscode("references-view.tree.focus")
key(down enter)
ref last:
user.vscode("references-view.tree.focus")
key(up enter)
#code navigation
(<user.teleport> declaration | follow):
user.vscode("editor.action.revealDefinition")
spring back:
user.vscode("workbench.action.navigateBack")
spring forward: user.vscode("workbench.action.navigateForward")
<user.teleport> implementation:
user.vscode("editor.action.goToImplementation")
<user.teleport> type:
user.vscode("editor.action.goToTypeDefinition")
<user.teleport> usage:
user.vscode("references-view.find")
# Bookmarks. Requires Bookmarks plugin
<user.find> sesh [<user.text>]:
user.vscode("workbench.action.openRecent")
sleep(50ms)
insert(text or "")
sleep(250ms)
<user.teleport> sesh [<user.text>]:
user.vscode("workbench.action.openRecent")
sleep(50ms)
insert(text or "")
key(enter)
sleep(250ms)
<user.teleport> marks: user.vscode("workbench.view.extension.bookmarks")
toggle mark: user.vscode("bookmarks.toggle")
<user.teleport> next mark: user.vscode("bookmarks.jumpToNext")
<user.teleport> last mark: user.vscode("bookmarks.jumpToPrevious")
# Folding
fold that: user.vscode("editor.fold")
unfold that: user.vscode("editor.unfold")
fold those: user.vscode("editor.foldAllMarkerRegions")
unfold those: user.vscode("editor.unfoldRecursively")
fold all: user.vscode("editor.foldAll")
unfold all: user.vscode("editor.unfoldAll")
fold comments: user.vscode("editor.foldAllBlockComments")
# Git / Github (not using verb-noun-adjective pattern, mirroring terminal commands.)
git branch: user.vscode("git.branchFrom")
git branch this: user.vscode("git.branch")
git checkout [<user.text>]:
user.vscode("git.checkout")
sleep(50ms)
insert(text or "")
git commit [<user.text>]:
user.vscode("git.commitStaged")
sleep(100ms)
user.insert_formatted(text or "", "CAPITALIZE_FIRST_WORD")
git commit undo: user.vscode("git.undoCommit")
git commit ammend: user.vscode("git.commitStagedAmend")
git diff: user.vscode("git.openChange")
git ignore: user.vscode("git.ignore")
git merge: user.vscode("git.merge")
git output: user.vscode("git.showOutput")
git pull: user.vscode("git.pullRebase")
git push: user.vscode("git.push")
git push focus: user.vscode("git.pushForce")
git rebase abort: user.vscode("git.rebaseAbort")
git reveal: user.vscode("git.revealInExplorer")
git revert: user.vscode("git.revertChange")
git stash: user.vscode("git.stash")
git stash pop: user.vscode("git.stashPop")
git status: user.vscode("workbench.scm.focus")
git stage: user.vscode("git.stage")
git stage all: user.vscode("git.stageAll")
git unstage: user.vscode("git.unstage")
git unstage all: user.vscode("git.unstageAll")
pull request: user.vscode("pr.create")
change next: key(alt-f5)
change last: key(shift-alt-f5)
#Debugging
break point: user.vscode("editor.debug.action.toggleBreakpoint")
step over: user.vscode("workbench.action.debug.stepOver")
debug step into: user.vscode("workbench.action.debug.stepInto")
debug step out [of]: user.vscode("workbench.action.debug.stepOut")
debug start: user.vscode("workbench.action.debug.start")
debug pause: user.vscode("workbench.action.debug.pause")
debug stopper: user.vscode("workbench.action.debug.stop")
debug continue: user.vscode("workbench.action.debug.continue")
debug restart: user.vscode("workbench.action.debug.restart")
debug console: user.vscode("workbench.debug.action.toggleRepl")
# Terminal
term external: user.vscode("workbench.action.terminal.openNativeConsole")
term new: user.vscode("workbench.action.terminal.new")
term next: user.vscode("workbench.action.terminal.focusNext")
term last:user.vscode("workbench.action.terminal.focusPrevious")
term split: user.vscode("workbench.action.terminal.split")
term zoom: user.vscode("workbench.action.toggleMaximizedPanel")
term trash: user.vscode("workbench.action.terminal.kill")
term dog: user.vscode_and_wait("workbench.action.terminal.toggleTerminal")
term scroll up: user.vscode("workbench.action.terminal.scrollUp")
term scroll down: user.vscode("workbench.action.terminal.scrollDown")
term <number_small>: user.vscode_terminal(number_small)
#TODO: should this be added to linecommands?
copy line down: user.vscode("editor.action.copyLinesDownAction")
copy line up: user.vscode("editor.action.copyLinesUpAction")
#Expand/Shrink AST Selection
<user.select> less: user.vscode("editor.action.smartSelect.shrink")
<user.select> (more|this): user.vscode("editor.action.smartSelect.expand")
minimap: user.vscode("editor.action.toggleMinimap")
maximize: user.vscode("workbench.action.minimizeOtherEditors")
restore: user.vscode("workbench.action.evenEditorWidths")
replace here:
user.replace("")
key(cmd-alt-l)
hover show: user.vscode("editor.action.showHover")
edit last: user.vscode("editsHistory.moveCursorToPreviousEdit")
edit next: user.vscode("editsHistory.moveCursorToNextEdit")
edit add: user.vscode("editsHistory.createEditAtCursor")
edit last here: user.vscode("editsHistory.moveCursorToPreviousEditInSameFile")
edit next here: user.vscode("editsHistory.moveCursorToNextEditInSameFile")
join lines: user.vscode("editor.action.joinLines")
commode:
user.vscode("vscode-neovim.escape")
sleep(25ms)
insert:
key(i)
sleep(25ms)
replace smart:
key(:)
sleep(50ms)
key(S)
key(/)
swap this: user.vscode("extension.swap")
full screen: user.vscode("workbench.action.toggleFullScreen")
reload window: user.vscode("workbench.action.reloadWindow")
close window: user.vscode("workbench.action.closeWindow")
curse undo: user.vscode("cursorUndo")
<user.select> word: user.vscode("editor.action.addSelectionToNextFindMatch")
skip word: user.vscode("editor.action.moveSelectionToNextFindMatch")
Github open: user.vscode("openInGithub.openInGitHubFile")
stage on:
user.vscode_and_wait("git.stage")
key(cmd-w)
user.vscode_and_wait("workbench.scm.focus")
key(down:100)
sleep(100ms)
key(enter)
# jupyter
cell next: user.vscode("jupyter.gotoNextCellInFile")
cell last: user.vscode("jupyter.gotoPrevCellInFile")
cell run above: user.vscode("jupyter.runallcellsabove.palette")
cell run: user.vscode("jupyter.runcurrentcell")
jest: key(ctrl-space)
yes:
sleep(100ms)
key(tab)
install local: user.vscode("workbench.extensions.action.installVSIX")

View file

@ -0,0 +1,57 @@
# https://help.github.com/en/github/getting-started-with-github/keyboard-shortcuts
tag: browser
win.title: /github.com/
-
# site wide shortcuts
focus search: key(s)
go to notifications: insert("gn")
go to dashboard: insert("gd")
show keyboard shortcuts: key(?)
move selection down: key(j)
move selection up: key(k)
toggle selection: key(x)
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")
# network graph
# source code browsing
find file: key(t)
jump to line: key(l)
switch (branch|tag): key(w)
expand url: key(y)
(show|hide) [all] in line notes: key(i)
# issues
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)
submit comment: key(ctrl-enter)
preview comment: key(ctrl-shift-p)
#go fullscreen: key(ctrl-shift-l)
git hub full screen: key(ctrl-shift-l)
# browsing commit
#submit comment: key(ctrl-enter)
close form: key(escape)
parent commit: key(p)
other parent commit: key(o)
# commit list
#expand url: key(y)
# notifications
mark as read: key(y)
mute thread: key(shift-m)
# pull request list
open issue: key(o)

View file

@ -1,7 +1,8 @@
# Shortcuts taken from: https://docs.gitlab.com/ee/user/shortcuts.html
#
tag: browser
browser.host: /gitlab\.com/
win.title: /gitlab.com/
#win.title: /GitLab/
-
@ -16,7 +17,7 @@ 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)
(show|hide) performance bar: key(p)
edit last comment: key(1)
toggle mark down [preview]: key(ctrl-shift-p)
@ -27,9 +28,9 @@ 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 (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")

View file

@ -0,0 +1,12 @@
tag: browser
win.title: /gmail.com/
-
show inbox: key(escape i g i escape)
email sign off:
edit.line_end()
key(enter:2)
insert("Best,")
key(enter)
insert("Pokey")
forward this: key(escape i f)

View file

@ -1,6 +1,7 @@
# https://support.office.com/en-us/article/keyboard-shortcuts-for-outlook-3cdeb221-7ae5-4c1d-8c1d-9e63216c1efd#PickTab=Web
# the shortcuts below our based half of the bill in short cut menu, but the
# link above has significantly more that could so be added
os: linux
tag: browser
win.title: /Outlook/
@ -17,7 +18,7 @@ discard [draft]: key(esc)
insert [a] [hyper] link: key(ctrl-k)
# email list
(select | unselect) [this] message: key(ctrl-space)
(select|unselect) [this] message: key(ctrl-space)
select all [messages]: key(ctrl-a)
clear all [messages]: key(esc)
select first [message]: key(home)
@ -27,11 +28,11 @@ select last [message]: key(and)
open [this] message: key(o)
open [this] message [in] [a] new window: key(shift-enter)
close [this] message: key(esc)
[open] [the] next (item | message): key(ctrl-.)
[open] [the] (prev | previous) item: key(ctrl-,)
next reading [pane] (item | message): key(.)
(prev | previous) [pane] (item | message): key(,)
(expand | collapse) [conversation]: key(x)
[open] [the] next (item|message): key(ctrl-.)
[open] [the] (prev|previous) item: key(ctrl-,)
next reading [pane] (item|message): key(.)
(prev|previous) [pane] (item|message): key(,)
(expand|collapse) [conversation]: key(x)
# go to
go [to] mail: key(ctrl-shift-1)
@ -53,11 +54,11 @@ show help: key(?)
# email actions
undo [last] [action]: key(ctrl-z)
delete [this] [message]: key(delete)
(perm | permanently) delete [this] [message]: key(shift+delete)
(perm|permanently) delete [this] [message]: key(shift+delete)
new folder: key(shift-e)
mark [this] [(item | message)] as read: key(q)
mark [this] [(item | message)] as unread: key(u)
flag [this] [(item | message)]: key(insert)
mark [this] [(item|message)] as read: key(q)
mark [this] [(item|message)] as unread: key(u)
flag [this] [(item|message)]: key(insert)
archive: key(e)
mark [this] [message] [as] junk: key(j)
moved to [a] folder: key(v)

View file

@ -16,35 +16,35 @@ save message: key(ctrl-s)
# Mail
## Jumping
(go | jump) [to] inbox:
(go|jump) [to] inbox:
key(g)
key(i)
(go | jump) [to] draft:
(go|jump) [to] draft:
key(g)
key(d)
(go | jump) [to] sent:
(go|jump) [to] sent:
key(g)
key(s)
(go | jump) [to] starred:
(go|jump) [to] starred:
key(g)
key(.)
(go | jump) [to] archive:
(go|jump) [to] archive:
key(g)
key(a)
(go | jump) [to] spam:
(go|jump) [to] spam:
key(g)
key(x)
(go | jump) [to] trash:
(go|jump) [to] trash:
key(g)
key(t)
## Navigation
(prev | previous) message: key(up)
(prev|previous) message: key(up)
next message: key(down)
exit message: key(left)
enter message: key(right)
(show | display) newer [message]: key(k)
(show | display) older [message]: key(j)
(show|display) newer [message]: key(k)
(show|display) older [message]: key(j)
open message: key(enter)
go back: key(escape)
@ -52,26 +52,26 @@ go back: key(escape)
select all:
key(*)
key(a)
(deselect | unselect) all:
(deselect|unselect) all:
key(*)
key(n)
select [the] (message | conversation): key(x)
select [the] (message|conversation): key(x)
mark [as] read: key(r)
mark [as] unread: key(u)
star (message | conversation): key(.)
star (message|conversation): key(.)
move to inbox: key(i)
move to trash: key(t)
move to archive: key(a)
move to spam: key(s)
## Actions
reply to (message | conversation): key(shift-r)
reply all [to] (message | conversation): key(shift-a)
forward (message | conversation): key(shift-f)
reply to (message|conversation): key(shift-r)
reply all [to] (message|conversation): key(shift-a)
forward (message|conversation): key(shift-f)
# Contacts
## Contact List
(prev | previous) contact: key(up)
(prev|previous) contact: key(up)
next contact: key(down)
enter contact: key(right)
delete contact: key(t)

Some files were not shown because too many files have changed in this diff Show more