1
0
Fork 0

Compare commits

...

70 Commits

Author SHA1 Message Date
breandan d905909e31 attempt to fix #446 2023-09-16 16:34:46 -04:00
breandan 64c6956b88 add tmux plugins 2023-08-28 21:12:52 -04:00
breandan b1a044dbf8 update change notes 2023-08-28 17:27:29 -04:00
breandan e46cbe1d06 Merge remote-tracking branch 'origin/master' 2023-08-28 17:09:18 -04:00
breandan f64e25a0a9 fixes #442 2023-08-28 17:09:12 -04:00
breandan eba043dfb2
further instructions for locating `AceJump.xml` 2023-08-25 20:54:44 -04:00
breandan a746b0a516
add note about settings deserialization 2023-08-25 09:33:49 -04:00
breandan 209b6c97b7 update versions 2023-08-08 01:19:41 -04:00
breandan 3c89cd07b9 try @YannCebron's solution to #415, pt. II 2023-07-26 22:08:35 -10:00
breandan 2ffcc2c57a try @YannCebron's solution to #415 2023-07-26 21:49:42 -10:00
breandan 56b1dfa9a9 quiet plugin verifier error 2023-06-18 14:22:04 -04:00
breandan 48cadfef4c update versions, acknowledge @wuruofan 2023-06-18 14:11:42 -04:00
breandan 6d47331c71
Merge pull request #440 from wuruofan/master
fix(compatibility): avoid 'java.lang.NoSuchFieldError: Companion' error on lower version IDEA ide
2023-06-18 13:45:42 -04:00
wuruofan 3339f6bdb8 fix(compatibility): avoid 'java.lang.NoSuchFieldError: Companion' error on lower version IDEA ide such as PhpStorm, DevEco Studio etc, which related to `FileEditorManagerEx.getInstanceEx()` companion
Related issues: [#434](https://github.com/acejump/AceJump/issues/434), [#438](https://github.com/acejump/AceJump/issues/438), [#435](https://github.com/acejump/AceJump/issues/435), etc.
2023-06-12 16:34:18 +08:00
breandan e7e85a6944 update to gradle 8.2-rc-2 and new property assignment syntax 2023-06-11 21:42:16 -04:00
breandan 1839efb59f update version 2023-05-28 19:20:17 -04:00
breandan da913f61b6 Merge remote-tracking branch 'origin/master' 2023-05-13 15:04:28 -04:00
breandan 7dd12a0457 fixes #431 2023-05-13 15:04:06 -04:00
breandan dae7bd8fa4 fixes #431 2023-05-13 14:59:39 -04:00
breandan 7d39ea2fef fixes #429 2023-04-28 16:55:42 -04:00
breandan 64ad5039f2 update versions 2023-03-28 23:58:45 -04:00
breandan fb3bfa068e try increasing heap size to appease teamcity? 2023-03-01 14:19:57 -05:00
breandan c52f046a6f switch to K2 compiler 2023-02-14 00:21:43 -05:00
breandan ba739501e8 use BGT and migrate awt.Color to JBColor 2023-02-13 18:45:18 -05:00
breandan e939479368 fixes #426 2023-02-13 16:36:21 -05:00
breandan 1c604ce03c update versions 2023-02-09 16:10:41 -05:00
breandan 099c852e32 Merge remote-tracking branch 'origin/master' 2022-12-29 16:38:27 +11:00
breandan 6642eff1e0 update versions 2022-12-29 16:38:21 +11:00
breandan 73ba06b296
remove duplicate 2022-12-25 17:18:14 +13:00
breandan 9507496092
add Tridactyl 2022-12-25 17:17:30 +13:00
breandan 99e0a50884 fixes #417 2022-12-19 21:30:27 +13:00
breandan c070b211e3 update to latest IDE version 2022-11-30 19:43:24 -05:00
breandan 6a2b5dd422 update build script 2022-11-27 14:05:06 -05:00
breandan b7024842ba add leap and lightspeed 2022-10-13 22:49:12 -04:00
breandan 4831f38b34 update versions and remove unnecessary build instructions 2022-08-22 11:22:17 -04:00
breandan 07014455e6
Merge pull request #410 from AlexPl292/master
Add ids to editor action handlers
2022-08-22 10:59:32 -04:00
Alex Plate ab6c6a702b
Add ids to editor action handlers 2022-08-17 08:20:04 +03:00
breandan 8b9e8bb89b
Merge pull request #409 from colossatr0n/patch-1
Update README.md to specify normal mode mapping for vim-sneak like behavior.
2022-07-24 15:35:48 -04:00
breandan 6c6544cf47 update versions 2022-07-15 23:47:12 -04:00
colossatr0n 7fe9d13f48
Update README.md to specify normal mode mapping for vim-sneak like behavior.
Also update ideavim action syntax to the latest syntax.
2022-07-12 14:23:17 -06:00
breandan f1f9ec5974 fixes #408 2022-06-28 17:53:44 -07:00
breandan 5271d97c00 new kotlin version 2022-06-09 00:55:13 -07:00
breandan 872a99c84c update versions 2022-05-30 07:25:01 -07:00
breandan f8b2db5090
Merge pull request #407 from huoguangjin/master
Remove only the highlighters added by AceJump when the jump session ends
2022-05-16 19:53:40 -04:00
breandan 5f0965c921
update versions 2022-05-16 19:52:12 -04:00
guangjinhuo 5ee0245f0b Add a test case to ensure that other highlighters are not removed #406 2022-04-28 17:30:37 +08:00
guangjinhuo 176d450855 Remove only the highlighters added by AceJump when the jump session ends #406 2022-04-23 15:20:23 +08:00
breandan 1341c6aff4
update version 2022-04-12 12:05:48 -04:00
breandan 0b0622dcdf update anyascii and remove jitpack, fixes anyascii/anyascii#6 2022-04-07 04:00:14 -04:00
breandan 929b08e9d0 update versions 2022-04-05 01:47:41 -04:00
breandan 54ea6ac9c1
Merge pull request #401 from colossatr0n/vim-sneak-bounded-toggle-actions
Add bounded toggle mode classes to start jump mode before the caret or after the caret.
2022-03-27 12:18:56 -04:00
colossatr0n e477a487a2 Add bounded toggle mode classes to start jump mode before the caret or after the caret. 2022-03-27 10:05:42 -06:00
breandan f56dc3d457 fixes #399 2022-03-26 14:39:21 -04:00
breandan 0befd7895e update versions 2022-03-26 14:34:43 -04:00
breandan df94f4ce2a update buildscript as per https://youtrack.jetbrains.com/issue/IDEA-278926#focus=Comments-27-5881199.0-0 2022-03-26 14:26:17 -04:00
breandan 978edff59e update versions and change notes, acknowledge @delphinaubin 2022-03-14 12:42:52 -04:00
breandan f9938590fb
Merge pull request #398 from delphinaubin/add-azerty-key-layout
Add AZERTY keyboard layout (french keyboard)
2022-03-14 12:36:06 -04:00
Delphin Aubin c534192902 Add AZERTY keyboard layout (french keyboard) 2022-02-25 17:01:04 +01:00
breandan 6deac53165 Merge remote-tracking branch 'origin/master' 2022-02-16 04:13:14 -05:00
breandan 2c4d4431bc update versions 2022-02-16 04:13:07 -05:00
breandan 2185da7cb4
Merge pull request #396 from DavidLGoldberg/update-similar-projects-jumpy 2022-02-04 21:27:37 -05:00
David L. Goldberg c2a71a2c43 📝 Update README.md with Jumpy's status
- Jumpy1 is stable and has always been maintained as needed.  Atom's dev has slowed down. Will be fixed as needed.
- Adding Jumpy2.
2022-02-04 19:48:36 -05:00
breandan d29dd3fa34 fixes #392 2021-12-19 12:49:04 -05:00
breandan fdbcea0b4f update IDE version compatibility, fixes #389 2021-12-12 12:12:35 -05:00
breandan c14ae702ba update change notes 2021-12-11 12:30:55 -05:00
breandan 8de4495885 update versions and remove deprecated 2021-12-11 12:06:29 -05:00
breandan dd75e1ddea
update unmaintained and remove canary builds 2021-11-30 00:25:37 -05:00
breandan 02f9ecec5a
update language and reorder 2021-11-30 00:19:23 -05:00
chylex f17f4ef8c4
Fix not highlighting last line
Closes #360
2021-11-21 20:55:19 +01:00
breandan c9034bced6
update changelog 2021-11-21 02:39:25 -05:00
34 changed files with 475 additions and 332 deletions

3
.github/FUNDING.yml vendored
View File

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

View File

@ -2,14 +2,63 @@
## 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 for helping diagnose! - 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 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)! - 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)!
## 3.8.3 ## 3.8.3
@ -20,7 +69,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 for the PRs! - Thanks to [@SaiKai](https://github.com/SaiKai) for the PRs!
## 3.8.1 ## 3.8.1
@ -35,7 +84,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 for the PRs! - Thanks to [@AlexPl292](https://github.com/AlexPl292) for the PRs!
## 3.7.0 ## 3.7.0
- Improvements to tag latency - Improvements to tag latency
@ -49,7 +98,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 for [all the PRs](https://github.com/acejump/AceJump/pulls?q=is%3Apr+author%3Achylex)! - Huge thanks to [@chylex](https://github.com/chylex) for [all the PRs](https://github.com/acejump/AceJump/pulls?q=is%3Apr+author%3Achylex)!
## 3.6.3 ## 3.6.3
@ -59,12 +108,12 @@
## 3.6.2 ## 3.6.2
- Fixes [#226](https://github.com/acejump/AceJump/issues/226). Thanks @AlexPl292! - Fixes [#226](https://github.com/acejump/AceJump/issues/226). Thanks [@AlexPl292](https://github.com/AlexPl292)!
- Update Pinyin engine. - Update Pinyin engine.
## 3.6.1 ## 3.6.1
- Fixes [#324](https://github.com/acejump/AceJump/issues/324). Thanks @AlexPl292! - Fixes [#324](https://github.com/acejump/AceJump/issues/324). Thanks [@AlexPl292](https://github.com/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.
@ -72,7 +121,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. - Honor camel humps [#315](https://github.com/acejump/AceJump/issues/315). Thanks to [@clojj](https://github.com/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,13 +1,20 @@
<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="http://jb.gg/badges/team.svg"></a> <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://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)
@ -28,7 +35,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. *This feature is unavailable in `3.6.4-3.8.4`.* - Press <kbd>Tab</kbd> when searching to jump to the next group of matches in the editor.
- 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.
@ -54,8 +61,6 @@ 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:
@ -64,15 +69,25 @@ 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<CR> map f <Action>(AceAction)
" Press `F` to activate Target Mode " Press `F` to activate Target Mode
map F :action AceTargetAction<CR> map F <Action>(AceTargetAction)
" Press `g` to activate Line Mode " Press `g` to activate Line Mode
map g :action AceLineAction<CR> map g <Action>(AceLineAction)
' >> ~/.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)
@ -171,31 +186,37 @@ 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/) |
| [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) | | [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/) |
| [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) | | [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) |
| [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) | | [emacsIDEAs](https://github.com/whunmr/emacsIDEAs) | [](https://plugins.jetbrains.com/plugin/7163-emacsideas) | [IntelliJ Platform](https://jetbrains.com) | :x: | [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/) | :heavy_check_mark: | [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/) |
| [Jumpy](https://github.com/DavidLGoldberg/jumpy) | [](https://atom.io/packages/jumpy) | [Atom](https://atom.io/) | :heavy_check_mark: | [CoffeeScript](http://coffeescript.org/) | | [Jumpy](https://github.com/DavidLGoldberg/jumpy) | [](https://atom.io/packages/jumpy) | [Atom](https://atom.io/) | :heavy_check_mark: | [TypeScript](https://www.typescriptlang.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/) | :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/) |
| [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/) |
| [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-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/) |
| [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.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/) |
| [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,73 +1,93 @@
import org.jetbrains.changelog.* import org.jetbrains.changelog.Changelog.OutputType.HTML
import org.jetbrains.intellij.tasks.* import org.jetbrains.changelog.date
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
idea apply true idea apply true
kotlin("jvm") version "1.6.0-RC2" kotlin("jvm") version "1.9.20-Beta"
id("org.jetbrains.intellij") version "1.2.1" id("org.jetbrains.intellij") version "1.15.0"
id("org.jetbrains.changelog") version "1.3.1" id("org.jetbrains.changelog") version "2.2.0"
id("com.github.ben-manes.versions") version "0.39.0" id("com.github.ben-manes.versions") version "0.48.0"
} }
tasks { tasks {
withType<KotlinCompile> { compileKotlin {
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString() kotlinOptions.jvmTarget = JavaVersion.VERSION_17.toString()
} }
named<Zip>("buildPlugin") { named<Zip>("buildPlugin") {
dependsOn("test") dependsOn("test")
archiveFileName.set("AceJump.zip") archiveFileName = "AceJump.zip"
} }
withType<RunIdeTask> { runIde {
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.set(intellijPublishToken) token = intellijPublishToken
} }
patchPluginXml { patchPluginXml {
sinceBuild.set("203.7717.56") sinceBuild = "223.7571.182"
changeNotes.set(provider { changeNotes = provider {
changelog.getAll().values.take(2).last().toHTML() changelog.renderItem(changelog.getAll().values.take(2).last(), HTML)
}) }
} }
runPluginVerifier { runPluginVerifier {
ideVersions.set(listOf("2021.2.1")) ideVersions = listOf("2023.2")
}
// 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.set("3.8.5") version = acejumpVersion
path.set("${project.projectDir}/CHANGES.md") path = "${project.projectDir}/CHANGES.md"
header.set(provider { "[${project.version}] - ${date()}" }) header = provider { "[${project.version}] - ${date()}" }
itemPrefix.set("-") itemPrefix = "-"
unreleasedTerm.set("Unreleased") unreleasedTerm = "Unreleased"
} }
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://jitpack.io")
} }
dependencies { dependencies {
// gradle-intellij-plugin doesn't attach sources properly for Kotlin :( // https://github.com/anyascii/anyascii
implementation(platform("org.jetbrains.kotlin:kotlin-bom")) implementation("com.anyascii:anyascii:0.3.2")
compileOnly(kotlin("stdlib-jdk8"))
implementation("com.anyascii:anyascii:0.3.0")
} }
intellij { intellij {
version.set("2021.2.1") version = "2023.2.1"
pluginName.set("AceJump") pluginName = "AceJump"
updateSinceUntilBuild.set(false) updateSinceUntilBuild = false
plugins.set(listOf("java")) plugins = listOf("java")
} }
group = "org.acejump" group = "org.acejump"
version = "3.8.5" version = acejumpVersion

1
gradle.properties Normal file
View File

@ -0,0 +1 @@
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-7.3-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -2,9 +2,11 @@ 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.*
/** /**
@ -127,18 +129,15 @@ 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 {
val firstVisibleLine = max(0, getVisualLineAtTopOfScreen() - 1) ApplicationManager.getApplication().assertIsDispatchThread()
val firstLine = visualLineToLogicalLine(firstVisibleLine) val rect = scrollingModel.visibleArea
val startOffset = getLineStartOffset(firstLine) val startPosition = xyToLogicalPosition(Point(rect.x, rect.y))
val visibleStart = logicalPositionToOffset(startPosition)
val height = getScreenHeight() + 2 val endPosition = xyToLogicalPosition(Point(rect.x + rect.width, rect.y + rect.height))
val lastLine = visualLineToLogicalLine(firstVisibleLine + height) val visibleEnd = logicalPositionToOffset(LogicalPosition(endPosition.line + 1, 0))
var endOffset = getLineEndOffset(lastLine, true) return visibleStart..visibleEnd
endOffset = normalizeOffset(lastLine, endOffset)
endOffset = min(max(0, document.textLength - 1), endOffset + 1)
return startOffset..endOffset
} }
/** /**

View File

@ -1,17 +1,30 @@
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.* import org.acejump.boundaries.StandardBoundaries.AFTER_CARET
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.* import org.acejump.input.JumpMode.DECLARATION
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.* import org.acejump.search.Pattern.ALL_WORDS
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
@ -19,25 +32,28 @@ 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.getData(EDITOR) != null action.presentation.isEnabled =
(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) ?: return val editor = e.getData(EDITOR) ?: (e.getData(LAST_ACTIVE_FILE_EDITOR) as? TextEditor)?.editor ?: return
val project = e.project val project = e.project
if (project != null) { if (project != null) {
try { try {
val openEditors = FileEditorManagerEx.getInstanceEx(project).splitters.selectedEditors val fem = FileEditorManager.getInstance(project) as FileEditorManagerEx
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))
} }
} }
@ -51,6 +67,13 @@ 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.
*/ */
@ -74,12 +97,17 @@ 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,22 +1,31 @@
package org.acejump.action package org.acejump.action
import com.intellij.openapi.actionSystem.* import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.actionSystem.IdeActions.* import com.intellij.openapi.actionSystem.AnAction
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.* import org.acejump.countMatchingCharacters
import org.acejump.immutableText
import org.acejump.input.JumpMode import org.acejump.input.JumpMode
import org.acejump.input.JumpMode.* import org.acejump.input.JumpMode.DECLARATION
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.
@ -28,7 +37,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
@ -95,12 +104,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 = FileEditorManagerEx.getInstanceEx(project) val fem = FileEditorManager.getInstance(project) as FileEditorManagerEx
val window = fem.windows.firstOrNull { (it.selectedEditor?.selectedWithProvider?.fileEditor as? TextEditor)?.editor === editor } val window = fem.windows.firstOrNull { (it.getSelectedComposite(false)?.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(forward: Boolean = true): Boolean { fun scroll(
val position = if (forward) findNextPosition() else findPreviousPosition() forward: Boolean = true,
return if (position != null) true.also { scrollTo(position) } else false position: LogicalPosition? = if (forward) findNextPosition() else findPreviousPosition()
} ) = 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,7 +2,6 @@ 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,12 +16,14 @@ 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,9 +30,7 @@ sealed class EditorOffsetCache {
*/ */
abstract fun offsetToXY(editor: Editor, offset: Int): Point abstract fun offsetToXY(editor: Editor, offset: Int): Point
companion object { companion object { fun new(): EditorOffsetCache = Cache() }
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
@ -45,17 +43,13 @@ 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).also { else Uncached.xyToOffset(editor, pos)
@Suppress("ReplacePutWithAssignment") .also { pointToOffset.put(pos, it) }
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).also { offsetToPoint.get(offset) ?: Uncached.offsetToXY(editor, offset)
@Suppress("ReplacePutWithAssignment") .also { offsetToPoint.put(offset, it) }
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 until editor.document.textLength 0..editor.document.textLength
override fun isOffsetInside(editor: Editor, offset: Int, cache: EditorOffsetCache) = override fun isOffsetInside(editor: Editor, offset: Int, cache: EditorOffsetCache) =
offset in (0 until editor.document.textLength) offset in (0..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() = ServiceManager.getService(AceConfig::class.java).aceSettings val settings get() = application.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.jumpModeColor val jumpModeColor get() = settings.getJumpModeJBC()
val jumpEndModeColor get() = settings.jumpEndModeColor val jumpEndModeColor get() = settings.getJumpEndModeJBC()
val targetModeColor get() = settings.targetModeColor val targetModeColor get() = settings.getTargetModeJBC()
val definitionModeColor get() = settings.definitionModeColor val definitionModeColor get() = settings.getDefinitionModeJBC()
val textHighlightColor get() = settings.textHighlightColor val textHighlightColor get() = settings.getTextHighlightJBC()
val tagForegroundColor get() = settings.tagForegroundColor val tagForegroundColor get() = settings.getTagForegroundJBC()
val tagBackgroundColor get() = settings.tagBackgroundColor val tagBackgroundColor get() = settings.getTagBackgroundJBC()
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 != settings.jumpModeColor || panel.jumpModeColor?.rgb != settings.jumpModeColor ||
panel.jumpEndModeColor != settings.jumpEndModeColor || panel.jumpEndModeColor?.rgb != settings.jumpEndModeColor ||
panel.targetModeColor != settings.targetModeColor || panel.targetModeColor?.rgb != settings.targetModeColor ||
panel.definitionModeColor != settings.definitionModeColor || panel.definitionModeColor?.rgb != settings.definitionModeColor ||
panel.textHighlightColor != settings.textHighlightColor || panel.textHighlightColor?.rgb != settings.textHighlightColor ||
panel.tagForegroundColor != settings.tagForegroundColor || panel.tagForegroundColor?.rgb != settings.tagForegroundColor ||
panel.tagBackgroundColor != settings.tagBackgroundColor || panel.tagBackgroundColor?.rgb != 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 } panel.jumpModeColor?.let { settings.jumpModeColor = it.rgb }
panel.jumpEndModeColor?.let { settings.jumpEndModeColor = it } panel.jumpEndModeColor?.let { settings.jumpEndModeColor = it.rgb }
panel.targetModeColor?.let { settings.targetModeColor = it } panel.targetModeColor?.let { settings.targetModeColor = it.rgb }
panel.definitionModeColor?.let { settings.definitionModeColor = it } panel.definitionModeColor?.let { settings.definitionModeColor = it.rgb }
panel.textHighlightColor?.let { settings.textHighlightColor = it } panel.textHighlightColor?.let { settings.textHighlightColor = it.rgb }
panel.tagForegroundColor?.let { settings.tagForegroundColor = it } panel.tagForegroundColor?.let { settings.tagForegroundColor = it.rgb }
panel.tagBackgroundColor?.let { settings.tagBackgroundColor = it } panel.tagBackgroundColor?.let { settings.tagBackgroundColor = it.rgb }
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,11 +1,8 @@
package org.acejump.config package org.acejump.config
import com.intellij.util.xmlb.Converter import com.intellij.ui.JBColor
import com.intellij.util.xmlb.annotations.OptionTag import org.acejump.input.*
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,
@ -16,35 +13,31 @@ data class AceSettings(
var cycleMode4: JumpMode = JumpMode.JUMP_END, var cycleMode4: JumpMode = JumpMode.JUMP_END,
var minQueryLength: Int = 1, var minQueryLength: Int = 1,
@OptionTag("jumpModeRGB", converter = ColorConverter::class) var jumpModeColor: Int = 0xFFFFFF,
var jumpModeColor: Color = Color(0xFFFFFF),
@OptionTag("jumpEndModeRGB", converter = ColorConverter::class) var jumpEndModeColor: Int = 0x33E78A,
var jumpEndModeColor: Color = Color(0x33E78A),
@OptionTag("targetModeRGB", converter = ColorConverter::class) var targetModeColor: Int = 0xFFB700,
var targetModeColor: Color = Color(0xFFB700),
@OptionTag("definitionModeRGB", converter = ColorConverter::class) var definitionModeColor: Int = 0x6FC5FF,
var definitionModeColor: Color = Color(0x6FC5FF),
@OptionTag("textHighlightRGB", converter = ColorConverter::class) var textHighlightColor: Int = 0x394B58,
var textHighlightColor: Color = Color(0x394B58),
@OptionTag("tagForegroundRGB", converter = ColorConverter::class) var tagForegroundColor: Int = 0xFFFFFF,
var tagForegroundColor: Color = Color(0xFFFFFF),
@OptionTag("tagBackgroundRGB", converter = ColorConverter::class) var tagBackgroundColor: Int = 0x008299,
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)
internal class ColorConverter: Converter<Color>() { fun getJumpEndModeJBC() = JBColor.namedColor("jumpEndModeRGB", jumpEndModeColor)
override fun toString(value: Color) = value.rgb.toString() fun getTargetModeJBC() = JBColor.namedColor("targetModeRGB", targetModeColor)
override fun fromString(value: String) = value.toIntOrNull()?.let(::Color) fun getDefinitionModeJBC() = JBColor.namedColor("definitionModeRGB", definitionModeColor)
fun getTextHighlightJBC() = JBColor.namedColor("textHighlightRGB", textHighlightColor)
fun getTagForegroundJBC() = JBColor.namedColor("tagForegroundRGB", tagForegroundColor)
fun getTagBackgroundJBC() = JBColor.namedColor("tagBackgroundRGB", tagBackgroundColor)
} }

View File

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

View File

@ -61,20 +61,19 @@ enum class JumpMode {
*/ */
DECLARATION; DECLARATION;
val caretColor: Color val caretColor: Color get() = when (this) {
get() = when (this) { DISABLED -> AbstractColorsScheme.INHERITED_COLOR_MARKER
JUMP -> AceConfig.jumpModeColor JUMP -> AceConfig.jumpModeColor
JUMP_END -> AceConfig.jumpEndModeColor JUMP_END -> AceConfig.jumpEndModeColor
DECLARATION -> AceConfig.definitionModeColor TARGET -> AceConfig.targetModeColor
TARGET -> AceConfig.targetModeColor DECLARATION -> AceConfig.definitionModeColor
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,42 +19,43 @@ 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"), LINE_STARTS("^.|^\\n|(?<!.)\\Z"),
LINE_ENDS("\\n|\\Z"), LINE_ENDS("\\n|\\Z"),
LINE_INDENTS("[^\\s].*|^\\n"), LINE_INDENTS("[^\\s].*|^\\n|(?<!.)\\Z"),
LINE_ALL_MARKS(LINE_ENDS.regex + "|" + LINE_STARTS.regex + "|" + LINE_INDENTS.regex), LINE_ALL_MARKS(listOf(LINE_ENDS, LINE_STARTS, LINE_INDENTS).flatMap { it.regex.split("|") }.distinct().joinToString("|")),
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.canQueryMatchAnyTag(newQuery) val canMatchTag = tagger.canQueryMatchAnyVisibleTag(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) = 1 override fun getHighlightLength(text: CharSequence, offset: Int) = 0
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,7 +187,10 @@ 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,13 +5,10 @@ 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.ExternalUsage import org.acejump.*
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
@ -143,24 +140,23 @@ 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 =
return query.endsWith(key, true) && isTagCompatibleWithQuery(key, value, query) 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 =
return tag.editor.immutableText.matchesAt(tag.offset, getPlaintextPortion(query, marker), ignoreCase = true) 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 =
return tagMap.inverse()[tag].let { it != null && isTagCompatibleWithQuery(it, tag, query) } tagMap.inverse()[tag].let { it != null && isTagCompatibleWithQuery(it, tag, query) }
}
fun canQueryMatchAnyTag(query: String): Boolean { fun canQueryMatchAnyVisibleTag(query: String): Boolean =
return tagMap.any { (tag, offset) -> tagMap.any { (label, tag) ->
val tagPortion = getTagPortion(query, tag) val tagPortion = getTagPortion(query, label)
tagPortion.isNotEmpty() && tag.startsWith(tagPortion, ignoreCase = true) && isTagCompatibleWithQuery(tag, offset, query) tagPortion.isNotEmpty()
&& 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,7 +10,6 @@ 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 {
@ -20,12 +19,10 @@ 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
} }
@ -37,6 +34,5 @@ internal data class EditorSettings(
settings.isBlockCursor = isBlockCursor settings.isBlockCursor = isBlockCursor
settings.isBlinkCaret = isBlinkCaret settings.isBlinkCaret = isBlinkCaret
document.setReadOnly(isReadOnly)
} }
} }

View File

@ -81,6 +81,10 @@ 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'
}
} }
/** /**
@ -106,7 +110,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 == 0 || editor.immutableText[offsetL - 1].let { it == '\n' || it == '\r' }) { if (hasSpaceRight || offsetL !in 1 until editor.document.textLength || isLineEnding(editor.immutableText[offsetL - 1])) {
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) }
} }
@ -124,7 +128,15 @@ 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,6 +9,7 @@ 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.*
@ -31,7 +32,7 @@ internal class TextHighlighter {
/** /**
* Label for the search notification. * Label for the search notification.
*/ */
private class NotificationLabel constructor(text: String?): JLabel(text) { private class NotificationLabel(text: String?): JLabel(text) {
init { init {
background = HintUtil.getInformationColor() background = HintUtil.getInformationColor()
foreground = JBColor.foreground() foreground = JBColor.foreground()
@ -61,9 +62,7 @@ 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
try { DocumentUtil.executeInBulk(document, enableBulkEditing) {
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)
@ -72,8 +71,6 @@ 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
} }
} }
@ -96,58 +93,64 @@ internal class TextHighlighter {
previousHint?.hide() previousHint?.hide()
// add notification hint to first editor // add notification hint to first editor
results.keys.first().let { val editor = results.keys.first()
val component: JComponent = it.component val component: JComponent = editor.component
val label1: JLabel = NotificationLabel(" " + val label1 = NotificationLabel(
CodeInsightBundle.message("incremental.search.tooltip.prefix")) " " +
label1.font = UIUtil.getLabelFont().deriveFont(Font.BOLD) CodeInsightBundle.message("incremental.search.tooltip.prefix")
).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
) )
val panel = JPanel(BorderLayout()).apply { preferredSize = Dimension(
add(label1, BorderLayout.WEST) editor.contentComponent.width +
add(label2, BorderLayout.CENTER) label1.preferredSize.width, preferredSize.height
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.keys.forEach { it.markupModel.removeAllHighlighters() } previousHighlights.forEach { (editor, highlighters) ->
highlighters.forEach(editor.markupModel::removeHighlighter)
}
previousHighlights.clear() previousHighlights.clear()
previousHint?.hide() previousHint?.hide()
} }

View File

@ -20,27 +20,38 @@
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>
@ -55,6 +66,12 @@
<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" xmlns:serif="http://www.serif.com/" 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" 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\n") makeEditor(" test\n three\n lines")
takeAction(AceAction.StartAllLineMarksMode()) takeAction(AceAction.StartAllLineMarksMode())
assertEquals(8, session.tags.size) // last empty line does not count assertEquals(9, session.tags.size)
} }
fun `test chinese selection`() { fun `test chinese selection`() {

View File

@ -1,5 +1,7 @@
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
@ -41,12 +43,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")
myManager.openFile(fileA, true) manager?.openFile(fileA, true)
myManager.openFile(fileB, false) manager?.openFile(fileB, false)
val mainEditor = (myManager.selectedEditor as TextEditor).editor val mainEditor = (manager?.selectedEditor as TextEditor).editor
val editorA = (myManager.getEditors(fileA).single() as TextEditor).editor val editorA = (manager?.getEditors(fileA)?.single() as TextEditor).editor
val editorB = (myManager.getEditors(fileB).single() as TextEditor).editor val editorB = (manager?.getEditors(fileB)?.single() as TextEditor).editor
val session = SessionManager.start(mainEditor, listOf(editorA, editorB)) val session = SessionManager.start(mainEditor, listOf(editorA, editorB))
@ -85,7 +87,7 @@ class ExternalUsageTest: BaseTest() {
SessionManager.start(myFixture.editor) SessionManager.start(myFixture.editor)
.startRegexSearch("[aeiou]+", WHOLE_FILE) .startRegexSearch("[aeiou]+", WHOLE_FILE)
TestCase.assertEquals(8, session.tags.size) TestCase.assertEquals(9, session.tags.size)
} }
fun `test external jump with bounds`() { fun `test external jump with bounds`() {
@ -166,4 +168,21 @@ 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,7 +7,6 @@ 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)
} }
myManager.closeAllFiles() manager?.closeAllFiles()
} }
fun typeAndWaitForResults(string: String) { fun typeAndWaitForResults(string: String) {