1
0
mirror of https://github.com/chylex/IntelliJ-IdeaVim.git synced 2025-08-17 16:31:45 +02:00

Compare commits

...

30 Commits
0.48 ... 0.49

Author SHA1 Message Date
Andrey Vlasovskikh
942b64052d Inherit from VimTestCase to setup IntelliJ extension points properly
Otherwise these tests depend on the run order of other tests for
proper initialization.
2017-12-12 20:17:49 +03:00
Andrey Vlasovskikh
559aabd6b8 Version 0.49 2017-12-12 19:55:08 +03:00
Andrey Vlasovskikh
a76b41b737 VIM-1367 Fixed resetting the default value
The previous fix tried to parse the current value instead of the default
one.
2017-11-03 05:00:29 +03:00
Andrey Vlasovskikh
2fc6553203 VIM-1367 Correctly reset parsed and stored 'iskeyword' option value 2017-11-03 04:26:46 +03:00
Andrey Vlasovskikh
98b003e601 VIM-1367 Deterministic order of options for reproducible tests 2017-11-03 04:23:29 +03:00
Andrey Vlasovskikh
0dda443cc8 Added iskeyword option to the list of supported set commands 2017-11-03 03:59:13 +03:00
Andrey Vlasovskikh
9322283cb1 Updated changelog 2017-11-03 03:56:00 +03:00
Andrey Vlasovskikh
95d412c78d Added nickgieschen to contributors 2017-11-03 03:54:06 +03:00
Andrey Vlasovskikh
6245b15d8f Cleanup 2017-11-03 03:48:15 +03:00
Andrey Vlasovskikh
ab1d7ba6cb VIM-1367 Removed unnecessary repetition in positive lookbehind
It resulted in an inspection warning that positive lookbehind groups
cannot contain 1 or more repetition patterns.
2017-11-03 03:34:11 +03:00
nickgieschen
ef05491991 VIM-1367 Implement iskeyword
(cherry picked from commit d91d38c)
2017-11-03 03:22:39 +03:00
Andrey Vlasovskikh
113642c8f5 Fixed test configuration URL 2017-11-01 03:15:05 +03:00
Andrey Vlasovskikh
088dd98e0d Updated test configuration ID 2017-11-01 03:14:23 +03:00
Andrey Vlasovskikh
7e0046a715 Updated changelog 2017-11-01 03:00:40 +03:00
Andrey Vlasovskikh
1a11d5df35 Added tieTYT to the list of contributors 2017-11-01 02:58:06 +03:00
tieTYT
57b5b319a7 VIM-523 Fixed global mark remembering only the line number
Bear with me as this is the first thing I've ever done with
Intellij-IDEA plugin development.

I tested this and I believe I fixed the problem.  The cause of the
problem was that the code was checking if the mark was in a different
file but if it was, it was using the editor of the current file to go
to the line of the mark.  I changed the code so that it opens the file
of the mark first, then jumps to its line number.

I need a VirtualFile so that I can get the Editor to open. The Mark
stores the path of the file it's in, but the path is not enough
information to get a VirtualFile.  I also need the "protocol" of the
file.  So, I had to change the structure of the Mark and add a
"protocol" field to it.

I had to update the save/load logic to use this new field, too.  This
way, when you restart Intellij-IDEA, the marks can still be used.  For
old marks, I defaulted the "protocol" to the value of "file".

One thing I couldn't figure out how to do is add a test case to check
that this is working correctly.  This is not due to a lack of effort.
In fact, I tried to write the test case first.  But I have been unable
to find any examples anywhere of testing multiple Editors, and that's
what's involved to fix this issue.  Because of this, this issue may be
best used as a reference to fix the problem instead of worthy of being
used in production.  Either way, I'd love to know how to write such a
test.
2017-11-01 02:35:23 +03:00
Andrey Vlasovskikh
0a4672c050 Updated intellij-gradle-plugin, Kotlin, and IntelliJ platform versions 2017-11-01 02:12:07 +03:00
Andrey Vlasovskikh
8808b651e2 Updated gradle wrapper to 4.3 2017-11-01 02:12:07 +03:00
Andrey Vlasovskikh
e9fca757b7 JetBrains project badge 2017-09-08 23:09:46 +03:00
Andrey Vlasovskikh
98a3801f6a New code style settings format of IntelliJ 2017.3 2017-09-08 23:06:24 +03:00
Andrey Vlasovskikh
49ecfd6879 Added Pavel Fatin to contributors 2017-01-16 01:03:42 +03:00
Andrey Vlasovskikh
4d4b5967da Updated CHANGES 2017-01-16 01:02:47 +03:00
Andrey Vlasovskikh
a882e37d04 Merge remote-tracking branch 'origin/vim-1007'
# Conflicts:
#	gradle.properties
#	resources/META-INF/plugin.xml
#	src/com/maddyhome/idea/vim/VimTypedActionHandler.java
2017-01-16 00:57:31 +03:00
Andrey Vlasovskikh
4734d23e29 Fixed compilation by adding Kotlin Gradle plugin 2017-01-16 00:42:55 +03:00
Andrey Vlasovskikh
b7416da26d Merge branch 'kotlin'
# Conflicts:
#	build.gradle
#	gradle.properties
2017-01-16 00:30:30 +03:00
Andrey Vlasovskikh
36e768ab37 Allow Java 8 2017-01-16 00:27:51 +03:00
Andrey Vlasovskikh
ede0bd8623 Set minimal version to 2017.1 in order to use new API for zero-latency typing 2017-01-16 00:25:47 +03:00
Andrey Vlasovskikh
b4072eb62d Use gradle-intellij-plugin 0.2.0 2017-01-15 23:36:27 +03:00
Andrey Vlasovskikh
3344bb3254 Ability to use Kotlin along with Java 2016-11-21 19:40:14 +03:00
Pavel Fatin
6b9ab7163a Support for zero-latency rendering, #VIM-1007 fixed 2016-10-26 12:53:13 +02:00
27 changed files with 859 additions and 111 deletions

235
.idea/codeStyles/Project.xml generated Normal file
View File

@@ -0,0 +1,235 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<option name="OTHER_INDENT_OPTIONS">
<value>
<option name="INDENT_SIZE" value="4" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="false" />
<option name="SMART_TABS" value="false" />
<option name="LABEL_INDENT_SIZE" value="0" />
<option name="LABEL_INDENT_ABSOLUTE" value="false" />
<option name="USE_RELATIVE_INDENTS" value="false" />
</value>
</option>
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="BLOCK_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
<option name="SPACE_AFTER_TYPE_CAST" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="5" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
<JavaCodeStyleSettings>
<option name="FIELD_NAME_PREFIX" value="my" />
<option name="STATIC_FIELD_NAME_PREFIX" value="our" />
</JavaCodeStyleSettings>
<XML>
<option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
</XML>
<ADDITIONAL_INDENT_OPTIONS fileType="rb">
<option name="INDENT_SIZE" value="2" />
</ADDITIONAL_INDENT_OPTIONS>
<codeStyleSettings language="CFML">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="ECMA Script Level 4">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="GSP">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="Groovy">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="SPACE_AFTER_TYPE_CAST" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="5" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="HTML">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="8" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="LINE_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="BLOCK_COMMENT_AT_FIRST_COLUMN" value="false" />
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_ASSIGNMENT" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_THROWS_LIST" value="true" />
<option name="ALIGN_MULTILINE_EXTENDS_LIST" value="true" />
<option name="ALIGN_MULTILINE_PARENTHESIZED_EXPRESSION" value="true" />
<option name="SPACE_AFTER_TYPE_CAST" value="false" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="5" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="8" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JSON">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="JSP">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="8" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
<option name="ALIGN_MULTILINE_BINARY_OPERATION" value="true" />
<option name="ALIGN_MULTILINE_TERNARY_OPERATION" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="5" />
<option name="BINARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="TERNARY_OPERATION_SIGNS_ON_NEXT_LINE" value="true" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="ASSIGNMENT_WRAP" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="Python">
<option name="KEEP_LINE_BREAKS" value="false" />
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="SQL">
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
</codeStyleSettings>
<codeStyleSettings language="XML">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="TAB_SIZE" value="8" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

5
.idea/codeStyles/codeStyleConfig.xml generated Normal file
View File

@@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@@ -40,6 +40,9 @@ Contributors:
* [Aleksey Lagoshin](mailto:aleksey@pri-num.com)
* [Paulo Bu](mailto:pbu_98@yahoo.com)
* [Giorgos Gaganis](mailto:gaganis@yahoo.com)
* [Pavel Fatin](mailto:pavel.fatin@jetbrains.com)
* [tieTYT](mailto:tietyt@gmail.com)
* [Nick Gieschen](mailto:nickgieschen@gmail.com)
If you are a contributor and your name is not listed here, feel free to
contact the maintainer.

View File

@@ -17,6 +17,16 @@ Please note that the quality of EAP versions may at times be way below even
usual beta standards.
0.49, 2017-12-12
----------------
Enabled zero-latency typing for Vim emulation. Added support for `iskeyword` option. Various bug fixes.
* [VIM-1254](https://youtrack.jetbrains.com/issue/VIM-1254) Enable zero-latency typing for Vim emulation
* [VIM-1367](https://youtrack.jetbrains.com/issue/VIM-1367) Support `iskeyword` option
* [VIM-523](https://youtrack.jetbrains.com/issue/VIM-523) Fixed global mark remembering only the line number
0.48, 2017-01-15
----------------
@@ -28,6 +38,11 @@ Bug fixes:
* [VIM-1216](https://youtrack.jetbrains.com/issue/VIM-1216) Fixed `.` resetting the last find movement while repeating change that also uses movement
Features:
* Support for zero-latency rendering
0.47, 2016-10-19
----------------

View File

@@ -1,6 +1,12 @@
IdeaVim
=======
<div>
<a href="https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub">
<img src="http://jb.gg/badges/official.svg" alt="official JetBrains project"/>
</a>
</div>
<div>
<a href="http://teamcity.jetbrains.com/viewType.html?buildTypeId=IdeaVim_Build&guest=1">
<img src="http://teamcity.jetbrains.com/app/rest/builds/buildType:(id:IdeaVim_Build)/statusIcon.svg?guest=1"/>
@@ -9,8 +15,8 @@ IdeaVim
</div>
<div>
<a href="http://teamcity.jetbrains.com/viewType.html?buildTypeId=IdeaVim_TestsForIntelliJ15&guest=1">
<img src="http://teamcity.jetbrains.com/app/rest/builds/buildType:(id:IdeaVim_TestsForIntelliJ15)/statusIcon.svg?guest=1"/>
<a href="http://teamcity.jetbrains.com/viewType.html?buildTypeId=IdeaVim_TestsForIntelliJ20172&guest=1">
<img src="http://teamcity.jetbrains.com/app/rest/builds/buildType:(id:IdeaVim_TestsForIntelliJ20172)/statusIcon.svg?guest=1"/>
</a>
<span>Tests</span>
</div>

View File

@@ -1,20 +1,19 @@
buildscript {
repositories {
mavenCentral()
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
maven {
url 'http://dl.bintray.com/jetbrains/intellij-plugin-service'
}
}
dependencies {
classpath "org.jetbrains.intellij.plugins:gradle-intellij-plugin:0.2.0-SNAPSHOT"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
}
apply plugin: 'org.jetbrains.intellij'
plugins {
id 'org.jetbrains.intellij' version '0.2.17'
}
apply plugin: 'java'
apply plugin: 'kotlin'
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
@@ -37,9 +36,18 @@ intellij {
updateSinceUntilBuild false
downloadSources Boolean.valueOf(downloadIdeaSources)
publish {
publishPlugin {
channels publishChannels.split(',')
username publishUsername
password publishPassword
}
}
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
compile "org.jetbrains.kotlin:kotlin-runtime:$kotlinVersion"
}

View File

@@ -9,6 +9,7 @@ The following `:set` commands can appear in `~/.ideavimrc` or set manually in th
'history' 'hi' number of command-lines that are remembered
'hlsearch' 'hls' highlight matches with last search pattern
'ignorecase' 'ic' ignore case in search patterns
'iskeyword' 'isk' defines keywords for commands like 'w', '*', etc.
'incsearch' 'is' show where search pattern typed so far matches
'matchpairs' 'mps' pairs of characters that "%" can match
'nrformats' 'nf' number formats recognized for CTRL-A command

View File

@@ -1,7 +1,8 @@
ideaVersion IC-15.0.5
ideaVersion IC-172-EAP-SNAPSHOT
downloadIdeaSources true
version SNAPSHOT
javaVersion 1.6
javaVersion 1.8
kotlinVersion 1.1.51
publishUsername username
publishPassword password
publishChannels eap

Binary file not shown.

View File

@@ -1,6 +1,6 @@
#Sat Jan 23 00:00:00 MSK 2016
#Tue Oct 31 23:32:54 MSK 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-4.3-all.zip

100
gradlew vendored
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
##############################################################################
##
@@ -6,42 +6,6 @@
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
@@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -85,7 +89,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -150,11 +154,19 @@ if $cygwin ; then
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
APP_ARGS=$(save "$@")
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

14
gradlew.bat vendored
View File

@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,10 +46,9 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line

View File

@@ -2,6 +2,12 @@
<name>IdeaVim</name>
<id>IdeaVIM</id>
<change-notes><![CDATA[
<p>0.49:</p>
<ul>
<li>Enabled zero-latency typing for Vim emulation</li>
<li>Support for <code>iskeyword</code> option</li>
<li>Various bug fixes</li>
</ul>
<p>0.48:</p>
<ul>
<li>Various bug fixes</li>
@@ -40,7 +46,7 @@
<version>SNAPSHOT</version>
<vendor>JetBrains</vendor>
<idea-version since-build="143.0"/>
<idea-version since-build="171.0"/>
<!-- Mark the plugin as compatible with RubyMine and other products based on the IntelliJ platform -->
<depends>com.intellij.modules.lang</depends>

View File

@@ -25,6 +25,7 @@ import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.actionSystem.ActionPlan;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
import com.intellij.openapi.project.Project;
@@ -92,6 +93,26 @@ public class KeyHandler {
return origHandler;
}
/**
* Invoked before acquiring a write lock and actually handling the keystroke.
*
* Drafts an optional {@link ActionPlan} that will be used as a base for zero-latency rendering in editor.
*
* @param editor The editor the key was typed into
* @param key The keystroke typed by the user
* @param context The data context
* @param plan The current action plan
*/
public void beforeHandleKey(@NotNull Editor editor, @NotNull KeyStroke key,
@NotNull DataContext context, @NotNull ActionPlan plan) {
final CommandState.Mode mode = CommandState.getInstance(editor).getMode();
if (mode == CommandState.Mode.INSERT || mode == CommandState.Mode.REPLACE) {
VimPlugin.getChange().beforeProcessKey(editor, context, key, plan);
}
}
/**
* This is the main key handler for the Vim plugin. Every keystroke not handled directly by Idea is sent here for
* processing.

View File

@@ -22,8 +22,10 @@ import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.actionSystem.ActionPlan;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
import com.intellij.openapi.editor.actionSystem.TypedActionHandlerEx;
import com.maddyhome.idea.vim.helper.EditorDataContext;
import org.jetbrains.annotations.NotNull;
@@ -34,7 +36,7 @@ import javax.swing.*;
*
* IDE shortcut keys used by Vim commands are handled by {@link com.maddyhome.idea.vim.action.VimShortcutKeyAction}.
*/
public class VimTypedActionHandler implements TypedActionHandler {
public class VimTypedActionHandler implements TypedActionHandlerEx {
private static final Logger logger = Logger.getInstance(VimTypedActionHandler.class.getName());
private final TypedActionHandler origHandler;
@@ -46,6 +48,19 @@ public class VimTypedActionHandler implements TypedActionHandler {
handler.setOriginalHandler(origHandler);
}
@Override
public void beforeExecute(@NotNull Editor editor, char charTyped, @NotNull DataContext context, @NotNull ActionPlan plan) {
if (isEnabled(editor)) {
handler.beforeHandleKey(editor, KeyStroke.getKeyStroke(charTyped), context, plan);
}
else {
TypedActionHandler originalHandler = KeyHandler.getInstance().getOriginalHandler();
if (originalHandler instanceof TypedActionHandlerEx) {
((TypedActionHandlerEx)originalHandler).beforeExecute(editor, charTyped, context, plan);
}
}
}
@Override
public void execute(@NotNull final Editor editor, final char charTyped, @NotNull final DataContext context) {
if (isEnabled(editor)) {

8
src/com/maddyhome/idea/vim/common/Mark.java Normal file → Executable file
View File

@@ -35,10 +35,11 @@ public class Mark extends FileLocation {
* @param col The column within the line
* @param filename The file being marked
*/
public Mark(char key, int lline, int col, String filename) {
public Mark(char key, int lline, int col, String filename, String protocol) {
super(lline, col, filename);
this.key = key;
this.protocol = protocol;
}
/**
@@ -50,6 +51,10 @@ public class Mark extends FileLocation {
return key;
}
public String getProtocol() {
return protocol;
}
public boolean equals(@Nullable Object object) {
if (object instanceof Mark) {
if (((Mark)object).key == key) {
@@ -82,4 +87,5 @@ public class Mark extends FileLocation {
}
private final char key;
private final String protocol;
}

View File

@@ -29,6 +29,9 @@ import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.UndoConfirmationPolicy;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.ActionPlan;
import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
import com.intellij.openapi.editor.actionSystem.TypedActionHandlerEx;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.editor.impl.TextRangeInterval;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -598,6 +601,26 @@ public class ChangeGroup {
clearStrokes(editor);
}
/**
* Drafts an {@link ActionPlan} for preemptive rendering before "regular" keystroke processing in insert/replace mode.
*
* Like {@link #processKey(Editor, DataContext, KeyStroke)}, delegates the task to the original handler.
*
* @param editor The editor the character was typed into
* @param context The data context
* @param key The user entered keystroke
* @param plan the current action plan draft
*/
public void beforeProcessKey(@NotNull final Editor editor, @NotNull final DataContext context,
@NotNull final KeyStroke key, @NotNull ActionPlan plan) {
final TypedActionHandler originalHandler = KeyHandler.getInstance().getOriginalHandler();
if (originalHandler instanceof TypedActionHandlerEx) {
((TypedActionHandlerEx)originalHandler).beforeExecute(editor, key.getKeyChar(), context, plan);
}
}
/**
* This processes all "regular" keystrokes entered while in insert/replace mode
*

18
src/com/maddyhome/idea/vim/group/MarkGroup.java Normal file → Executable file
View File

@@ -31,6 +31,7 @@ import com.intellij.openapi.editor.event.EditorFactoryEvent;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.maddyhome.idea.vim.EventFacade;
import com.maddyhome.idea.vim.VimPlugin;
import com.maddyhome.idea.vim.command.Command;
@@ -100,13 +101,13 @@ public class MarkGroup {
int offset = SearchHelper.findNextParagraph(editor, ch == '{' ? -1 : 1, false);
offset = EditorHelper.normalizeOffset(editor, offset, false);
LogicalPosition lp = editor.offsetToLogicalPosition(offset);
mark = new Mark(ch, lp.line, lp.column, vf.getPath());
mark = new Mark(ch, lp.line, lp.column, vf.getPath(), extractProtocol(vf));
}
else if ("()".indexOf(ch) >= 0 && vf != null) {
int offset = SearchHelper.findNextSentenceStart(editor, ch == '(' ? -1 : 1, false, true);
offset = EditorHelper.normalizeOffset(editor, offset, false);
LogicalPosition lp = editor.offsetToLogicalPosition(offset);
mark = new Mark(ch, lp.line, lp.column, vf.getPath());
mark = new Mark(ch, lp.line, lp.column, vf.getPath(), extractProtocol(vf));
}
// If this is a file mark, get the mark from this file
else if (FILE_MARKS.indexOf(ch) >= 0) {
@@ -200,7 +201,7 @@ public class MarkGroup {
return false;
}
Mark mark = new Mark(ch, lp.line, lp.column, vf.getPath());
Mark mark = new Mark(ch, lp.line, lp.column, vf.getPath(), extractProtocol(vf));
// File specific marks get added to the file
if (FILE_MARKS.indexOf(ch) >= 0) {
HashMap<Character, Mark> fmarks = getFileMarks(editor.getDocument());
@@ -225,6 +226,10 @@ public class MarkGroup {
return true;
}
private String extractProtocol(VirtualFile vf) {
return VirtualFileManager.extractProtocol(vf.getUrl());
}
public void setVisualSelectionMarks(@NotNull Editor editor, @NotNull TextRange range) {
setMark(editor, MARK_VISUAL_START, range.getStartOffset());
setMark(editor, MARK_VISUAL_END, range.getEndOffset());
@@ -397,6 +402,7 @@ public class MarkGroup {
markElem.setAttribute("line", Integer.toString(mark.getLogicalLine()));
markElem.setAttribute("column", Integer.toString(mark.getCol()));
markElem.setAttribute("filename", StringUtil.notNullize(mark.getFilename()));
markElem.setAttribute("protocol", StringUtil.notNullize(mark.getProtocol(), "file"));
marksElem.addContent(markElem);
if (logger.isDebugEnabled()) {
logger.debug("saved mark = " + mark);
@@ -473,7 +479,8 @@ public class MarkGroup {
Mark mark = new Mark(markElem.getAttributeValue("key").charAt(0),
Integer.parseInt(markElem.getAttributeValue("line")),
Integer.parseInt(markElem.getAttributeValue("column")),
markElem.getAttributeValue("filename"));
markElem.getAttributeValue("filename"),
markElem.getAttributeValue("protocol"));
globalMarks.put(mark.getKey(), mark);
HashMap<Character, Mark> fmarks = getFileMarks(mark.getFilename());
@@ -506,7 +513,8 @@ public class MarkGroup {
Mark mark = new Mark(markElem.getAttributeValue("key").charAt(0),
Integer.parseInt(markElem.getAttributeValue("line")),
Integer.parseInt(markElem.getAttributeValue("column")),
filename);
filename,
markElem.getAttributeValue("protocol"));
fmarks.put(mark.getKey(), mark);
}

31
src/com/maddyhome/idea/vim/group/MotionGroup.java Normal file → Executable file
View File

@@ -23,14 +23,13 @@ import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.*;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.*;
import com.intellij.openapi.fileEditor.impl.EditorTabbedContainer;
import com.intellij.openapi.fileEditor.impl.EditorWindow;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.maddyhome.idea.vim.EventFacade;
import com.maddyhome.idea.vim.KeyHandler;
import com.maddyhome.idea.vim.VimPlugin;
@@ -400,7 +399,7 @@ public class MotionGroup {
}
final int line = mark.getLogicalLine();
if (!vf.getPath().equals(mark.getFilename())) {
final Editor selectedEditor = selectEditor(editor, vf);
final Editor selectedEditor = selectEditor(editor, mark);
if (selectedEditor != null) {
moveCaret(selectedEditor, moveCaretToLineStartSkipLeading(selectedEditor, line));
}
@@ -435,7 +434,7 @@ public class MotionGroup {
}
final LogicalPosition lp = new LogicalPosition(mark.getLogicalLine(), mark.getCol());
if (!vf.getPath().equals(mark.getFilename())) {
final Editor selectedEditor = selectEditor(editor, vf);
final Editor selectedEditor = selectEditor(editor, mark);
if (selectedEditor != null) {
moveCaret(selectedEditor, selectedEditor.logicalPositionToOffset(lp));
}
@@ -498,6 +497,26 @@ public class MotionGroup {
}
}
@Nullable
private Editor selectEditor(@NotNull Editor editor, @NotNull Mark mark) {
final VirtualFile virtualFile = markToVirtualFile(mark);
if (virtualFile != null) {
return selectEditor(editor, virtualFile);
} else {
return null;
}
}
@Nullable
private VirtualFile markToVirtualFile(@NotNull Mark mark) {
String protocol = mark.getProtocol();
VirtualFileSystem fileSystem = VirtualFileManager.getInstance().getFileSystem(protocol);
if (mark.getFilename() == null) {
return null;
}
return fileSystem.findFileByPath(mark.getFilename());
}
@Nullable
private Editor selectEditor(@NotNull Editor editor, @NotNull VirtualFile file) {
return VimPlugin.getFile().selectEditor(editor.getProject(), file);

View File

@@ -18,6 +18,8 @@
package com.maddyhome.idea.vim.helper;
import com.maddyhome.idea.vim.option.KeywordOption;
import com.maddyhome.idea.vim.option.Options;
import org.jetbrains.annotations.NotNull;
/**
@@ -25,8 +27,8 @@ import org.jetbrains.annotations.NotNull;
*/
public class CharacterHelper {
public static enum CharacterType {
LETTER_OR_DIGIT,
public enum CharacterType {
KEYWORD,
HIRAGANA,
KATAKANA,
HALF_WIDTH_KATAKANA,
@@ -41,7 +43,7 @@ public class CharacterHelper {
/**
* This returns the type of the supplied character. The logic is as follows:<br>
* If the character is whitespace, <code>WHITESPACE</code> is returned.<br>
* If the punctuation is being skipped or the character is a letter, digit, or underscore, <code>LETTER_OR_DIGIT</code>
* If the punctuation is being skipped or the character is a letter, digit, or underscore, <code>KEYWORD</code>
* is returned.<br>
* Otherwise <code>PUNCTUATION</code> is returned.
*
@@ -64,8 +66,8 @@ public class CharacterHelper {
else if (isHalfWidthKatakanaLetter(ch)) {
return CharacterType.HALF_WIDTH_KATAKANA;
}
else if (punctuationAsLetters || Character.isLetterOrDigit(ch) || ch == '_') {
return CharacterType.LETTER_OR_DIGIT;
else if (punctuationAsLetters || ((KeywordOption)Options.getInstance().getOption("iskeyword")).isKeyword(ch)) {
return CharacterType.KEYWORD;
}
else {
return CharacterType.PUNCTUATION;

View File

@@ -874,7 +874,7 @@ public class SearchHelper {
int pos = editor.getCaretModel().getOffset();
int start = pos;
CharacterHelper.CharacterType[] types = new CharacterHelper.CharacterType[] {
CharacterHelper.CharacterType.LETTER_OR_DIGIT,
CharacterHelper.CharacterType.KEYWORD,
CharacterHelper.CharacterType.PUNCTUATION
};
for (int i = 0; i < 2; i++) {
@@ -904,7 +904,7 @@ public class SearchHelper {
int end;
// Special case 1 character words because 'findNextWordEnd' returns one to many chars
if (start < stop && CharacterHelper.charType(chars.charAt(start + 1), false) != CharacterHelper.CharacterType.LETTER_OR_DIGIT) {
if (start < stop && CharacterHelper.charType(chars.charAt(start + 1), false) != CharacterHelper.CharacterType.KEYWORD) {
end = start + 1;
}
else {

View File

@@ -0,0 +1,249 @@
package com.maddyhome.idea.vim.option;
import org.apache.commons.lang.math.NumberUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
public final class KeywordOption extends ListOption {
@NotNull private final Pattern validationPattern;
// KeywordSpecs are the option values in reverse order
@NotNull private List<KeywordSpec> keywordSpecs = new ArrayList<>();
public KeywordOption(@NotNull String name, @NotNull String abbrev, @NotNull String[] defaultValue) {
super(name, abbrev, defaultValue,
"(\\^?(([^0-9^]|[0-9]{1,3})-([^0-9]|[0-9]{1,3})|([^0-9^]|[0-9]{1,3})),)*\\^?(([^0-9^]|[0-9]{1,3})-([^0-9]|[0-9]{1,3})|([^0-9]|[0-9]{1,3})),?$");
validationPattern = Pattern.compile(pattern);
set(getValue());
}
@Override
public boolean append(@NotNull String val) {
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null || value == null) {
return false;
}
value.addAll(vals);
keywordSpecs.addAll(0, specs);
fireOptionChangeEvent();
return true;
}
@Override
public boolean prepend(@NotNull String val) {
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null || value == null) {
return false;
}
value.addAll(0, vals);
keywordSpecs.addAll(specs);
fireOptionChangeEvent();
return true;
}
@Override
public boolean remove(@NotNull String val) {
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null || value == null) {
return false;
}
value.removeAll(vals);
keywordSpecs.removeAll(specs);
fireOptionChangeEvent();
return true;
}
@Override
public boolean set(@NotNull String val) {
final List<String> vals = parseVals(val);
final List<KeywordSpec> specs = valsToValidatedAndReversedSpecs(vals);
if (vals == null || specs == null || value == null) {
return false;
}
value = vals;
keywordSpecs = specs;
fireOptionChangeEvent();
return true;
}
@Override
public void resetDefault() {
if (!dflt.equals(value)) {
value = dflt;
set(getValue());
}
}
@Nullable
private List<KeywordSpec> valsToValidatedAndReversedSpecs(@Nullable List<String> vals) {
final List<KeywordSpec> specs = new ArrayList<>();
if (vals != null) {
for (String val : vals) {
KeywordSpec spec = new KeywordSpec(val);
if (!spec.isValid()) {
return null;
}
specs.add(spec);
}
Collections.reverse(specs);
}
return specs;
}
@Nullable
@Override
protected List<String> parseVals(@NotNull String content) {
if (!validationPattern.matcher(content).matches()) {
return null;
}
int index = 0;
boolean firstCharNumOfPart = true;
boolean inRange = false;
final List<String> vals = new ArrayList<>();
StringBuilder option = new StringBuilder();
// We need to split the input string into parts. However, we can't just split on a comma
// since a comma can either be a keyword or a separator depending on its location in the string.
while (index <= content.length()) {
char curChar = 0;
if (index < content.length()) {
curChar = content.charAt(index);
}
index++;
// If we either have a comma separator or are at the end of the content...
if (curChar == ',' && (!firstCharNumOfPart && !inRange) || index == content.length() + 1) {
String part = option.toString();
vals.add(part);
option = new StringBuilder();
inRange = false;
firstCharNumOfPart = true;
continue;
}
option.append(curChar);
if (curChar == '^' && option.length() == 1) {
firstCharNumOfPart = true;
continue;
}
if (curChar == '-' && !firstCharNumOfPart) {
inRange = true;
continue;
}
firstCharNumOfPart = false;
inRange = false;
}
return vals;
}
public boolean isKeyword(char c) {
final int code = (int)c;
if (code >= '\u0100') {
return true;
}
for (KeywordSpec spec : keywordSpecs) {
if (spec.contains(code)) {
return !spec.negate();
}
}
return false;
}
private static final class KeywordSpec {
private String part;
private boolean negate;
private boolean isRange = false;
private boolean isAllLetters = false;
private Integer rangeLow;
private Integer rangeHigh;
public KeywordSpec(@NotNull String part) {
this.part = part;
negate = part.matches("^\\^.+");
if (negate) {
part = part.substring(1);
}
final String[] keywords = part.split("(?<=.)-(?=.+)");
if (keywords.length > 1 || keywords[0].equals("@")) {
isRange = true;
if (keywords.length > 1) {
rangeLow = toUnicode(keywords[0]);
rangeHigh = toUnicode(keywords[1]);
}
else {
isAllLetters = true;
}
}
else {
int keyword = toUnicode(keywords[0]);
rangeLow = keyword;
rangeHigh = keyword;
}
}
private int toUnicode(@NotNull String str) {
if (NumberUtils.isNumber(str)) {
return Integer.parseInt(str); // If we have a number, it represents the Unicode code point of a letter
}
else {
return (int)str.charAt(0); // If it's not a number we should only have strings consisting of one char
}
}
@Override
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
KeywordSpec that = (KeywordSpec)o;
return part.equals(that.part);
}
@Override
public int hashCode() {
return part.hashCode();
}
public boolean isValid() {
return (!isRange || isAllLetters) || (rangeLow <= rangeHigh);
}
public boolean negate() {
return negate;
}
public boolean contains(int code) {
if (isAllLetters) {
return Character.isLetter(code);
}
if (isRange) {
return (code >= rangeLow && code <= rangeHigh);
}
return code == rangeLow;
}
}
}

View File

@@ -471,6 +471,7 @@ public class Options {
addOption(new ToggleOption(INCREMENTAL_SEARCH, "is", false));
addOption(new ToggleOption(TIMEOUT, "to", true));
addOption(new ListOption(VIMINFO, "vi", new String[]{"'100", "<50", "s10", "h"}, null));
addOption(new KeywordOption("iskeyword", "isk", new String[]{"@", "48-57", "_"}));
registerExtensionOptions();
}
@@ -504,8 +505,8 @@ public class Options {
abbrevs.put(option.getAbbreviation(), option);
}
@NotNull private final HashMap<String, Option> options = new HashMap<String, Option>();
@NotNull private final HashMap<String, Option> abbrevs = new HashMap<String, Option>();
@NotNull private final HashMap<String, Option> options = new LinkedHashMap<>();
@NotNull private final HashMap<String, Option> abbrevs = new LinkedHashMap<>();
private static Options ourInstance;

View File

View File

@@ -1,36 +1,30 @@
package org.jetbrains.plugins.ideavim.helper;
import com.maddyhome.idea.vim.helper.SearchHelper;
import org.junit.Test;
import org.jetbrains.plugins.ideavim.VimTestCase;
import static junit.framework.Assert.assertEquals;
public class SearchHelperTest {
@Test
public void testFindNextWord() throws Exception {
public class SearchHelperTest extends VimTestCase {
public void testFindNextWord() {
String text = "first second";
int nextWordPosition = SearchHelper.findNextWord(text, 0, text.length(), 1, true, false);
assertEquals(nextWordPosition, text.indexOf("second"));
}
@Test
public void testFindSecondNextWord() throws Exception {
public void testFindSecondNextWord() {
String text = "first second third";
int nextWordPosition = SearchHelper.findNextWord(text, 0, text.length(), 2, true, false);
assertEquals(nextWordPosition, text.indexOf("third"));
}
@Test
public void testFindAfterLastWord() throws Exception {
public void testFindAfterLastWord() {
String text = "first second";
int nextWordPosition = SearchHelper.findNextWord(text, 0, text.length(), 3, true, false);
assertEquals(nextWordPosition, text.length());
}
@Test
public void testFindPreviousWord() {
String text = "first second";
int previousWordPosition = SearchHelper.findNextWord(text, text.indexOf("second"), text.length(), -1, true, false);
@@ -38,7 +32,6 @@ public class SearchHelperTest {
assertEquals(previousWordPosition, text.indexOf("first"));
}
@Test
public void testFindSecondPreviousWord() {
String text = "first second third";
int previousWordPosition = SearchHelper.findNextWord(text, text.indexOf("third"), text.length(), -2, true, false);
@@ -46,7 +39,6 @@ public class SearchHelperTest {
assertEquals(previousWordPosition, text.indexOf("first"));
}
@Test
public void testFindBeforeFirstWord() {
String text = "first second";
int previousWordPosition = SearchHelper.findNextWord(text, text.indexOf("second"), text.length(), -3, true, false);
@@ -54,7 +46,6 @@ public class SearchHelperTest {
assertEquals(previousWordPosition, text.indexOf("first"));
}
@Test
public void testFindPreviousWordWhenCursorOutOfBound() {
String text = "first second";
int previousWordPosition = SearchHelper.findNextWord(text, text.length(), text.length(), -1, true, false);

View File

@@ -1,8 +1,8 @@
package org.jetbrains.plugins.ideavim.helper;
import com.maddyhome.idea.vim.helper.StringHelper;
import junit.framework.TestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.ideavim.VimTestCase;
import javax.swing.*;
import java.awt.event.InputEvent;
@@ -11,7 +11,7 @@ import java.util.List;
/**
* @author vlan
*/
public class StringHelperTest extends TestCase {
public class StringHelperTest extends VimTestCase {
public void testParseKeyModifiers() {
assertTypedKeyStroke('C', "C");
assertTypedKeyStroke('c', "c");

View File

@@ -0,0 +1,127 @@
package org.jetbrains.plugins.ideavim.option;
import com.maddyhome.idea.vim.ex.ExException;
import com.maddyhome.idea.vim.helper.CharacterHelper;
import com.maddyhome.idea.vim.option.KeywordOption;
import com.maddyhome.idea.vim.option.Options;
import org.jetbrains.plugins.ideavim.VimTestCase;
import java.util.ArrayList;
import java.util.List;
public class KeywordOptionTest extends VimTestCase {
private KeywordOption option;
public void setUp() throws Exception {
super.setUp();
option = (KeywordOption)Options.getInstance().getOption("iskeyword");
}
private void setKeyword(String val) {
Options.getInstance().parseOptionLine(myFixture.getEditor(), "iskeyword" + val, false);
}
private void assertIsKeyword(char c){
CharacterHelper.CharacterType charType = CharacterHelper.charType(c, false);
assertSame(CharacterHelper.CharacterType.KEYWORD, charType);
}
private void assertIsNotKeyword(char c) {
CharacterHelper.CharacterType charType = CharacterHelper.charType(c, false);
assertSame(CharacterHelper.CharacterType.PUNCTUATION, charType);
}
public void testSingleCommaIsAValue() throws ExException {
option.set(",");
assertEquals(",", option.values().get(0));
}
public void testSingleNegatedCommaIsAValue() throws ExException {
option.set("^,");
assertEquals("^,", option.values().get(0));
}
public void testCommaInARangeIsAValue() throws ExException {
option.set("+-,");
assertEquals("+-,", option.values().get(0));
}
public void testSecondCommaIsASeparator() throws ExException {
option.set(",,a");
assertEquals(",", option.values().get(0));
assertEquals("a", option.values().get(1));
}
public void testSingleHyphenIsAValue() throws ExException {
option.set("-");
assertEquals("-", option.values().get(0));
}
public void testHyphenBetweenCharNumsIsARange() throws ExException {
option.set("a-b");
assertEquals("a-b", option.values().get(0));
}
public void testRangeInWhichLeftValueIsHigherThanRightValueIsInvalid() {
option.set("b-a");
assertDoesntContain(option.values(), new ArrayList<String>(){{add("b-a");}});
}
public void testTwoAdjacentLettersAreInvalid() {
option.set("ab");
List<String> v = option.values();
assertDoesntContain(option.values(), new ArrayList<String>(){{add("ab");}});
}
public void testAddsACharByChar() throws ExException {
setKeyword("=-");
assertIsKeyword('-');
}
public void testAddsACharByUnicodeCodePoint() throws ExException {
setKeyword("=" + (int)'-');
assertIsKeyword('-');
}
public void testAddsARange() throws ExException {
setKeyword("=a-c");
assertIsKeyword('a');
assertIsKeyword('b');
assertIsKeyword('c');
}
public void testAtSignRepresentsAllLetters() throws ExException {
setKeyword("=@");
assertIsKeyword('A');
assertIsKeyword('Ā');
}
public void testRangeOfAtSignToAtSignRepresentsAtSign() throws ExException {
setKeyword("=@-@");
assertIsKeyword('@');
}
public void testCaretRemovesAChar() throws ExException {
setKeyword("=a");
setKeyword("+=^a");
assertIsNotKeyword('a');
}
public void testCaretRemovesARange() throws ExException {
setKeyword("=a-c");
setKeyword("+=^b-c,d");
assertIsKeyword('a');
assertIsNotKeyword('b');
assertIsNotKeyword('c');
}
public void testCaretAloneRepresentsACaret() throws ExException {
setKeyword("=^");
assertIsKeyword('^');
}
public void testMultibyteCharactersAreKeywords() throws ExException {
assertIsKeyword('Ź');
}
}