1
0
mirror of https://github.com/chylex/IntelliJ-AceJump.git synced 2024-11-25 17:42:46 +01:00

Compare commits

..

No commits in common. "d905909e31c40d7ededd9f1a422c6592641d2a8c" and "35003b0babc292f39f8fe90cd5b292681ce88bc8" have entirely different histories.

34 changed files with 332 additions and 475 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,3 @@
# These are supported funding model platforms
github: breandan

View File

@ -2,63 +2,14 @@
## Unreleased ## Unreleased
## 3.8.16
- Fix issue with unselectable tags, [#446](https://github.com/acejump/AceJump/issues/446)
## 3.8.15
- Forbid jumping to offscreen tags, [#442](https://github.com/acejump/AceJump/issues/442)
## 3.8.14
- Fixes NoSuchFieldError: Companion on older platform versions, [#432](https://github.com/acejump/AceJump/issues/432), [#434](https://github.com/acejump/AceJump/issues/434), [#435](https://github.com/acejump/AceJump/issues/432), [#437](https://github.com/acejump/AceJump/issues/437), [#438](https://github.com/acejump/AceJump/issues/438), thanks to [@wuruofan](https://github.com/wuruofan)
## 3.8.13
- Fixes color settings not being persisted, [#431](https://github.com/acejump/AceJump/issues/431)
## 3.8.12
- Fixes tag cycling issue with Enter/Shift+Enter, [#429](https://github.com/acejump/AceJump/issues/429)
## 3.8.11
- Fixes UI issue affecting mode cycling order, [#426](https://github.com/acejump/AceJump/issues/426)
## 3.8.10
- Fixes regression in 3.8.9 breaking cross-tab selection, [#417](https://github.com/acejump/AceJump/issues/417)
## 3.8.9
- Add ids to editor action handlers, [#410](https://github.com/acejump/AceJump/pull/410), thanks to [@AlexPl292](https://github.com/AlexPl292)
- Update API to IJ-2022.3 and JDK to 17
## 3.8.8
- Add AZERTY keyboard layout, [#398](https://github.com/acejump/AceJump/pull/398), thanks to [@delphinaubin](https://github.com/delphinaubin)
- Add bounded toggle mode to start jump mode before or after the caret, [#401](https://github.com/acejump/AceJump/pull/401), thanks to [@colossatr0n](https://github.com/colossatr0n)
- Remove only the highlighters added by AceJump when jump session ends, [#407](https://github.com/acejump/AceJump/pull/407), thanks to [@huoguangjin](https://github.com/huoguangjin)
## 3.8.7
- Fixes Unicode-ASCII regression, [#399](https://github.com/acejump/AceJump/issues/399)
## 3.8.6
- Adds AZERTY keyboard layout, [#398](https://github.com/acejump/AceJump/pull/398), thanks to [@delphinaubin](https://github.com/delphinaubin)
## 3.8.5 ## 3.8.5
- Improves tag order for non-QWERTY layouts, [#385](https://github.com/acejump/AceJump/issues/385)
- Restores <kbd>Tab</kbd>/<kbd>Shift</kbd>+<kbd>Tab</kbd> functionality, [#356](https://github.com/acejump/AceJump/issues/356) - Restores <kbd>Tab</kbd>/<kbd>Shift</kbd>+<kbd>Tab</kbd> functionality, [#356](https://github.com/acejump/AceJump/issues/356)
- Fixes tag cycling with <kbd>Enter</kbd>/<kbd>Shift</kbd>+<kbd>Enter</kbd>, [#380](https://github.com/acejump/AceJump/issues/380), thanks [@AlexPl292](https://github.com/AlexPl292)
## 3.8.4 ## 3.8.4
- Fixes Declaration Mode in Rider, [#379](https://github.com/acejump/AceJump/issues/379), thanks to [@igor-akhmetov](https://github.com/igor-akhmetov) for helping diagnose! - Fixes Declaration Mode in Rider, [#379](https://github.com/acejump/AceJump/issues/379), thanks to @igor-akhmetov for helping diagnose!
- Fixes highlight offset on high-DPI screens, [#362](https://github.com/acejump/AceJump/issues/362), thanks to [@chylex](https://github.com/chylex) for [the PR](https://github.com/acejump/AceJump/pull/384)! - Fixes highlight offset on high-DPI screens, [#362](https://github.com/acejump/AceJump/issues/362), thanks to @chylex for [the PR](https://github.com/acejump/AceJump/pull/384)!
## 3.8.3 ## 3.8.3
@ -69,7 +20,7 @@
- Add option to display current search text, [#375](https://github.com/acejump/AceJump/issues/375) - Add option to display current search text, [#375](https://github.com/acejump/AceJump/issues/375)
- Fixes a bug where editor was not focused, [#374](https://github.com/acejump/AceJump/issues/374) - Fixes a bug where editor was not focused, [#374](https://github.com/acejump/AceJump/issues/374)
- Thanks to [@SaiKai](https://github.com/SaiKai) for the PRs! - Thanks to @SaiKai for the PRs!
## 3.8.1 ## 3.8.1
@ -84,7 +35,7 @@
- Update AceJump extension API to include tag information, [#357](https://github.com/acejump/AceJump/pull/357) - Update AceJump extension API to include tag information, [#357](https://github.com/acejump/AceJump/pull/357)
- Allow defining jump mode with boundaries, [#358](https://github.com/acejump/AceJump/pull/358) - Allow defining jump mode with boundaries, [#358](https://github.com/acejump/AceJump/pull/358)
- Use Kotlin classes for actions, [#359](https://github.com/acejump/AceJump/pull/359) - Use Kotlin classes for actions, [#359](https://github.com/acejump/AceJump/pull/359)
- Thanks to [@AlexPl292](https://github.com/AlexPl292) for the PRs! - Thanks to @AlexPl292 for the PRs!
## 3.7.0 ## 3.7.0
- Improvements to tag latency - Improvements to tag latency
@ -98,7 +49,7 @@
- Increase limit for what is considered a large file - Increase limit for what is considered a large file
- Major refactoring, [#350](https://github.com/acejump/AceJump/pull/353) - Major refactoring, [#350](https://github.com/acejump/AceJump/pull/353)
- [Many bug fixes](https://github.com/acejump/AceJump/issues/348#issuecomment-739454920): [#338](https://github.com/acejump/AceJump/issues/338), [#336](https://github.com/acejump/AceJump/issues/336), [#329](https://github.com/acejump/AceJump/issues/329), [#327](https://github.com/acejump/AceJump/issues/327), [#310](https://github.com/acejump/AceJump/issues/310), [#233](https://github.com/acejump/AceJump/issues/233), [#228](https://github.com/acejump/AceJump/issues/228), [#187](https://github.com/acejump/AceJump/issues/187), [#147](https://github.com/acejump/AceJump/issues/147), [#132](https://github.com/acejump/AceJump/issues/132), [#71](https://github.com/acejump/AceJump/issues/71) - [Many bug fixes](https://github.com/acejump/AceJump/issues/348#issuecomment-739454920): [#338](https://github.com/acejump/AceJump/issues/338), [#336](https://github.com/acejump/AceJump/issues/336), [#329](https://github.com/acejump/AceJump/issues/329), [#327](https://github.com/acejump/AceJump/issues/327), [#310](https://github.com/acejump/AceJump/issues/310), [#233](https://github.com/acejump/AceJump/issues/233), [#228](https://github.com/acejump/AceJump/issues/228), [#187](https://github.com/acejump/AceJump/issues/187), [#147](https://github.com/acejump/AceJump/issues/147), [#132](https://github.com/acejump/AceJump/issues/132), [#71](https://github.com/acejump/AceJump/issues/71)
- Huge thanks to [@chylex](https://github.com/chylex) for [all the PRs](https://github.com/acejump/AceJump/pulls?q=is%3Apr+author%3Achylex)! - Huge thanks to @chylex for [all the PRs](https://github.com/acejump/AceJump/pulls?q=is%3Apr+author%3Achylex)!
## 3.6.3 ## 3.6.3
@ -108,12 +59,12 @@
## 3.6.2 ## 3.6.2
- Fixes [#226](https://github.com/acejump/AceJump/issues/226). Thanks [@AlexPl292](https://github.com/AlexPl292)! - Fixes [#226](https://github.com/acejump/AceJump/issues/226). Thanks @AlexPl292!
- Update Pinyin engine. - Update Pinyin engine.
## 3.6.1 ## 3.6.1
- Fixes [#324](https://github.com/acejump/AceJump/issues/324). Thanks [@AlexPl292](https://github.com/AlexPl292)! - Fixes [#324](https://github.com/acejump/AceJump/issues/324). Thanks @AlexPl292!
- Fixes [#325](https://github.com/acejump/AceJump/issues/325). - Fixes [#325](https://github.com/acejump/AceJump/issues/325).
- Fixes Pinyin support. - Fixes Pinyin support.
@ -121,7 +72,7 @@
- Adds support for Chinese [#314](https://github.com/acejump/AceJump/issues/314). - Adds support for Chinese [#314](https://github.com/acejump/AceJump/issues/314).
- Fixes constantly loading settings page [#303](https://github.com/acejump/AceJump/issues/303). - Fixes constantly loading settings page [#303](https://github.com/acejump/AceJump/issues/303).
- Honor camel humps [#315](https://github.com/acejump/AceJump/issues/315). Thanks to [@clojj](https://github.com/clojj). - Honor camel humps [#315](https://github.com/acejump/AceJump/issues/315). Thanks to @clojj.
- Support dynamic application reloading [#322](https://github.com/acejump/AceJump/issues/322). - Support dynamic application reloading [#322](https://github.com/acejump/AceJump/issues/322).
## 3.5.9 ## 3.5.9

View File

@ -1,20 +1,13 @@
<p align="center"><a href="https://plugins.jetbrains.com/plugin/7086"> <img src="logo.png" alt="AceJumpLogo"></a></p> <p align="center"><a href="https://plugins.jetbrains.com/plugin/7086"> <img src="logo.png" alt="AceJumpLogo"></a></p>
<p align="center"> <p align="center">
<a href="https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub" title="JetBrains on GitHub"><img src="https://jb.gg/badges/team.svg"></a> <a href="https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub" title="JetBrains on GitHub"><img src="http://jb.gg/badges/team.svg"></a>
<a href="https://teamcity.jetbrains.com/viewType.html?buildTypeId=acejump_buildplugin&guest=1" title="Build Plugin"><img src="https://teamcity.jetbrains.com/app/rest/builds/buildType:acejump_buildplugin/statusIcon.svg"></a> <a href="https://teamcity.jetbrains.com/viewType.html?buildTypeId=acejump_buildplugin&guest=1" title="Build Plugin"><img src="https://teamcity.jetbrains.com/app/rest/builds/buildType:acejump_buildplugin/statusIcon.svg"></a>
<a href="https://plugins.jetbrains.com/plugin/7086-acejump" title="Jetbrains Plugin"><img src="https://img.shields.io/jetbrains/plugin/v/7086-acejump.svg"></a> <a href="https://plugins.jetbrains.com/plugin/7086-acejump" title="Jetbrains Plugin"><img src="https://img.shields.io/jetbrains/plugin/v/7086-acejump.svg"></a>
<a href="LICENSE" title="License"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a> <a href="LICENSE" title="License"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
<a href="https://twitter.com/search?q=AceJump&f=live" title="Twitter"><img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social"></a> <a href="https://twitter.com/search?q=AceJump&f=live" title="Twitter"><img src="https://img.shields.io/twitter/url/http/shields.io.svg?style=social"></a>
</p> </p>
> **Note**: There is currently an outstanding issue with [settings deserialization](https://github.com/acejump/AceJump/issues/445). If the AceJump settings were changed in the past, they can become corrupted and may need to be manually deleted. The location varies depending on the operating system and platform version used. For IntelliJ IDEA, the plugin settings file is located in either `options` or `plugins` in the following directories:
> * Mac: `~/Library/Application Support/JetBrains/IntelliJIdea<VERSION>`
> * Windows: `%APPDATA%\JetBrains\IntelliJIdea<VERSION>`
> * Linux: `~/.local/share/JetBrains/IntelliJIdea<VERSION>`
>
> If not found, you can locate this file via the command, `find . | grep AceJump.xml` under the `JetBrains` directory. We apologize for any inconvenience this may have caused.
[AceJump](https://plugins.jetbrains.com/plugin/7086) is a plugin for the [IntelliJ Platform](https://github.com/JetBrains/intellij-community/) that lets you jump to any symbol in the editor with just a few keystrokes. Press the keyboard shortcut for `AceAction` (<kbd>Ctrl</kbd>+<kbd>;</kbd> by default) to activate AceJump. Type any string in the editor, followed by one of the illustrated tags, to jump its position: [AceJump](https://plugins.jetbrains.com/plugin/7086) is a plugin for the [IntelliJ Platform](https://github.com/JetBrains/intellij-community/) that lets you jump to any symbol in the editor with just a few keystrokes. Press the keyboard shortcut for `AceAction` (<kbd>Ctrl</kbd>+<kbd>;</kbd> by default) to activate AceJump. Type any string in the editor, followed by one of the illustrated tags, to jump its position:
![](https://cloud.githubusercontent.com/assets/175716/20177444/124fb534-a74d-11e6-8912-1d220ae27091.png) ![](https://cloud.githubusercontent.com/assets/175716/20177444/124fb534-a74d-11e6-8912-1d220ae27091.png)
@ -35,7 +28,7 @@ AceJump search is [smart case](http://ideavim.sourceforge.net/vim/usr_27.html#vi
## Tips ## Tips
- Press <kbd>Tab</kbd> when searching to jump to the next group of matches in the editor. - Press <kbd>Tab</kbd> when searching to jump to the next group of matches in the editor. *This feature is unavailable in `3.6.4-3.8.4`.*
- If you make a mistake searching, just press <kbd>Backspace</kbd> to restart from scratch. - If you make a mistake searching, just press <kbd>Backspace</kbd> to restart from scratch.
@ -61,6 +54,8 @@ AceJump search is [smart case](http://ideavim.sourceforge.net/vim/usr_27.html#vi
AceJump can be [installed directly from the IDE](https://www.jetbrains.com/help/idea/managing-plugins.html#install), via **Settings | Plugins | Browse Repositories... | 🔍 "AceJump"**. AceJump can be [installed directly from the IDE](https://www.jetbrains.com/help/idea/managing-plugins.html#install), via **Settings | Plugins | Browse Repositories... | 🔍 "AceJump"**.
[Canary builds](https://teamcity.jetbrains.com/repository/download/acejump_buildplugin/.lastSuccessful/AceJump.zip?guest=1) are provided courtesy of [TeamCity](https://www.jetbrains.com/teamcity/). These can be downloaded and [installed from disk](https://www.jetbrains.com/help/idea/managing-plugins.html#install_plugin_from_disk).
## Configuring ## Configuring
[IdeaVim](https://plugins.jetbrains.com/plugin/164) users can choose to activate AceJump with a single keystroke (<kbd>f</kbd>, <kbd>F</kbd> and <kbd>g</kbd> are arbitrary) by running: [IdeaVim](https://plugins.jetbrains.com/plugin/164) users can choose to activate AceJump with a single keystroke (<kbd>f</kbd>, <kbd>F</kbd> and <kbd>g</kbd> are arbitrary) by running:
@ -69,25 +64,15 @@ AceJump can be [installed directly from the IDE](https://www.jetbrains.com/help/
echo -e ' echo -e '
" Press `f` to activate AceJump " Press `f` to activate AceJump
map f <Action>(AceAction) map f :action AceAction<CR>
" Press `F` to activate Target Mode " Press `F` to activate Target Mode
map F <Action>(AceTargetAction) map F :action AceTargetAction<CR>
" Press `g` to activate Line Mode " Press `g` to activate Line Mode
map g <Action>(AceLineAction) map g :action AceLineAction<CR>
' >> ~/.ideavimrc ' >> ~/.ideavimrc
``` ```
To customize AceJump's behavior further with additional actions, see the `<action>` tags in [plugin.xml](src/main/resources/META-INF/plugin.xml). The following example shows how to activate AceJump before or after the caret.
```
" Press `S` in normal mode to activate AceJump mode before the caret
nmap S <Action>(AceBackwardAction)
" Press `s` in normal mode to activate AceJump mode after the caret
nmap s <Action>(AceForwardAction)
```
To change the default keyboard shortcuts, open **File \| Settings \| Keymap \| 🔍 "AceJump" \| AceJump \|** <kbd>Enter⏎</kbd>. To change the default keyboard shortcuts, open **File \| Settings \| Keymap \| 🔍 "AceJump" \| AceJump \|** <kbd>Enter⏎</kbd>.
![Keymap](https://cloud.githubusercontent.com/assets/175716/11760350/911aed4c-a065-11e5-8f17-49bc97ad1dad.png) ![Keymap](https://cloud.githubusercontent.com/assets/175716/11760350/911aed4c-a065-11e5-8f17-49bc97ad1dad.png)
@ -186,37 +171,31 @@ The following plugins have a similar UI for navigating text and web browsing:
|:----------------------------------------------------------------------|:-------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------:|:-------------------:|:------------------------------------------------------------------------:| |:----------------------------------------------------------------------|:-------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------:|:-------------------:|:------------------------------------------------------------------------:|
| AceJump | [](https://plugins.jetbrains.com/plugin/7086-acejump) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Kotlin](http://kotlinlang.org/) | | AceJump | [](https://plugins.jetbrains.com/plugin/7086-acejump) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Kotlin](http://kotlinlang.org/) |
| [IdeaVim-EasyMotion](https://github.com/AlexPl292/IdeaVim-EasyMotion) | [](https://github.com/AlexPl292/IdeaVim-EasyMotion) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Kotlin](http://kotlinlang.org/) | | [IdeaVim-EasyMotion](https://github.com/AlexPl292/IdeaVim-EasyMotion) | [](https://github.com/AlexPl292/IdeaVim-EasyMotion) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Kotlin](http://kotlinlang.org/) |
| [KJump](https://github.com/a690700752/KJump) | [](https://plugins.jetbrains.com/plugin/10149-kjump) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Kotlin](http://kotlinlang.org/) | | [AceJump-Lite](https://github.com/EeeMt/AceJump-Lite) | [](https://plugins.jetbrains.com/plugin/9803-acejump-lite) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Java](https://www.java.com) |
| [AceJump-Lite](https://github.com/EeeMt/AceJump-Lite) | [](https://plugins.jetbrains.com/plugin/9803-acejump-lite) | [IntelliJ Platform](https://jetbrains.com) | :x: | [Java](https://www.java.com) | | [KJump](https://github.com/a690700752/KJump) | [](https://plugins.jetbrains.com/plugin/10149-kjump) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Java](https://www.java.com) |
| [emacsIDEAs](https://github.com/whunmr/emacsIDEAs) | [](https://plugins.jetbrains.com/plugin/7163-emacsideas) | [IntelliJ Platform](https://jetbrains.com) | :x: | [Java](https://www.java.com) | | [emacsIDEAs](https://github.com/whunmr/emacsIDEAs) | [](https://plugins.jetbrains.com/plugin/7163-emacsideas) | [IntelliJ Platform](https://jetbrains.com) | :heavy_check_mark: | [Java](https://www.java.com) |
| [TraceJump](https://github.com/acejump/tracejump) | [](https://github.com/acejump/tracejump) | Desktop | :heavy_check_mark: | [Kotlin](http://kotlinlang.org/) | | [TraceJump](https://github.com/acejump/tracejump) | [](https://github.com/acejump/tracejump) | Desktop | :heavy_check_mark: | [Kotlin](http://kotlinlang.org/) |
| [ace-jump-mode](https://github.com/winterTTr/ace-jump-mode) | [](https://melpa.org/#/ace-jump-mode) | [emacs](https://www.gnu.org/software/emacs/) | :x: | [Emacs Lisp](https://www.gnu.org/software/emacs/manual/eintr.html) | | [ace-jump-mode](https://github.com/winterTTr/ace-jump-mode) | [](https://melpa.org/#/ace-jump-mode) | [emacs](https://www.gnu.org/software/emacs/) | :x: | [Emacs Lisp](https://www.gnu.org/software/emacs/manual/eintr.html) |
| [avy](https://github.com/abo-abo/avy) | [](https://melpa.org/#/avy) | [emacs](https://www.gnu.org/software/emacs/) | :heavy_check_mark: | [Emacs Lisp](https://www.gnu.org/software/emacs/manual/eintr.html) | | [avy](https://github.com/abo-abo/avy) | [](https://melpa.org/#/avy) | [emacs](https://www.gnu.org/software/emacs/) | :heavy_check_mark: | [Emacs Lisp](https://www.gnu.org/software/emacs/manual/eintr.html) |
| [EasyMotion](https://github.com/easymotion/vim-easymotion) | [](https://vimawesome.com/plugin/easymotion) | [Vim](http://www.vim.org/) | :x: | [Vimscript](http://learnvimscriptthehardway.stevelosh.com/) | | [EasyMotion](https://github.com/easymotion/vim-easymotion) | [](https://vimawesome.com/plugin/easymotion) | [Vim](http://www.vim.org/) | :x: | [Vimscript](http://learnvimscriptthehardway.stevelosh.com/) |
| [Hop](https://github.com/phaazon/hop.nvim) | [](https://github.com/phaazon/hop.nvim#installation) | [NeoVim](https://neovim.io/) | :heavy_check_mark: | [Lua](https://www.lua.org/) | | [Hop](https://github.com/phaazon/hop.nvim) | [](https://github.com/phaazon/hop.nvim#installation) | [NeoVim](https://neovim.io/) | :heavy_check_mark: | [Lua](https://www.lua.org/) |
| [leap.nvim](https://github.com/ggandor/leap.nvim) | [](https://github.com/ggandor/leap.nvim#installation) | [NeoVim](https://neovim.io/) | :heavy_check_mark: | [Fennel](https://fennel-lang.org) |
| [lightspeed.nvim](https://github.com/ggandor/lightspeed.nvim) | [](https://github.com/ggandor/lightspeed.nvim#installation) | [NeoVim](https://neovim.io/) | :x: | [Fennel](https://fennel-lang.org) |
| [Sublime EasyMotion](https://github.com/tednaleid/sublime-EasyMotion) | [](https://packagecontrol.io/packages/EasyMotion) | [Sublime](https://www.sublimetext.com/) | :x: | [Python](https://www.python.org/) | | [Sublime EasyMotion](https://github.com/tednaleid/sublime-EasyMotion) | [](https://packagecontrol.io/packages/EasyMotion) | [Sublime](https://www.sublimetext.com/) | :x: | [Python](https://www.python.org/) |
| [AceJump](https://github.com/ice9js/ace-jump-sublime) | [](https://packagecontrol.io/packages/AceJump) | [Sublime](https://www.sublimetext.com/) | :x: | [Python](https://www.python.org/) | | [AceJump](https://github.com/ice9js/ace-jump-sublime) | [](https://packagecontrol.io/packages/AceJump) | [Sublime](https://www.sublimetext.com/) | :heavy_check_mark: | [Python](https://www.python.org/) |
| [Jumpy](https://github.com/DavidLGoldberg/jumpy) | [](https://atom.io/packages/jumpy) | [Atom](https://atom.io/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) | | [Jumpy](https://github.com/DavidLGoldberg/jumpy) | [](https://atom.io/packages/jumpy) | [Atom](https://atom.io/) | :heavy_check_mark: | [CoffeeScript](http://coffeescript.org/) |
| [Jumpy2](https://github.com/DavidLGoldberg/jumpy2) | [](https://marketplace.visualstudio.com/items?itemName=DavidLGoldberg.jumpy2) | [Visual Studio Code](https://code.visualstudio.com/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) |
| [Find-Jump](https://github.com/msafi/xvsc/tree/master/findJump) | [](https://marketplace.visualstudio.com/items?itemName=mksafi.find-jump) | [Visual Studio Code](https://code.visualstudio.com/) | :x: | [TypeScript](https://www.typescriptlang.org/) | | [Find-Jump](https://github.com/msafi/xvsc/tree/master/findJump) | [](https://marketplace.visualstudio.com/items?itemName=mksafi.find-jump) | [Visual Studio Code](https://code.visualstudio.com/) | :x: | [TypeScript](https://www.typescriptlang.org/) |
| [MetaGo](https://github.com/metaseed/metaGo) | [](https://marketplace.visualstudio.com/items?itemName=metaseed.metago) | [Visual Studio Code](https://code.visualstudio.com/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) | | [MetaGo](https://github.com/metaseed/metaGo) | [](https://marketplace.visualstudio.com/items?itemName=metaseed.metago) | [Visual Studio Code](https://code.visualstudio.com/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) |
| [VSCodeVim](https://github.com/VSCodeVim/Vim) | [](https://marketplace.visualstudio.com/items?itemName=vscodevim.vim) | [Visual Studio Code](https://code.visualstudio.com/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) | | [VSCodeVim](https://github.com/VSCodeVim/Vim) | [](https://marketplace.visualstudio.com/items?itemName=vscodevim.vim) | [Visual Studio Code](https://code.visualstudio.com/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) |
| [CodeAceJumper](https://github.com/lucax88x/CodeAceJumper) | [](https://marketplace.visualstudio.com/items?itemName=lucax88x.codeacejumper) | [Visual Studio Code](https://code.visualstudio.com/) | :x: | [TypeScript](https://www.typescriptlang.org/) | | [CodeAceJumper](https://github.com/lucax88x/CodeAceJumper) | [](https://marketplace.visualstudio.com/items?itemName=lucax88x.codeacejumper) | [Visual Studio Code](https://code.visualstudio.com/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) |
| [AceJump](https://github.com/jsturtevant/ace-jump) | [](https://marketplace.visualstudio.com/items?itemName=jsturtevant.AceJump) | [Visual Studio](https://www.visualstudio.com/) | :x: | [C#](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/) | | [AceJump](https://github.com/jsturtevant/ace-jump) | [](https://marketplace.visualstudio.com/items?itemName=jsturtevant.AceJump) | [Visual Studio](https://www.visualstudio.com/) | :x: | [C#](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/) |
| [EasyMotion](https://github.com/jaredpar/EasyMotion) | [](https://marketplace.visualstudio.com/items?itemName=JaredParMSFT.EasyMotion) | [Visual Studio](https://www.visualstudio.com/) | :x: | [C#](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/) | | [EasyMotion](https://github.com/jaredpar/EasyMotion) | [](https://marketplace.visualstudio.com/items?itemName=JaredParMSFT.EasyMotion) | [Visual Studio](https://www.visualstudio.com/) | :x: | [C#](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/) |
| [tmux-fingers](https://github.com/Morantron/tmux-fingers) | [](https://github.com/Morantron/tmux-fingers#using-tmux-plugin-manager) | [tmux](https://github.com/tmux/tmux) | :heavy_check_mark: | [Bash](https://www.gnu.org/software/bash/) | | [cVim](https://github.com/1995eaton/chromium-vim) | [](https://chrome.google.com/webstore/detail/cvim/ihlenndgcmojhcghmfjfneahoeklbjjh) | [Chrome](https://www.google.com/chrome) | :heavy_check_mark: | [JavaScript](https://www.javascript.com/) |
| [tmux-thumb](https://github.com/Morantron/tmux-fingers) | [](https://github.com/fcsonline/tmux-thumbs#using-tmux-plugin-manager) | [tmux](https://github.com/tmux/tmux) | :heavy_check_mark: | [Rust](https://www.rust-lang.org/) |
| [tmux-jump](https://github.com/schasse/tmux-jump) | [](https://github.com/schasse/tmux-jump#installation-via-tpm) | [tmux](https://github.com/tmux/tmux) | :heavy_check_mark: | [Ruby](https://www.ruby-lang.org) |
| [cVim](https://github.com/1995eaton/chromium-vim) | [](https://chrome.google.com/webstore/detail/cvim/ihlenndgcmojhcghmfjfneahoeklbjjh) | [Chrome](https://www.google.com/chrome) | :x: | [JavaScript](https://www.javascript.com/) |
| [SurfingKeys](https://github.com/brookhong/Surfingkeys) | [](https://chrome.google.com/webstore/detail/surfingkeys/gfbliohnnapiefjpjlpjnehglfpaknnc) | [Chrome](https://www.google.com/chrome) / [Firefox](https://www.mozilla.org/firefox) | :heavy_check_mark: | [JavaScript](https://www.javascript.com/) | | [SurfingKeys](https://github.com/brookhong/Surfingkeys) | [](https://chrome.google.com/webstore/detail/surfingkeys/gfbliohnnapiefjpjlpjnehglfpaknnc) | [Chrome](https://www.google.com/chrome) / [Firefox](https://www.mozilla.org/firefox) | :heavy_check_mark: | [JavaScript](https://www.javascript.com/) |
| [Vimium](https://github.com/philc/vimium) | [](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb) | [Chrome](https://www.google.com/chrome) | :heavy_check_mark: | [CoffeeScript](http://coffeescript.org/) | | [Vimium](https://github.com/philc/vimium) | [](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb) | [Chrome](https://www.google.com/chrome) | :heavy_check_mark: | [CoffeeScript](http://coffeescript.org/) |
| [Vrome](https://github.com/jinzhu/vrome) | [](https://chrome.google.com/webstore/detail/vrome/godjoomfiimiddapohpmfklhgmbfffjj) | [Chrome](https://www.google.com/chrome) | :x: | [CoffeeScript](http://coffeescript.org/) | | [Vrome](https://github.com/jinzhu/vrome) | [](https://chrome.google.com/webstore/detail/vrome/godjoomfiimiddapohpmfklhgmbfffjj) | [Chrome](https://www.google.com/chrome) | :x: | [CoffeeScript](http://coffeescript.org/) |
| [ViChrome](https://github.com/k2nr/ViChrome) | [](https://chrome.google.com/webstore/detail/vichrome/gghkfhpblkcmlkmpcpgaajbbiikbhpdi) | [Chrome](https://www.google.com/chrome) | :x: | [CoffeeScript](http://coffeescript.org/) | | [ViChrome](https://github.com/k2nr/ViChrome) | [](https://chrome.google.com/webstore/detail/vichrome/gghkfhpblkcmlkmpcpgaajbbiikbhpdi) | [Chrome](https://www.google.com/chrome) | :x: | [CoffeeScript](http://coffeescript.org/) |
| [VimFx](https://github.com/akhodakivskiy/VimFx) | [](https://github.com/akhodakivskiy/VimFx/releases) | [Firefox](https://www.mozilla.org/firefox) | :heavy_check_mark: | [CoffeeScript](http://coffeescript.org/) | | [VimFx](https://github.com/akhodakivskiy/VimFx) | [](https://github.com/akhodakivskiy/VimFx/releases) | [Firefox](https://www.mozilla.org/firefox) | :heavy_check_mark: | [CoffeeScript](http://coffeescript.org/) |
| [Vimperator](https://github.com/vimperator/vimperator-labs/) | [](https://github.com/vimperator/vimperator-labs/releases) | [Firefox](https://www.mozilla.org/firefox) | :x: | [JavaScript](https://www.javascript.com/) | | [Vimperator](https://github.com/vimperator/vimperator-labs/) | [](https://github.com/vimperator/vimperator-labs/releases) | [Firefox](https://www.mozilla.org/firefox) | :x: | [JavaScript](https://www.javascript.com/) |
| [Pentadactyl](https://github.com/5digits/dactyl) | [](http://bug.5digits.org/pentadactyl/#sect-download) | [Firefox](https://www.mozilla.org/firefox) | :x: | [JavaScript](https://www.typescriptlang.org/) | | [Pentadactyl](https://github.com/5digits/dactyl) | [](http://bug.5digits.org/pentadactyl/#sect-download) | [Firefox](https://www.mozilla.org/firefox) | :x: | [JavaScript](https://www.javascript.com/) |
| [Vim Vixen](https://github.com/ueokande/vim-vixen) | [](https://addons.mozilla.org/firefox/addon/vim-vixen/) | [Firefox 57+](https://blog.mozilla.org/addons/2017/09/28/webextensions-in-firefox-57/) | :heavy_check_mark: | [JavaScript](https://www.javascript.com/) | | [Vim Vixen](https://github.com/ueokande/vim-vixen) | [](https://addons.mozilla.org/firefox/addon/vim-vixen/) | [Firefox 57+](https://blog.mozilla.org/addons/2017/09/28/webextensions-in-firefox-57/) | :heavy_check_mark: | [JavaScript](https://www.javascript.com/) |
| [Tridactyl](https://github.com/tridactyl/tridactyl) | [](https://addons.mozilla.org/firefox/addon/tridactyl-vim/) | [Firefox 57+](https://blog.mozilla.org/addons/2017/09/28/webextensions-in-firefox-57/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) | | [Tridactyl](https://github.com/tridactyl/tridactyl) | [](https://addons.mozilla.org/firefox/addon/tridactyl-vim/) | [Firefox 57+](https://blog.mozilla.org/addons/2017/09/28/webextensions-in-firefox-57/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.org/) |
| [Vimari](https://github.com/guyht/vimari) | [](https://github.com/guyht/vimari/releases) | [Safari](https://www.apple.com/safari/) | :heavy_check_mark: | [JavaScript](https://www.javascript.com/) | | [Vimari](https://github.com/guyht/vimari) | [](https://github.com/guyht/vimari/releases) | [Safari](https://www.apple.com/safari/) | :heavy_check_mark: | [JavaScript](https://www.javascript.com/) |

View File

@ -1,93 +1,73 @@
import org.jetbrains.changelog.Changelog.OutputType.HTML import org.jetbrains.changelog.*
import org.jetbrains.changelog.date import org.jetbrains.intellij.tasks.*
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
idea apply true idea apply true
kotlin("jvm") version "1.9.20-Beta" kotlin("jvm") version "1.6.0-RC2"
id("org.jetbrains.intellij") version "1.15.0" id("org.jetbrains.intellij") version "1.2.1"
id("org.jetbrains.changelog") version "2.2.0" id("org.jetbrains.changelog") version "1.3.1"
id("com.github.ben-manes.versions") version "0.48.0" id("com.github.ben-manes.versions") version "0.39.0"
} }
tasks { tasks {
compileKotlin { withType<KotlinCompile> {
kotlinOptions.jvmTarget = JavaVersion.VERSION_17.toString() kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
} }
named<Zip>("buildPlugin") { named<Zip>("buildPlugin") {
dependsOn("test") dependsOn("test")
archiveFileName = "AceJump.zip" archiveFileName.set("AceJump.zip")
} }
runIde { withType<RunIdeTask> {
dependsOn("test") dependsOn("test")
findProperty("luginDev")?.let { args = listOf(projectDir.absolutePath) } findProperty("luginDev")?.let { args = listOf(projectDir.absolutePath) }
} }
publishPlugin { publishPlugin {
val intellijPublishToken: String? by project val intellijPublishToken: String? by project
token = intellijPublishToken token.set(intellijPublishToken)
} }
patchPluginXml { patchPluginXml {
sinceBuild = "223.7571.182" sinceBuild.set("203.7717.56")
changeNotes = provider { changeNotes.set(provider {
changelog.renderItem(changelog.getAll().values.take(2).last(), HTML) changelog.getAll().values.take(2).last().toHTML()
} })
} }
runPluginVerifier { runPluginVerifier {
ideVersions = listOf("2023.2") ideVersions.set(listOf("2021.2.1"))
}
// Remove pending: https://youtrack.jetbrains.com/issue/IDEA-278926
val test by getting(Test::class) {
isScanForTestClasses = false
// Only run tests from classes that end with "Test"
include("**/AceTest.class")
include("**/ExternalUsageTest.class")
include("**/LatencyTest.class")
} }
} }
kotlin {
jvmToolchain {
run {
languageVersion = JavaLanguageVersion.of(17)
}
}
sourceSets.all {
languageSettings.apply {
languageVersion = "2.0"
}
}
}
val acejumpVersion = "3.8.16"
changelog { changelog {
version = acejumpVersion version.set("3.8.5")
path = "${project.projectDir}/CHANGES.md" path.set("${project.projectDir}/CHANGES.md")
header = provider { "[${project.version}] - ${date()}" } header.set(provider { "[${project.version}] - ${date()}" })
itemPrefix = "-" itemPrefix.set("-")
unreleasedTerm = "Unreleased" unreleasedTerm.set("Unreleased")
} }
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://jitpack.io")
} }
dependencies { dependencies {
// https://github.com/anyascii/anyascii // gradle-intellij-plugin doesn't attach sources properly for Kotlin :(
implementation("com.anyascii:anyascii:0.3.2") implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
compileOnly(kotlin("stdlib-jdk8"))
implementation("com.anyascii:anyascii:0.3.0")
} }
intellij { intellij {
version = "2023.2.1" version.set("2021.2.1")
pluginName = "AceJump" pluginName.set("AceJump")
updateSinceUntilBuild = false updateSinceUntilBuild.set(false)
plugins = listOf("java") plugins.set(listOf("java"))
} }
group = "org.acejump" group = "org.acejump"
version = acejumpVersion version = "3.8.5"

View File

@ -1 +0,0 @@
org.gradle.jvmargs=-Xmx2048m

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -2,11 +2,9 @@ package org.acejump
import com.anyascii.AnyAscii import com.anyascii.AnyAscii
import com.intellij.diff.util.DiffUtil.getLineCount import com.intellij.diff.util.DiffUtil.getLineCount
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.* import com.intellij.openapi.editor.*
import it.unimi.dsi.fastutil.ints.IntArrayList import it.unimi.dsi.fastutil.ints.IntArrayList
import org.acejump.config.AceConfig import org.acejump.config.AceConfig
import java.awt.Point
import kotlin.math.* import kotlin.math.*
/** /**
@ -129,15 +127,18 @@ fun Editor.offsetCenter(first: Int, second: Int): LogicalPosition {
return offsetToLogicalPosition(getLineStartOffset(center)) return offsetToLogicalPosition(getLineStartOffset(center))
} }
// Borrowed from Editor.calculateVisibleRange() but only available after 232.6095.10
fun Editor.getView(): IntRange { fun Editor.getView(): IntRange {
ApplicationManager.getApplication().assertIsDispatchThread() val firstVisibleLine = max(0, getVisualLineAtTopOfScreen() - 1)
val rect = scrollingModel.visibleArea val firstLine = visualLineToLogicalLine(firstVisibleLine)
val startPosition = xyToLogicalPosition(Point(rect.x, rect.y)) val startOffset = getLineStartOffset(firstLine)
val visibleStart = logicalPositionToOffset(startPosition)
val endPosition = xyToLogicalPosition(Point(rect.x + rect.width, rect.y + rect.height)) val height = getScreenHeight() + 2
val visibleEnd = logicalPositionToOffset(LogicalPosition(endPosition.line + 1, 0)) val lastLine = visualLineToLogicalLine(firstVisibleLine + height)
return visibleStart..visibleEnd var endOffset = getLineEndOffset(lastLine, true)
endOffset = normalizeOffset(lastLine, endOffset)
endOffset = min(max(0, document.textLength - 1), endOffset + 1)
return startOffset..endOffset
} }
/** /**

View File

@ -1,30 +1,17 @@
package org.acejump.action package org.acejump.action
import com.intellij.openapi.actionSystem.ActionUpdateThread
import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR import com.intellij.openapi.actionSystem.CommonDataKeys.EDITOR
import com.intellij.openapi.actionSystem.PlatformDataKeys.LAST_ACTIVE_FILE_EDITOR
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.TextEditor import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
import com.intellij.openapi.project.DumbAwareAction import com.intellij.openapi.project.DumbAwareAction
import com.intellij.util.IncorrectOperationException import com.intellij.util.IncorrectOperationException
import org.acejump.boundaries.Boundaries import org.acejump.boundaries.Boundaries
import org.acejump.boundaries.StandardBoundaries.AFTER_CARET import org.acejump.boundaries.StandardBoundaries.*
import org.acejump.boundaries.StandardBoundaries.BEFORE_CARET
import org.acejump.boundaries.StandardBoundaries.WHOLE_FILE
import org.acejump.input.JumpMode import org.acejump.input.JumpMode
import org.acejump.input.JumpMode.DECLARATION import org.acejump.input.JumpMode.*
import org.acejump.input.JumpMode.JUMP
import org.acejump.input.JumpMode.JUMP_END
import org.acejump.input.JumpMode.TARGET
import org.acejump.search.Pattern import org.acejump.search.Pattern
import org.acejump.search.Pattern.ALL_WORDS import org.acejump.search.Pattern.*
import org.acejump.search.Pattern.LINE_ALL_MARKS
import org.acejump.search.Pattern.LINE_ENDS
import org.acejump.search.Pattern.LINE_INDENTS
import org.acejump.search.Pattern.LINE_STARTS
import org.acejump.session.Session import org.acejump.session.Session
import org.acejump.session.SessionManager import org.acejump.session.SessionManager
@ -32,28 +19,25 @@ import org.acejump.session.SessionManager
* Base class for keyboard-activated actions that create or update an AceJump [Session]. * Base class for keyboard-activated actions that create or update an AceJump [Session].
*/ */
sealed class AceAction: DumbAwareAction() { sealed class AceAction: DumbAwareAction() {
override fun getActionUpdateThread(): ActionUpdateThread = ActionUpdateThread.BGT
final override fun update(action: AnActionEvent) { final override fun update(action: AnActionEvent) {
action.presentation.isEnabled = action.presentation.isEnabled = action.getData(EDITOR) != null
(action.getData(EDITOR) ?: (action.getData(LAST_ACTIVE_FILE_EDITOR) as? TextEditor)?.editor) != null
} }
final override fun actionPerformed(e: AnActionEvent) { final override fun actionPerformed(e: AnActionEvent) {
val editor = e.getData(EDITOR) ?: (e.getData(LAST_ACTIVE_FILE_EDITOR) as? TextEditor)?.editor ?: return val editor = e.getData(EDITOR) ?: return
val project = e.project val project = e.project
if (project != null) { if (project != null) {
try { try {
val fem = FileEditorManager.getInstance(project) as FileEditorManagerEx val openEditors = FileEditorManagerEx.getInstanceEx(project).splitters.selectedEditors
val openEditors = fem.splitters.getSelectedEditors()
.mapNotNull { (it as? TextEditor)?.editor } .mapNotNull { (it as? TextEditor)?.editor }
.sortedBy { if (it === editor) 0 else 1 } .sortedBy { if (it === editor) 0 else 1 }
invoke(SessionManager.start(editor, openEditors)) invoke(SessionManager.start(editor, openEditors))
} catch (e: IncorrectOperationException) { } catch (e: IncorrectOperationException) {
invoke(SessionManager.start(editor)) invoke(SessionManager.start(editor))
} }
} else { }
else {
invoke(SessionManager.start(editor)) invoke(SessionManager.start(editor))
} }
} }
@ -67,13 +51,6 @@ sealed class AceAction: DumbAwareAction() {
final override fun invoke(session: Session) = session.toggleJumpMode(mode) final override fun invoke(session: Session) = session.toggleJumpMode(mode)
} }
/**
* Generic action type that toggles a specific [JumpMode] with [Boundaries].
*/
abstract class BaseToggleBoundedJumpModeAction(private val mode: JumpMode, private val boundaries: Boundaries): AceAction() {
final override fun invoke(session: Session) = session.toggleJumpMode(mode, boundaries)
}
/** /**
* Generic action type that starts a regex search. * Generic action type that starts a regex search.
*/ */
@ -97,17 +74,12 @@ sealed class AceAction: DumbAwareAction() {
// @formatter:off // @formatter:off
// Unbounded Toggle Modes
class ToggleJumpMode : BaseToggleJumpModeAction(JUMP) class ToggleJumpMode : BaseToggleJumpModeAction(JUMP)
class ToggleJumpEndMode : BaseToggleJumpModeAction(JUMP_END) class ToggleJumpEndMode : BaseToggleJumpModeAction(JUMP_END)
class ToggleTargetMode : BaseToggleJumpModeAction(TARGET) class ToggleTargetMode : BaseToggleJumpModeAction(TARGET)
class ToggleDeclarationMode : BaseToggleJumpModeAction(DECLARATION) class ToggleDeclarationMode : BaseToggleJumpModeAction(DECLARATION)
// Bounded Toggle Modes
class ToggleBackwardJumpMode : BaseToggleBoundedJumpModeAction(JUMP, BEFORE_CARET)
class ToggleForwardJumpMode : BaseToggleBoundedJumpModeAction(JUMP, AFTER_CARET)
// Regex Modes
class StartAllWordsMode : BaseRegexSearchAction(ALL_WORDS, WHOLE_FILE) class StartAllWordsMode : BaseRegexSearchAction(ALL_WORDS, WHOLE_FILE)
class StartAllWordsBackwardsMode : BaseRegexSearchAction(ALL_WORDS, BEFORE_CARET) class StartAllWordsBackwardsMode : BaseRegexSearchAction(ALL_WORDS, BEFORE_CARET)
class StartAllWordsForwardMode : BaseRegexSearchAction(ALL_WORDS, AFTER_CARET) class StartAllWordsForwardMode : BaseRegexSearchAction(ALL_WORDS, AFTER_CARET)

View File

@ -1,31 +1,22 @@
package org.acejump.action package org.acejump.action
import com.intellij.openapi.actionSystem.ActionManager import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.IdeActions.*
import com.intellij.openapi.actionSystem.IdeActions.ACTION_GOTO_DECLARATION
import com.intellij.openapi.actionSystem.IdeActions.ACTION_GOTO_TYPE_DECLARATION
import com.intellij.openapi.command.CommandProcessor import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.command.UndoConfirmationPolicy import com.intellij.openapi.command.UndoConfirmationPolicy
import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.Document
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId import com.intellij.openapi.editor.actionSystem.DocCommandGroupId
import com.intellij.openapi.fileEditor.FileEditorManager
import com.intellij.openapi.fileEditor.TextEditor import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.playback.commands.ActionCommand import com.intellij.openapi.ui.playback.commands.ActionCommand
import org.acejump.countMatchingCharacters import org.acejump.*
import org.acejump.immutableText
import org.acejump.input.JumpMode import org.acejump.input.JumpMode
import org.acejump.input.JumpMode.DECLARATION import org.acejump.input.JumpMode.*
import org.acejump.input.JumpMode.JUMP_END
import org.acejump.input.JumpMode.TARGET
import org.acejump.isWordPart
import org.acejump.search.SearchProcessor import org.acejump.search.SearchProcessor
import org.acejump.search.Tag import org.acejump.search.Tag
import org.acejump.wordEnd
import org.acejump.wordStart
/** /**
* Performs [JumpMode] navigation and actions. * Performs [JumpMode] navigation and actions.
@ -37,7 +28,7 @@ internal class TagJumper(private val mode: JumpMode, private val searchProcessor
fun visit(tag: Tag) { fun visit(tag: Tag) {
val editor = tag.editor val editor = tag.editor
val offset = tag.offset val offset = tag.offset
if (mode === JUMP_END || mode === TARGET) { if (mode === JUMP_END || mode === TARGET) {
val chars = editor.immutableText val chars = editor.immutableText
val matchingChars = searchProcessor?.let { chars.countMatchingCharacters(offset, it.query.rawText) } ?: 0 val matchingChars = searchProcessor?.let { chars.countMatchingCharacters(offset, it.query.rawText) } ?: 0
@ -104,12 +95,12 @@ internal class TagJumper(private val mode: JumpMode, private val searchProcessor
selectionModel.setSelection(fromOffset, toOffset) selectionModel.setSelection(fromOffset, toOffset)
caretModel.moveToOffset(toOffset) caretModel.moveToOffset(toOffset)
} }
private fun ensureEditorFocused(editor: Editor) { private fun ensureEditorFocused(editor: Editor) {
val project = editor.project ?: return val project = editor.project ?: return
val fem = FileEditorManager.getInstance(project) as FileEditorManagerEx val fem = FileEditorManagerEx.getInstanceEx(project)
val window = fem.windows.firstOrNull { (it.getSelectedComposite(false)?.selectedWithProvider?.fileEditor as? TextEditor)?.editor === editor } val window = fem.windows.firstOrNull { (it.selectedEditor?.selectedWithProvider?.fileEditor as? TextEditor)?.editor === editor }
if (window != null && window !== fem.currentWindow) { if (window != null && window !== fem.currentWindow) {
fem.currentWindow = window fem.currentWindow = window
} }

View File

@ -5,10 +5,10 @@ import org.acejump.*
import org.acejump.search.SearchProcessor import org.acejump.search.SearchProcessor
internal class TagScroller(private val editor: Editor, private val searchProcessor: SearchProcessor) { internal class TagScroller(private val editor: Editor, private val searchProcessor: SearchProcessor) {
fun scroll( fun scroll(forward: Boolean = true): Boolean {
forward: Boolean = true, val position = if (forward) findNextPosition() else findPreviousPosition()
position: LogicalPosition? = if (forward) findNextPosition() else findPreviousPosition() return if (position != null) true.also { scrollTo(position) } else false
) = if (position != null) true.also { scrollTo(position) } else false }
private fun scrollTo(position: LogicalPosition) = editor.run { private fun scrollTo(position: LogicalPosition) = editor.run {
scrollingModel.disableAnimation() scrollingModel.disableAnimation()

View File

@ -2,6 +2,7 @@ package org.acejump.action
import com.intellij.openapi.editor.* import com.intellij.openapi.editor.*
import com.intellij.openapi.editor.ScrollType.* import com.intellij.openapi.editor.ScrollType.*
import org.acejump.*
import org.acejump.search.SearchProcessor import org.acejump.search.SearchProcessor
import org.acejump.search.Tag import org.acejump.search.Tag
import kotlin.math.abs import kotlin.math.abs

View File

@ -16,14 +16,12 @@ interface Boundaries {
* offsets outside the boundary, for ex. when the boundary is rectangular * offsets outside the boundary, for ex. when the boundary is rectangular
* and the file has long lines which are only partially visible. * and the file has long lines which are only partially visible.
*/ */
fun getOffsetRange(editor: Editor, cache: EditorOffsetCache = EditorOffsetCache.Uncached): IntRange = fun getOffsetRange(editor: Editor, cache: EditorOffsetCache = EditorOffsetCache.Uncached): IntRange
StandardBoundaries.VISIBLE_ON_SCREEN.getOffsetRange(editor, cache)
/** /**
* Returns whether the editor offset is included within the boundary. * Returns whether the editor offset is included within the boundary.
*/ */
fun isOffsetInside(editor: Editor, offset: Int, cache: EditorOffsetCache = EditorOffsetCache.Uncached): Boolean = fun isOffsetInside(editor: Editor, offset: Int, cache: EditorOffsetCache = EditorOffsetCache.Uncached): Boolean
StandardBoundaries.VISIBLE_ON_SCREEN.isOffsetInside(editor, offset, cache)
/** /**
* Creates a boundary so that an offset/range is within the boundary * Creates a boundary so that an offset/range is within the boundary

View File

@ -30,7 +30,9 @@ sealed class EditorOffsetCache {
*/ */
abstract fun offsetToXY(editor: Editor, offset: Int): Point abstract fun offsetToXY(editor: Editor, offset: Int): Point
companion object { fun new(): EditorOffsetCache = Cache() } companion object {
fun new(): EditorOffsetCache = Cache()
}
private class Cache: EditorOffsetCache() { private class Cache: EditorOffsetCache() {
private var visibleArea: Pair<Point, Point>? = null private var visibleArea: Pair<Point, Point>? = null
@ -43,13 +45,17 @@ sealed class EditorOffsetCache {
override fun xyToOffset(editor: Editor, pos: Point): Int = override fun xyToOffset(editor: Editor, pos: Point): Int =
pointToOffset.getInt(pos).let { offset -> pointToOffset.getInt(pos).let { offset ->
if (offset != -1) offset if (offset != -1) offset
else Uncached.xyToOffset(editor, pos) else Uncached.xyToOffset(editor, pos).also {
.also { pointToOffset.put(pos, it) } @Suppress("ReplacePutWithAssignment")
pointToOffset.put(pos, it)
}
} }
override fun offsetToXY(editor: Editor, offset: Int) = override fun offsetToXY(editor: Editor, offset: Int) =
offsetToPoint.get(offset) ?: Uncached.offsetToXY(editor, offset) offsetToPoint.get(offset) ?: Uncached.offsetToXY(editor, offset).also {
.also { offsetToPoint.put(offset, it) } @Suppress("ReplacePutWithAssignment")
offsetToPoint.put(offset, it)
}
} }
object Uncached: EditorOffsetCache() { object Uncached: EditorOffsetCache() {

View File

@ -5,10 +5,10 @@ import com.intellij.openapi.editor.Editor
enum class StandardBoundaries : Boundaries { enum class StandardBoundaries : Boundaries {
WHOLE_FILE { WHOLE_FILE {
override fun getOffsetRange(editor: Editor, cache: EditorOffsetCache) = override fun getOffsetRange(editor: Editor, cache: EditorOffsetCache) =
0..editor.document.textLength 0 until editor.document.textLength
override fun isOffsetInside(editor: Editor, offset: Int, cache: EditorOffsetCache) = override fun isOffsetInside(editor: Editor, offset: Int, cache: EditorOffsetCache) =
offset in (0..editor.document.textLength) offset in (0 until editor.document.textLength)
}, },
VISIBLE_ON_SCREEN { VISIBLE_ON_SCREEN {

View File

@ -1,9 +1,9 @@
package org.acejump.config package org.acejump.config
import com.intellij.openapi.components.PersistentStateComponent import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.components.State import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage import com.intellij.openapi.components.Storage
import com.intellij.util.application
import org.acejump.input.KeyLayoutCache import org.acejump.input.KeyLayoutCache
/** /**
@ -16,19 +16,19 @@ class AceConfig: PersistentStateComponent<AceSettings> {
private var aceSettings = AceSettings() private var aceSettings = AceSettings()
companion object { companion object {
val settings get() = application.getService(AceConfig::class.java).aceSettings val settings get() = ServiceManager.getService(AceConfig::class.java).aceSettings
// @formatter:off // @formatter:off
val layout get() = settings.layout val layout get() = settings.layout
val cycleModes get() = settings.let { arrayOf(it.cycleMode1, it.cycleMode2, it.cycleMode3, it.cycleMode4) } val cycleModes get() = settings.let { arrayOf(it.cycleMode1, it.cycleMode2, it.cycleMode3, it.cycleMode4) }
val minQueryLength get() = settings.minQueryLength val minQueryLength get() = settings.minQueryLength
val jumpModeColor get() = settings.getJumpModeJBC() val jumpModeColor get() = settings.jumpModeColor
val jumpEndModeColor get() = settings.getJumpEndModeJBC() val jumpEndModeColor get() = settings.jumpEndModeColor
val targetModeColor get() = settings.getTargetModeJBC() val targetModeColor get() = settings.targetModeColor
val definitionModeColor get() = settings.getDefinitionModeJBC() val definitionModeColor get() = settings.definitionModeColor
val textHighlightColor get() = settings.getTextHighlightJBC() val textHighlightColor get() = settings.textHighlightColor
val tagForegroundColor get() = settings.getTagForegroundJBC() val tagForegroundColor get() = settings.tagForegroundColor
val tagBackgroundColor get() = settings.getTagBackgroundJBC() val tagBackgroundColor get() = settings.tagBackgroundColor
val searchWholeFile get() = settings.searchWholeFile val searchWholeFile get() = settings.searchWholeFile
val mapToASCII get() = settings.mapToASCII val mapToASCII get() = settings.mapToASCII
val showSearchNotification get() = settings.showSearchNotification val showSearchNotification get() = settings.showSearchNotification

View File

@ -19,13 +19,13 @@ class AceConfigurable: Configurable {
panel.cycleMode3 != settings.cycleMode3 || panel.cycleMode3 != settings.cycleMode3 ||
panel.cycleMode4 != settings.cycleMode4 || panel.cycleMode4 != settings.cycleMode4 ||
panel.minQueryLengthInt != settings.minQueryLength || panel.minQueryLengthInt != settings.minQueryLength ||
panel.jumpModeColor?.rgb != settings.jumpModeColor || panel.jumpModeColor != settings.jumpModeColor ||
panel.jumpEndModeColor?.rgb != settings.jumpEndModeColor || panel.jumpEndModeColor != settings.jumpEndModeColor ||
panel.targetModeColor?.rgb != settings.targetModeColor || panel.targetModeColor != settings.targetModeColor ||
panel.definitionModeColor?.rgb != settings.definitionModeColor || panel.definitionModeColor != settings.definitionModeColor ||
panel.textHighlightColor?.rgb != settings.textHighlightColor || panel.textHighlightColor != settings.textHighlightColor ||
panel.tagForegroundColor?.rgb != settings.tagForegroundColor || panel.tagForegroundColor != settings.tagForegroundColor ||
panel.tagBackgroundColor?.rgb != settings.tagBackgroundColor || panel.tagBackgroundColor != settings.tagBackgroundColor ||
panel.searchWholeFile != settings.searchWholeFile || panel.searchWholeFile != settings.searchWholeFile ||
panel.mapToASCII != settings.mapToASCII || panel.mapToASCII != settings.mapToASCII ||
panel.showSearchNotification != settings.showSearchNotification panel.showSearchNotification != settings.showSearchNotification
@ -38,13 +38,13 @@ class AceConfigurable: Configurable {
settings.cycleMode3 = panel.cycleMode3 settings.cycleMode3 = panel.cycleMode3
settings.cycleMode4 = panel.cycleMode4 settings.cycleMode4 = panel.cycleMode4
settings.minQueryLength = panel.minQueryLengthInt ?: settings.minQueryLength settings.minQueryLength = panel.minQueryLengthInt ?: settings.minQueryLength
panel.jumpModeColor?.let { settings.jumpModeColor = it.rgb } panel.jumpModeColor?.let { settings.jumpModeColor = it }
panel.jumpEndModeColor?.let { settings.jumpEndModeColor = it.rgb } panel.jumpEndModeColor?.let { settings.jumpEndModeColor = it }
panel.targetModeColor?.let { settings.targetModeColor = it.rgb } panel.targetModeColor?.let { settings.targetModeColor = it }
panel.definitionModeColor?.let { settings.definitionModeColor = it.rgb } panel.definitionModeColor?.let { settings.definitionModeColor = it }
panel.textHighlightColor?.let { settings.textHighlightColor = it.rgb } panel.textHighlightColor?.let { settings.textHighlightColor = it }
panel.tagForegroundColor?.let { settings.tagForegroundColor = it.rgb } panel.tagForegroundColor?.let { settings.tagForegroundColor = it }
panel.tagBackgroundColor?.let { settings.tagBackgroundColor = it.rgb } panel.tagBackgroundColor?.let { settings.tagBackgroundColor = it }
settings.searchWholeFile = panel.searchWholeFile settings.searchWholeFile = panel.searchWholeFile
settings.mapToASCII = panel.mapToASCII settings.mapToASCII = panel.mapToASCII
settings.showSearchNotification = panel.showSearchNotification settings.showSearchNotification = panel.showSearchNotification

View File

@ -1,8 +1,11 @@
package org.acejump.config package org.acejump.config
import com.intellij.ui.JBColor import com.intellij.util.xmlb.Converter
import org.acejump.input.* import com.intellij.util.xmlb.annotations.OptionTag
import org.acejump.input.JumpMode
import org.acejump.input.KeyLayout
import org.acejump.input.KeyLayout.QWERTY import org.acejump.input.KeyLayout.QWERTY
import java.awt.Color
data class AceSettings( data class AceSettings(
var layout: KeyLayout = QWERTY, var layout: KeyLayout = QWERTY,
@ -13,31 +16,35 @@ data class AceSettings(
var cycleMode4: JumpMode = JumpMode.JUMP_END, var cycleMode4: JumpMode = JumpMode.JUMP_END,
var minQueryLength: Int = 1, var minQueryLength: Int = 1,
var jumpModeColor: Int = 0xFFFFFF, @OptionTag("jumpModeRGB", converter = ColorConverter::class)
var jumpModeColor: Color = Color(0xFFFFFF),
var jumpEndModeColor: Int = 0x33E78A, @OptionTag("jumpEndModeRGB", converter = ColorConverter::class)
var jumpEndModeColor: Color = Color(0x33E78A),
var targetModeColor: Int = 0xFFB700, @OptionTag("targetModeRGB", converter = ColorConverter::class)
var targetModeColor: Color = Color(0xFFB700),
var definitionModeColor: Int = 0x6FC5FF, @OptionTag("definitionModeRGB", converter = ColorConverter::class)
var definitionModeColor: Color = Color(0x6FC5FF),
var textHighlightColor: Int = 0x394B58, @OptionTag("textHighlightRGB", converter = ColorConverter::class)
var textHighlightColor: Color = Color(0x394B58),
var tagForegroundColor: Int = 0xFFFFFF, @OptionTag("tagForegroundRGB", converter = ColorConverter::class)
var tagForegroundColor: Color = Color(0xFFFFFF),
var tagBackgroundColor: Int = 0x008299, @OptionTag("tagBackgroundRGB", converter = ColorConverter::class)
var tagBackgroundColor: Color = Color(0x008299),
var searchWholeFile: Boolean = true, var searchWholeFile: Boolean = true,
var mapToASCII: Boolean = false, var mapToASCII : Boolean = false,
var showSearchNotification: Boolean = false var showSearchNotification : Boolean = false
) { )
fun getJumpModeJBC() = JBColor.namedColor("jumpModeRGB", jumpModeColor)
fun getJumpEndModeJBC() = JBColor.namedColor("jumpEndModeRGB", jumpEndModeColor) internal class ColorConverter: Converter<Color>() {
fun getTargetModeJBC() = JBColor.namedColor("targetModeRGB", targetModeColor) override fun toString(value: Color) = value.rgb.toString()
fun getDefinitionModeJBC() = JBColor.namedColor("definitionModeRGB", definitionModeColor) override fun fromString(value: String) = value.toIntOrNull()?.let(::Color)
fun getTextHighlightJBC() = JBColor.namedColor("textHighlightRGB", textHighlightColor)
fun getTagForegroundJBC() = JBColor.namedColor("tagForegroundRGB", tagForegroundColor)
fun getTagBackgroundJBC() = JBColor.namedColor("tagBackgroundRGB", tagBackgroundColor)
} }

View File

@ -2,11 +2,20 @@ package org.acejump.config
import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.ComboBox
import com.intellij.ui.ColorPanel import com.intellij.ui.ColorPanel
import com.intellij.ui.components.* import com.intellij.ui.components.JBCheckBox
import com.intellij.ui.dsl.builder.* import com.intellij.ui.components.JBTextArea
import org.acejump.input.* import com.intellij.ui.components.JBTextField
import java.awt.* import com.intellij.ui.layout.Cell
import javax.swing.* import com.intellij.ui.layout.GrowPolicy.MEDIUM_TEXT
import com.intellij.ui.layout.GrowPolicy.SHORT_TEXT
import com.intellij.ui.layout.panel
import org.acejump.input.JumpMode
import org.acejump.input.KeyLayout
import java.awt.Color
import java.awt.Font
import javax.swing.JCheckBox
import javax.swing.JComponent
import javax.swing.JPanel
import javax.swing.text.JTextComponent import javax.swing.text.JTextComponent
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@ -45,40 +54,45 @@ internal class AceSettingsPanel {
} }
internal val rootPanel: JPanel = panel { internal val rootPanel: JPanel = panel {
group("Characters and Layout") { fun Cell.short(component: JComponent) = component(growPolicy = SHORT_TEXT)
row("Allowed characters in tags:") { cell(tagCharsField).columns(COLUMNS_LARGE) } fun Cell.medium(component: JComponent) = component(growPolicy = MEDIUM_TEXT)
row("Keyboard layout:") { cell(keyboardLayoutCombo).columns(COLUMNS_SHORT) }
row("Keyboard design:") { cell(keyboardLayoutArea).columns(COLUMNS_SHORT) } titledRow("Characters and Layout") {
row("Allowed characters in tags:") { medium(tagCharsField) }
row("Keyboard layout:") { short(keyboardLayoutCombo) }
row("Keyboard design:") { short(keyboardLayoutArea) }
} }
group("Modes") { titledRow("Modes") {
row("Cycle order:") { row("Cycle order:") { cell { cycleModeCombo1() } }
cell(cycleModeCombo1).columns(10) row("") {
cell(cycleModeCombo2).columns(10) cell(isVerticalFlow = true) {
cell(cycleModeCombo3).columns(10) cycleModeCombo2()
cell(cycleModeCombo4).columns(10) cycleModeCombo3()
cycleModeCombo4()
}
} }
} }
group("Colors") { titledRow("Colors") {
row("Jump mode caret background:") { cell(jumpModeColorWheel) } row("Jump mode caret background:") { short(jumpModeColorWheel) }
row("Jump to End mode caret background:") { cell(jumpEndModeColorWheel) } row("Jump to End mode caret background:") { short(jumpEndModeColorWheel) }
row("Target mode caret background:") { cell(targetModeColorWheel) } row("Target mode caret background:") { short(targetModeColorWheel) }
row("Definition mode caret background:") { cell(definitionModeColorWheel) } row("Definition mode caret background:") { short(definitionModeColorWheel) }
row("Searched text background:") { cell(textHighlightColorWheel) } row("Searched text background:") { short(textHighlightColorWheel) }
row("Tag foreground:") { cell(tagForegroundColorWheel) } row("Tag foreground:") { short(tagForegroundColorWheel) }
row("Tag background:") { cell(tagBackgroundColorWheel) } row("Tag background:") { short(tagBackgroundColorWheel) }
} }
group("Behavior") { titledRow("Behavior") {
row { cell(searchWholeFileCheckBox.apply { text = "Search whole file" }) } row { short(searchWholeFileCheckBox.apply { text = "Search whole file" }) }
row("Minimum typed characters (1-10):") { cell(minQueryLengthField) } row("Minimum typed characters (1-10):") { short(minQueryLengthField) }
} }
group("Language Settings") { titledRow("Language Settings") {
row { cell(mapToASCIICheckBox.apply { text = "Map unicode to ASCII" }) } row { short(mapToASCIICheckBox.apply { text = "Map unicode to ASCII" }) }
} }
group("Visual") { titledRow("Visual") {
row { cell(showSearchNotificationCheckBox.apply { text = "Show hint with search text" }) } row { short(showSearchNotificationCheckBox.apply { text = "Show hint with search text" }) }
} }
} }
@ -116,13 +130,13 @@ internal class AceSettingsPanel {
cycleMode3 = settings.cycleMode3 cycleMode3 = settings.cycleMode3
cycleMode4 = settings.cycleMode4 cycleMode4 = settings.cycleMode4
minQueryLength = settings.minQueryLength.toString() minQueryLength = settings.minQueryLength.toString()
jumpModeColor = settings.getJumpModeJBC() jumpModeColor = settings.jumpModeColor
jumpEndModeColor = settings.getJumpEndModeJBC() jumpEndModeColor = settings.jumpEndModeColor
targetModeColor = settings.getTargetModeJBC() targetModeColor = settings.targetModeColor
definitionModeColor = settings.getDefinitionModeJBC() definitionModeColor = settings.definitionModeColor
textHighlightColor = settings.getTextHighlightJBC() textHighlightColor = settings.textHighlightColor
tagForegroundColor = settings.getTagForegroundJBC() tagForegroundColor = settings.tagForegroundColor
tagBackgroundColor = settings.getTagBackgroundJBC() tagBackgroundColor = settings.tagBackgroundColor
searchWholeFile = settings.searchWholeFile searchWholeFile = settings.searchWholeFile
mapToASCII = settings.mapToASCII mapToASCII = settings.mapToASCII
showSearchNotification = settings.showSearchNotification showSearchNotification = settings.showSearchNotification

View File

@ -61,19 +61,20 @@ enum class JumpMode {
*/ */
DECLARATION; DECLARATION;
val caretColor: Color get() = when (this) { val caretColor: Color
DISABLED -> AbstractColorsScheme.INHERITED_COLOR_MARKER get() = when (this) {
JUMP -> AceConfig.jumpModeColor JUMP -> AceConfig.jumpModeColor
JUMP_END -> AceConfig.jumpEndModeColor JUMP_END -> AceConfig.jumpEndModeColor
TARGET -> AceConfig.targetModeColor DECLARATION -> AceConfig.definitionModeColor
DECLARATION -> AceConfig.definitionModeColor TARGET -> AceConfig.targetModeColor
} DISABLED -> AbstractColorsScheme.INHERITED_COLOR_MARKER
}
override fun toString() = when (this) { override fun toString() = when (this) {
DISABLED -> "(Skip)" DISABLED -> "(Skip)"
JUMP -> "Jump" JUMP -> "Jump"
JUMP_END -> "Jump to End" JUMP_END -> "Jump to End"
TARGET -> "Target" TARGET -> "Target"
DECLARATION -> "Definition" DECLARATION -> "Definition"
} }
} }

View File

@ -19,43 +19,42 @@ enum class KeyLayout(internal val rows: Array<String>, priority: String) {
QWERTZ(arrayOf("1234567890", "qwertzuiop", "asdfghjkl", "yxcvbnm"), priority = "fjghdkslavncmbxyrutzeiwoqp5849673210"), QWERTZ(arrayOf("1234567890", "qwertzuiop", "asdfghjkl", "yxcvbnm"), priority = "fjghdkslavncmbxyrutzeiwoqp5849673210"),
QGMLWY(arrayOf("1234567890", "qgmlwyfub", "dstnriaeoh", "zxcvjkp"), priority = "naterisodhvkcpjxzlfmuwygbq5849673210"), QGMLWY(arrayOf("1234567890", "qgmlwyfub", "dstnriaeoh", "zxcvjkp"), priority = "naterisodhvkcpjxzlfmuwygbq5849673210"),
QGMLWB(arrayOf("1234567890", "qgmlwbyuv", "dstnriaeoh", "zxcfjkp"), priority = "naterisodhfkcpjxzlymuwbgvq5849673210"), QGMLWB(arrayOf("1234567890", "qgmlwbyuv", "dstnriaeoh", "zxcfjkp"), priority = "naterisodhfkcpjxzlymuwbgvq5849673210"),
NORMAN(arrayOf("1234567890", "qwdfkjurl", "asetgynioh", "zxcvbpm"), priority = "tneigysoahbvpcmxzjkufrdlwq5849673210"), NORMAN(arrayOf("1234567890", "qwdfkjurl", "asetgynioh", "zxcvbpm"), priority = "tneigysoahbvpcmxzjkufrdlwq5849673210");
AZERTY(arrayOf("1234567890", "azertyuiop", "qsdfghjklm", "wxcvbn"), priority = "fjghdkslqvncmbxwrutyeizoap5849673210");
internal val allChars = rows.joinToString("").toCharArray().apply(CharArray::sort).joinToString("") internal val allChars = rows.joinToString("").toCharArray().apply(CharArray::sort).joinToString("")
internal val allPriorities = priority.mapIndexed { index, char -> char to index }.toMap() internal val allPriorities = priority.mapIndexed { index, char -> char to index }.toMap()
private val keyDistances: Map<Char, Object2IntMap<Char>> by lazy { private val keyDistances: Map<Char, Object2IntMap<Char>> by lazy {
val keyDistanceMap = mutableMapOf<Char, Object2IntMap<Char>>() val keyDistanceMap = mutableMapOf<Char, Object2IntMap<Char>>()
val keyLocations = mutableMapOf<Char, Point2D>() val keyLocations = mutableMapOf<Char, Point2D>()
for ((rowIndex, rowChars) in rows.withIndex()) { for ((rowIndex, rowChars) in rows.withIndex()) {
val keyY = rowIndex * 1.2F // Slightly increase cost of traveling between rows. val keyY = rowIndex * 1.2F // Slightly increase cost of traveling between rows.
for ((columnIndex, char) in rowChars.withIndex()) { for ((columnIndex, char) in rowChars.withIndex()) {
val keyX = columnIndex + (0.25F * rowIndex) // Assume a 1/4-key uniform stagger. val keyX = columnIndex + (0.25F * rowIndex) // Assume a 1/4-key uniform stagger.
keyLocations[char] = Point2D.Float(keyX, keyY) keyLocations[char] = Point2D.Float(keyX, keyY)
} }
} }
for (fromChar in allChars) { for (fromChar in allChars) {
val distances = Object2IntOpenHashMap<Char>() val distances = Object2IntOpenHashMap<Char>()
val fromLocation = keyLocations.getValue(fromChar) val fromLocation = keyLocations.getValue(fromChar)
for (toChar in allChars) { for (toChar in allChars) {
distances[toChar] = floor(2F * fromLocation.distanceSq(keyLocations.getValue(toChar))).toInt() distances[toChar] = floor(2F * fromLocation.distanceSq(keyLocations.getValue(toChar))).toInt()
} }
keyDistanceMap[fromChar] = distances keyDistanceMap[fromChar] = distances
} }
keyDistanceMap keyDistanceMap
} }
internal inline fun priority(crossinline tagToChar: (String) -> Char): (String) -> Int? { internal inline fun priority(crossinline tagToChar: (String) -> Char): (String) -> Int? {
return { allPriorities[tagToChar(it)] } return { allPriorities[tagToChar(it)] }
} }
internal fun distanceBetweenKeys(char1: Char, char2: Char): Int { internal fun distanceBetweenKeys(char1: Char, char2: Char): Int {
return keyDistances.getValue(char1).getValue(char2) return keyDistances.getValue(char1).getValue(char2)
} }

View File

@ -1,9 +1,9 @@
package org.acejump.search package org.acejump.search
enum class Pattern(val regex: String) { enum class Pattern(val regex: String) {
LINE_STARTS("^.|^\\n|(?<!.)\\Z"), LINE_STARTS("^.|^\\n"),
LINE_ENDS("\\n|\\Z"), LINE_ENDS("\\n|\\Z"),
LINE_INDENTS("[^\\s].*|^\\n|(?<!.)\\Z"), LINE_INDENTS("[^\\s].*|^\\n"),
LINE_ALL_MARKS(listOf(LINE_ENDS, LINE_STARTS, LINE_INDENTS).flatMap { it.regex.split("|") }.distinct().joinToString("|")), LINE_ALL_MARKS(LINE_ENDS.regex + "|" + LINE_STARTS.regex + "|" + LINE_INDENTS.regex),
ALL_WORDS("(?<=[^a-zA-Z0-9_]|\\A)[a-zA-Z0-9_]"); ALL_WORDS("(?<=[^a-zA-Z0-9_]|\\A)[a-zA-Z0-9_]");
} }

View File

@ -70,7 +70,7 @@ internal class SearchProcessor private constructor(
*/ */
fun type(char: Char, tagger: Tagger): Boolean { fun type(char: Char, tagger: Tagger): Boolean {
val newQuery = query.rawText + char val newQuery = query.rawText + char
val canMatchTag = tagger.canQueryMatchAnyVisibleTag(newQuery) val canMatchTag = tagger.canQueryMatchAnyTag(newQuery)
// If the typed character is not compatible with any existing tag or as // If the typed character is not compatible with any existing tag or as
// a continuation of any previous occurrence, reject the query change // a continuation of any previous occurrence, reject the query change

View File

@ -51,7 +51,7 @@ internal sealed class SearchQuery {
class RegularExpression(private var pattern: String): SearchQuery() { class RegularExpression(private var pattern: String): SearchQuery() {
override val rawText = "" override val rawText = ""
override fun getHighlightLength(text: CharSequence, offset: Int) = 0 override fun getHighlightLength(text: CharSequence, offset: Int) = 1
override fun toRegex(): Regex = override fun toRegex(): Regex =
Regex(pattern, setOf(RegexOption.MULTILINE, RegexOption.IGNORE_CASE)) Regex(pattern, setOf(RegexOption.MULTILINE, RegexOption.IGNORE_CASE))

View File

@ -187,10 +187,7 @@ internal class Solver private constructor(
val chars = editor.immutableText val chars = editor.immutableText
val left = max(0, site + queryLength - 1) val left = max(0, site + queryLength - 1)
val right = chars.wordEndPlus(site) val right = chars.wordEndPlus(site)
if (right >= chars.length) {
return
}
val builder = StringBuilder(1 + right - left) val builder = StringBuilder(1 + right - left)
for (i in left..right) { for (i in left..right) {

View File

@ -5,10 +5,13 @@ import com.google.common.collect.HashBiMap
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import it.unimi.dsi.fastutil.ints.IntArrayList import it.unimi.dsi.fastutil.ints.IntArrayList
import it.unimi.dsi.fastutil.ints.IntList import it.unimi.dsi.fastutil.ints.IntList
import org.acejump.* import org.acejump.ExternalUsage
import org.acejump.boundaries.EditorOffsetCache import org.acejump.boundaries.EditorOffsetCache
import org.acejump.boundaries.StandardBoundaries.VISIBLE_ON_SCREEN import org.acejump.boundaries.StandardBoundaries.VISIBLE_ON_SCREEN
import org.acejump.immutableText
import org.acejump.input.KeyLayoutCache.allPossibleTags import org.acejump.input.KeyLayoutCache.allPossibleTags
import org.acejump.isWordPart
import org.acejump.matchesAt
import org.acejump.view.TagMarker import org.acejump.view.TagMarker
import java.util.AbstractMap.SimpleImmutableEntry import java.util.AbstractMap.SimpleImmutableEntry
import kotlin.collections.component1 import kotlin.collections.component1
@ -140,23 +143,24 @@ internal class Tagger(private val editors: List<Editor>) {
} }
} }
private infix fun Map.Entry<String, Tag>.solves(query: String): Boolean = private infix fun Map.Entry<String, Tag>.solves(query: String): Boolean {
query.endsWith(key, true) && isTagCompatibleWithQuery(key, value, query) return query.endsWith(key, true) && isTagCompatibleWithQuery(key, value, query)
}
private fun isTagCompatibleWithQuery(marker: String, tag: Tag, query: String): Boolean = private fun isTagCompatibleWithQuery(marker: String, tag: Tag, query: String): Boolean {
tag.editor.immutableText.matchesAt(tag.offset, getPlaintextPortion(query, marker), ignoreCase = true) return tag.editor.immutableText.matchesAt(tag.offset, getPlaintextPortion(query, marker), ignoreCase = true)
}
fun isQueryCompatibleWithTagAt(query: String, tag: Tag): Boolean = fun isQueryCompatibleWithTagAt(query: String, tag: Tag): Boolean {
tagMap.inverse()[tag].let { it != null && isTagCompatibleWithQuery(it, tag, query) } return tagMap.inverse()[tag].let { it != null && isTagCompatibleWithQuery(it, tag, query) }
}
fun canQueryMatchAnyVisibleTag(query: String): Boolean = fun canQueryMatchAnyTag(query: String): Boolean {
tagMap.any { (label, tag) -> return tagMap.any { (tag, offset) ->
val tagPortion = getTagPortion(query, label) val tagPortion = getTagPortion(query, tag)
tagPortion.isNotEmpty() tagPortion.isNotEmpty() && tag.startsWith(tagPortion, ignoreCase = true) && isTagCompatibleWithQuery(tag, offset, query)
&& label.startsWith(tagPortion, ignoreCase = true)
&& isTagCompatibleWithQuery(label, tag, query)
&& tag.offset in tag.editor.getView()
} }
}
private fun removeResultsWithOverlappingTags(editor: Editor, offsets: IntList) { private fun removeResultsWithOverlappingTags(editor: Editor, offsets: IntList) {
val iter = offsets.iterator() val iter = offsets.iterator()

View File

@ -10,6 +10,7 @@ import com.intellij.openapi.editor.Editor
internal data class EditorSettings( internal data class EditorSettings(
private val isBlockCursor: Boolean, private val isBlockCursor: Boolean,
private val isBlinkCaret: Boolean, private val isBlinkCaret: Boolean,
private val isReadOnly: Boolean
) { ) {
companion object { companion object {
fun setup(editor: Editor): EditorSettings { fun setup(editor: Editor): EditorSettings {
@ -19,10 +20,12 @@ internal data class EditorSettings(
val original = EditorSettings( val original = EditorSettings(
isBlockCursor = settings.isBlockCursor, isBlockCursor = settings.isBlockCursor,
isBlinkCaret = settings.isBlinkCaret, isBlinkCaret = settings.isBlinkCaret,
isReadOnly = !document.isWritable
) )
settings.isBlockCursor = true settings.isBlockCursor = true
settings.isBlinkCaret = false settings.isBlinkCaret = false
document.setReadOnly(true)
return original return original
} }
@ -34,5 +37,6 @@ internal data class EditorSettings(
settings.isBlockCursor = isBlockCursor settings.isBlockCursor = isBlockCursor
settings.isBlinkCaret = isBlinkCaret settings.isBlinkCaret = isBlinkCaret
document.setReadOnly(isReadOnly)
} }
} }

View File

@ -81,10 +81,6 @@ class TagMarker(
g.color = AceConfig.tagForegroundColor g.color = AceConfig.tagForegroundColor
g.drawString(text, x, y) g.drawString(text, x, y)
} }
private fun isLineEnding(char: Char): Boolean {
return char == '\n' || char == '\r'
}
} }
/** /**
@ -110,7 +106,7 @@ class TagMarker(
private fun alignTag(editor: Editor, cache: EditorOffsetCache, font: TagFont, occupied: List<Rectangle>): Rectangle? { private fun alignTag(editor: Editor, cache: EditorOffsetCache, font: TagFont, occupied: List<Rectangle>): Rectangle? {
val boundaries = VISIBLE_ON_SCREEN val boundaries = VISIBLE_ON_SCREEN
if (hasSpaceRight || offsetL !in 1 until editor.document.textLength || isLineEnding(editor.immutableText[offsetL - 1])) { if (hasSpaceRight || offsetL == 0 || editor.immutableText[offsetL - 1].let { it == '\n' || it == '\r' }) {
val rectR = createRightAlignedTagRect(editor, cache, font) val rectR = createRightAlignedTagRect(editor, cache, font)
return rectR.takeIf { boundaries.isOffsetInside(editor, offsetR, cache) && occupied.none(rectR::intersects) } return rectR.takeIf { boundaries.isOffsetInside(editor, offsetR, cache) && occupied.none(rectR::intersects) }
} }
@ -128,15 +124,7 @@ class TagMarker(
private fun createRightAlignedTagRect(editor: Editor, cache: EditorOffsetCache, font: TagFont): Rectangle { private fun createRightAlignedTagRect(editor: Editor, cache: EditorOffsetCache, font: TagFont): Rectangle {
val pos = cache.offsetToXY(editor, offsetR) val pos = cache.offsetToXY(editor, offsetR)
val shift = font.editorFontMetrics.charWidth(editor.immutableText[offsetR]) + (font.tagCharWidth * shiftR)
val char = if (offsetR >= editor.document.textLength)
' ' // Use the width of a space on the last line.
else editor.immutableText[offsetR].let {
// Use the width of a space on empty lines.
if (isLineEnding(it)) ' ' else it
}
val shift = font.editorFontMetrics.charWidth(char) + (font.tagCharWidth * shiftR)
return Rectangle(pos.x + shift, pos.y, (font.tagCharWidth * length) + 4, font.lineHeight) return Rectangle(pos.x + shift, pos.y, (font.tagCharWidth * length) + 4, font.lineHeight)
} }

View File

@ -9,7 +9,6 @@ import com.intellij.openapi.editor.colors.EditorFontType
import com.intellij.openapi.editor.markup.* import com.intellij.openapi.editor.markup.*
import com.intellij.openapi.editor.markup.HighlighterTargetArea.EXACT_RANGE import com.intellij.openapi.editor.markup.HighlighterTargetArea.EXACT_RANGE
import com.intellij.ui.* import com.intellij.ui.*
import com.intellij.util.DocumentUtil
import com.intellij.util.ui.* import com.intellij.util.ui.*
import it.unimi.dsi.fastutil.ints.IntList import it.unimi.dsi.fastutil.ints.IntList
import org.acejump.* import org.acejump.*
@ -32,7 +31,7 @@ internal class TextHighlighter {
/** /**
* Label for the search notification. * Label for the search notification.
*/ */
private class NotificationLabel(text: String?): JLabel(text) { private class NotificationLabel constructor(text: String?): JLabel(text) {
init { init {
background = HintUtil.getInformationColor() background = HintUtil.getInformationColor()
foreground = JBColor.foreground() foreground = JBColor.foreground()
@ -62,7 +61,9 @@ internal class TextHighlighter {
val modifications = (highlights?.size ?: 0) + offsets.size val modifications = (highlights?.size ?: 0) + offsets.size
val enableBulkEditing = modifications > 1000 val enableBulkEditing = modifications > 1000
DocumentUtil.executeInBulk(document, enableBulkEditing) { try {
if (enableBulkEditing) document.isInBulkUpdate = true
highlights?.forEach(markup::removeHighlighter) highlights?.forEach(markup::removeHighlighter)
previousHighlights[editor] = Array(offsets.size) { index -> previousHighlights[editor] = Array(offsets.size) { index ->
val start = offsets.getInt(index) val start = offsets.getInt(index)
@ -71,6 +72,8 @@ internal class TextHighlighter {
markup.addRangeHighlighter(start, end, LAYER, null, EXACT_RANGE) markup.addRangeHighlighter(start, end, LAYER, null, EXACT_RANGE)
.apply { customRenderer = renderer } .apply { customRenderer = renderer }
} }
} finally {
if (enableBulkEditing) document.isInBulkUpdate = false
} }
} }
@ -93,64 +96,58 @@ internal class TextHighlighter {
previousHint?.hide() previousHint?.hide()
// add notification hint to first editor // add notification hint to first editor
val editor = results.keys.first() results.keys.first().let {
val component: JComponent = editor.component val component: JComponent = it.component
val label1 = NotificationLabel( val label1: JLabel = NotificationLabel(" " +
" " + CodeInsightBundle.message("incremental.search.tooltip.prefix"))
CodeInsightBundle.message("incremental.search.tooltip.prefix") label1.font = UIUtil.getLabelFont().deriveFont(Font.BOLD)
).apply { font = UIUtil.getLabelFont().deriveFont(Font.BOLD) }
val queryText = " " + val queryText = " " +
if (query is SearchQuery.RegularExpression) query.toRegex().toString() if (query is SearchQuery.RegularExpression) query.toRegex().toString()
else query.rawText[0] + query.rawText.drop(1).lowercase() else query.rawText[0] + query.rawText.drop(1).lowercase()
val label2 = NotificationLabel(queryText) val label2 = NotificationLabel(queryText)
val label3 = NotificationLabel( val label3 = NotificationLabel(
"Found ${results.values.flatMap { it.asIterable() }.size}" + "Found ${results.values.flatMap { it.asIterable() }.size}" +
" results in ${results.keys.size}" + " results in ${results.keys.size}" +
" editor" + if (1 != results.keys.size) "s" else "." " editor" + if(1 != results.keys.size) "s" else "."
)
val panel = JPanel(BorderLayout()).apply {
add(label1, BorderLayout.WEST)
add(label2, BorderLayout.CENTER)
add(label3, BorderLayout.EAST)
border = BorderFactory.createLineBorder(
if (jumpMode == JumpMode.DISABLED) JBColor.BLACK else jumpMode.caretColor
) )
preferredSize = Dimension( val panel = JPanel(BorderLayout()).apply {
editor.contentComponent.width + add(label1, BorderLayout.WEST)
label1.preferredSize.width, preferredSize.height add(label2, BorderLayout.CENTER)
add(label3, BorderLayout.EAST)
border = BorderFactory.createLineBorder(
if (jumpMode == JumpMode.DISABLED) Color.BLACK else jumpMode.caretColor
)
preferredSize = Dimension(it.contentComponent.width +
label1.preferredSize.width, preferredSize.height)
}
val hint = LightweightHint(panel)
val x = SwingUtilities.convertPoint(component, 0, 0, component).x
val y: Int = -hint.component.preferredSize.height
val p = SwingUtilities.convertPoint(component, x, y,
component.rootPane.layeredPane)
HintManagerImpl.getInstanceImpl().showEditorHint(
hint,
it,
p,
HIDE_BY_ESCAPE or HIDE_BY_TEXT_CHANGE,
0,
false,
HintHint(it, p).setAwtTooltip(false)
) )
previousHint = hint
} }
val hint = LightweightHint(panel)
val x = SwingUtilities.convertPoint(component, 0, 0, component).x
val y: Int = -hint.component.preferredSize.height
val p = SwingUtilities.convertPoint(
component, x, y,
component.rootPane.layeredPane
)
HintManagerImpl.getInstanceImpl().showEditorHint(
hint,
editor,
p,
HIDE_BY_ESCAPE or HIDE_BY_TEXT_CHANGE,
0,
false,
HintHint(editor, p).setAwtTooltip(false)
)
previousHint = hint
} }
fun reset() { fun reset() {
previousHighlights.forEach { (editor, highlighters) -> previousHighlights.keys.forEach { it.markupModel.removeAllHighlighters() }
highlighters.forEach(editor.markupModel::removeHighlighter)
}
previousHighlights.clear() previousHighlights.clear()
previousHint?.hide() previousHint?.hide()
} }

View File

@ -20,38 +20,27 @@
id="preferences.AceConfigurable" dynamic="true"/> id="preferences.AceConfigurable" dynamic="true"/>
<editorActionHandler action="EditorEscape" order="first" <editorActionHandler action="EditorEscape" order="first"
implementationClass="org.acejump.action.AceEditorAction$Reset" implementationClass="org.acejump.action.AceEditorAction$Reset"/>
id="AceHandlerEscape"/>
<editorActionHandler action="EditorBackSpace" order="first" <editorActionHandler action="EditorBackSpace" order="first"
implementationClass="org.acejump.action.AceEditorAction$ClearSearch" implementationClass="org.acejump.action.AceEditorAction$ClearSearch"/>
id="AceHandlerBackSpace"/>
<editorActionHandler action="EditorStartNewLine" order="first" <editorActionHandler action="EditorStartNewLine" order="first"
implementationClass="org.acejump.action.AceEditorAction$SelectBackward" implementationClass="org.acejump.action.AceEditorAction$SelectBackward"/>
id="AceHandlerStartNewLine"/>
<editorActionHandler action="EditorEnter" order="first" <editorActionHandler action="EditorEnter" order="first"
implementationClass="org.acejump.action.AceEditorAction$SelectForward" implementationClass="org.acejump.action.AceEditorAction$SelectForward"/>
id="AceHandlerEnter"/>
<editorActionHandler action="EditorTab" order="first" <editorActionHandler action="EditorTab" order="first"
implementationClass="org.acejump.action.AceEditorAction$ScrollToNextScreenful" implementationClass="org.acejump.action.AceEditorAction$ScrollToNextScreenful"/>
id="AceHandlerTab"/>
<editorActionHandler action="EditorUnindentSelection" order="first" <editorActionHandler action="EditorUnindentSelection" order="first"
implementationClass="org.acejump.action.AceEditorAction$ScrollToPreviousScreenful" implementationClass="org.acejump.action.AceEditorAction$ScrollToPreviousScreenful"/>
id="AceHandlerUnindentSelection"/>
<editorActionHandler action="EditorUp" order="first" <editorActionHandler action="EditorUp" order="first"
implementationClass="org.acejump.action.AceEditorAction$SearchLineStarts" implementationClass="org.acejump.action.AceEditorAction$SearchLineStarts"/>
id="AceHandlerUp"/>
<editorActionHandler action="EditorLeft" order="first" <editorActionHandler action="EditorLeft" order="first"
implementationClass="org.acejump.action.AceEditorAction$SearchLineIndents" implementationClass="org.acejump.action.AceEditorAction$SearchLineIndents"/>
id="AceHandlerLeft"/>
<editorActionHandler action="EditorLineStart" order="first" <editorActionHandler action="EditorLineStart" order="first"
implementationClass="org.acejump.action.AceEditorAction$SearchLineIndents" implementationClass="org.acejump.action.AceEditorAction$SearchLineIndents"/>
id="AceHandlerLineStart"/>
<editorActionHandler action="EditorRight" order="first" <editorActionHandler action="EditorRight" order="first"
implementationClass="org.acejump.action.AceEditorAction$SearchLineEnds" implementationClass="org.acejump.action.AceEditorAction$SearchLineEnds"/>
id="AceHandlerRight"/>
<editorActionHandler action="EditorLineEnd" order="first" <editorActionHandler action="EditorLineEnd" order="first"
implementationClass="org.acejump.action.AceEditorAction$SearchLineEnds" implementationClass="org.acejump.action.AceEditorAction$SearchLineEnds"/>
id="AceHandlerLineEnd"/>
</extensions> </extensions>
@ -66,12 +55,6 @@
<action id="AceReverseAction" <action id="AceReverseAction"
class="org.acejump.action.AceAction$ActivateOrReverseCycleMode" class="org.acejump.action.AceAction$ActivateOrReverseCycleMode"
text="Activate / Reverse Cycle AceJump Mode"/> text="Activate / Reverse Cycle AceJump Mode"/>
<action id="AceForwardAction"
class="org.acejump.action.AceAction$ToggleForwardJumpMode"
text="Start AceJump in Jump After Caret Mode"/>
<action id="AceBackwardAction"
class="org.acejump.action.AceAction$ToggleBackwardJumpMode"
text="Start AceJump in Jump Before Caret Mode"/>
<action id="AceWordStartAction" <action id="AceWordStartAction"
class="org.acejump.action.AceAction$ToggleJumpMode" class="org.acejump.action.AceAction$ToggleJumpMode"
text="Start AceJump in Jump Mode"/> text="Start AceJump in Jump Mode"/>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 40 41" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"> <svg width="100%" height="100%" viewBox="0 0 40 41" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,0,-635)"> <g transform="matrix(1,0,0,1,0,-635)">
<g id="pluginIcon" transform="matrix(0.154082,0,0,0.154082,-39.7746,553.645)"> <g id="pluginIcon" transform="matrix(0.154082,0,0,0.154082,-39.7746,553.645)">
<rect x="258.139" y="529.264" width="259.602" height="259.602" style="fill:none;"/> <rect x="258.139" y="529.264" width="259.602" height="259.602" style="fill:none;"/>

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -121,11 +121,11 @@ class AceTest : BaseTest() {
} }
fun `test line mode`() { fun `test line mode`() {
makeEditor(" test\n three\n lines") makeEditor(" test\n three\n lines\n")
takeAction(AceAction.StartAllLineMarksMode()) takeAction(AceAction.StartAllLineMarksMode())
assertEquals(9, session.tags.size) assertEquals(8, session.tags.size) // last empty line does not count
} }
fun `test chinese selection`() { fun `test chinese selection`() {

View File

@ -1,7 +1,5 @@
import com.intellij.mock.MockVirtualFile import com.intellij.mock.MockVirtualFile
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.markup.HighlighterLayer
import com.intellij.openapi.editor.markup.HighlighterTargetArea
import com.intellij.openapi.fileEditor.TextEditor import com.intellij.openapi.fileEditor.TextEditor
import com.intellij.util.ui.UIUtil import com.intellij.util.ui.UIUtil
import it.unimi.dsi.fastutil.ints.IntArrayList import it.unimi.dsi.fastutil.ints.IntArrayList
@ -43,12 +41,12 @@ class ExternalUsageTest: BaseTest() {
fun `test externally tagged results with multiple editors`() { fun `test externally tagged results with multiple editors`() {
val fileA = MockVirtualFile("a.txt", "first file") val fileA = MockVirtualFile("a.txt", "first file")
val fileB = MockVirtualFile("b.txt", "second file with more markers") val fileB = MockVirtualFile("b.txt", "second file with more markers")
manager?.openFile(fileA, true) myManager.openFile(fileA, true)
manager?.openFile(fileB, false) myManager.openFile(fileB, false)
val mainEditor = (manager?.selectedEditor as TextEditor).editor val mainEditor = (myManager.selectedEditor as TextEditor).editor
val editorA = (manager?.getEditors(fileA)?.single() as TextEditor).editor val editorA = (myManager.getEditors(fileA).single() as TextEditor).editor
val editorB = (manager?.getEditors(fileB)?.single() as TextEditor).editor val editorB = (myManager.getEditors(fileB).single() as TextEditor).editor
val session = SessionManager.start(mainEditor, listOf(editorA, editorB)) val session = SessionManager.start(mainEditor, listOf(editorA, editorB))
@ -87,7 +85,7 @@ class ExternalUsageTest: BaseTest() {
SessionManager.start(myFixture.editor) SessionManager.start(myFixture.editor)
.startRegexSearch("[aeiou]+", WHOLE_FILE) .startRegexSearch("[aeiou]+", WHOLE_FILE)
TestCase.assertEquals(9, session.tags.size) TestCase.assertEquals(8, session.tags.size)
} }
fun `test external jump with bounds`() { fun `test external jump with bounds`() {
@ -168,21 +166,4 @@ class ExternalUsageTest: BaseTest() {
TestCase.assertEquals(mark, detectedMark) TestCase.assertEquals(mark, detectedMark)
TestCase.assertEquals("", detectedQuery) TestCase.assertEquals("", detectedQuery)
} }
fun `test do not remove other highlights when the session ends`() {
makeEditor("test do not remove other highlights when the session ends")
val markupModel = myFixture.editor.markupModel
val layer = HighlighterLayer.SELECTION - 1
val existedHighlighter = markupModel.addRangeHighlighter(0, 1, layer, null, HighlighterTargetArea.EXACT_RANGE)
takeAction(AceAction.StartAllWordsMode())
val mark = session.tags[0].key
typeAndWaitForResults(mark)
TestCase.assertEquals("last session should be disposed", null, SessionManager[myFixture.editor])
TestCase.assertTrue("existed highlighter should not be removed", existedHighlighter.isValid)
existedHighlighter.dispose()
}
} }

View File

@ -7,6 +7,7 @@ import kotlin.system.measureTimeMillis
@Ignore @Ignore
class LatencyTest: BaseTest() { class LatencyTest: BaseTest() {
private fun `test tag latency`(editorText: String) { private fun `test tag latency`(editorText: String) {
val chars = editorText.toCharArray().distinct().filter { !it.isWhitespace() } val chars = editorText.toCharArray().distinct().filter { !it.isWhitespace() }
val avg = averageTimeWithWarmup(warmupRuns = 10, timedRuns = 10) { val avg = averageTimeWithWarmup(warmupRuns = 10, timedRuns = 10) {

View File

@ -38,7 +38,7 @@ abstract class BaseTest: FileEditorManagerTestCase() {
UIUtil.dispatchAllInvocationEvents() UIUtil.dispatchAllInvocationEvents()
assertEmpty(it.markupModel.allHighlighters) assertEmpty(it.markupModel.allHighlighters)
} }
manager?.closeAllFiles() myManager.closeAllFiles()
} }
fun typeAndWaitForResults(string: String) { fun typeAndWaitForResults(string: String) {