Skip to content

Commit a413ace

Browse files
authored
Merge pull request #254 from SeeSharpSoft/master
Release 2.14.4
2 parents 5718d70 + 42f6afe commit a413ace

File tree

10 files changed

+129
-31
lines changed

10 files changed

+129
-31
lines changed

CHANGELOG

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2.14.4
2+
Feb 14, 2021
3+
4+
NEW: Auto detect value separator (by count)
5+
16
2.14.3
27
Oct 10, 2020
38

README.md

+14-5
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ This enables default editor features like syntax validation, highlighting and in
4141

4242
- Starting with **CSV Plugin 2.11.0**, _Java 9 (53) or higher is required_. Previous versions can be downloaded and installed manually from the following locations: [GitHub Releases](https://github.com/SeeSharpSoft/intellij-csv-validator/releases), [Plugin Repository](https://plugins.jetbrains.com/plugin/10037-csv-plugin/versions) (see also section [Installation](https://github.com/SeeSharpSoft/intellij-csv-validator#installation)).
4343

44+
- Starting with **CSV Plugin 2.14.0**, _Java 11 (55) or higher is required_. Previous versions can be downloaded and installed manually from the following locations: [GitHub Releases](https://github.com/SeeSharpSoft/intellij-csv-validator/releases), [Plugin Repository](https://plugins.jetbrains.com/plugin/10037-csv-plugin/versions) (see also section [Installation](https://github.com/SeeSharpSoft/intellij-csv-validator#installation)).
45+
4446
### Syntax parser & validation
4547

4648
The CSV syntax parser follows the standard defined in [IETF 4180](https://www.ietf.org/rfc/rfc4180.txt) but tolerates leading and trailing whitespaces of escaped text and accepts basically every literal as text data.
@@ -130,9 +132,16 @@ The preferred editor usage can be switched between "Text Editor first", "Table E
130132

131133
The following separators are currently supported: **,** (Comma), **;** (Semicolon), **:** (Colon), **|** (Pipe) and **↹** (Tab)
132134

133-
_Default Value Separator_ defines which separator is used as standard for each newly opened CSV file. The separator character can be changed for each file individually in its editors context menu.
135+
_Default Value Separator_ defines which separator is used as standard for each newly created or opened CSV file.
136+
The separator character can be changed for each file individually in its editors context menu.
137+
138+
###### Auto Detect
139+
140+
The value separator of a newly opened CSV file can be detected automatically based on the number of predefined separator occurrences.
141+
142+
If _Auto Detect_ is enabled (default), the _Default Value Separator_ setting is only taken into account for newly created files.
134143

135-
This option has no effect on TSV/PSV files, the separator is pre-defined by their file- and language-type.
144+
**Note:** This option has no effect on TSV/PSV files, the separator is pre-defined by their file- and language-type.
136145

137146
##### Default Escape Character
138147

@@ -414,11 +423,11 @@ You can also download the JAR package from the [Jetbrains plugin repository](htt
414423

415424
#### CSV Plugin causes the IDE to stop working properly
416425

417-
Since version 2.11.0, the plugins requires the IntelliJ platform to be executed on JRE9 or higher. If this is not the case, the following error log can be noticed:
426+
Since version 2.14.0, the plugins requires the IntelliJ platform to be executed on JRE11 or higher. If this is not the case, the following error log can be noticed:
418427

419-
`com.intellij.diagnostic.PluginException: While loading class net.seesharpsoft.intellij.plugins.csv.CsvFileTypeOverrider: net/seesharpsoft/intellij/plugins/csv/CsvFileTypeOverrider has been compiled by a more recent version of the Java Runtime (class file version 53.0), this version of the Java Runtime only recognizes class file versions up to 52.0 [Plugin: net.seesharpsoft.intellij.plugins.csv]`
428+
`com.intellij.diagnostic.PluginException: While loading class net.seesharpsoft.intellij.plugins.csv.CsvFileTypeOverrider: net/seesharpsoft/intellij/plugins/csv/CsvFileTypeOverrider has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 [Plugin: net.seesharpsoft.intellij.plugins.csv]`
420429

421-
In some cases the error log doesn't seem to point this out in a noticable manner, but the IDE doesn't work correctly after enabling the plugin. Always disable the plugin first before continuing with the following steps.
430+
In some cases the error log doesn't seem to point this out in a noticeable manner, but the IDE doesn't work correctly after enabling the plugin. Always disable the plugin first before continuing with the following steps.
422431

423432
Please read the [official instructions](https://intellij-support.jetbrains.com/hc/en-us/articles/206544879-Selecting-the-JDK-version-the-IDE-will-run-under) on how to switch to a newer JRE, or [manually install](https://github.com/SeeSharpSoft/intellij-csv-validator#installation) a [prior CSV plugin version](https://github.com/SeeSharpSoft/intellij-csv-validator/releases/tag/2.10.0).
424433

build.gradle

+5-5
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ jacocoTestReport {
2424
}
2525

2626
group 'net.seesharpsoft.intellij.plugins'
27-
version '2.14.3'
27+
version '2.14.4'
2828

2929
apply plugin: 'java'
30-
sourceCompatibility = javaVersion
31-
targetCompatibility = javaTargetVersion
30+
project.sourceCompatibility = JavaVersion.VERSION_11
31+
project.targetCompatibility = JavaVersion.VERSION_11
3232
tasks.withType(JavaCompile) { options.encoding = 'UTF-8' }
3333
repositories {
3434
mavenCentral()
@@ -60,8 +60,8 @@ sourceSets {
6060
apply plugin: 'idea'
6161
idea {
6262
project {
63-
jdkName = javaVersion
64-
languageLevel = javaVersion
63+
jdkName = JavaVersion.VERSION_11
64+
languageLevel = JavaVersion.VERSION_11
6565
vcs = 'Git'
6666
}
6767
module {

gradle.properties

-2
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,3 @@
33
# https://www.jetbrains.com/intellij-repository/snapshots
44

55
name='CSV Plugin'
6-
javaVersion=11
7-
javaTargetVersion=11

src/main/java/net/seesharpsoft/intellij/plugins/csv/components/CsvFileAttributes.java

+51-5
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@
55
import com.intellij.openapi.components.ServiceManager;
66
import com.intellij.openapi.components.State;
77
import com.intellij.openapi.components.Storage;
8+
import com.intellij.openapi.editor.Document;
9+
import com.intellij.openapi.fileEditor.FileDocumentManager;
810
import com.intellij.openapi.fileTypes.LanguageFileType;
911
import com.intellij.openapi.project.Project;
1012
import com.intellij.openapi.vfs.VirtualFile;
1113
import com.intellij.psi.PsiFile;
1214
import com.intellij.util.xmlb.XmlSerializerUtil;
1315
import com.intellij.util.xmlb.annotations.OptionTag;
16+
import net.seesharpsoft.commons.collection.Pair;
1417
import net.seesharpsoft.intellij.plugins.csv.*;
1518
import net.seesharpsoft.intellij.plugins.csv.settings.CsvEditorSettings;
19+
import org.apache.commons.lang.StringUtils;
1620
import org.jetbrains.annotations.NotNull;
1721
import org.jetbrains.annotations.Nullable;
1822

23+
import java.util.Arrays;
1924
import java.util.HashMap;
2025
import java.util.Map;
2126

@@ -87,12 +92,18 @@ public boolean canChangeValueSeparator(@NotNull PsiFile psiFile) {
8792
return language.isKindOf(CsvLanguage.INSTANCE) && !(language instanceof CsvSeparatorHolder);
8893
}
8994

95+
private void setFileSeparator(@NotNull Project project, @NotNull VirtualFile virtualFile, @NotNull CsvValueSeparator separator) {
96+
Attribute attribute = getFileAttribute(project, virtualFile, true);
97+
if (attribute != null) {
98+
attribute.separator = separator;
99+
}
100+
}
101+
90102
public void setFileSeparator(@NotNull PsiFile psiFile, @NotNull CsvValueSeparator separator) {
91103
if (!canChangeValueSeparator(psiFile)) {
92104
return;
93105
}
94-
Attribute attribute = getFileAttribute(psiFile.getProject(), psiFile.getOriginalFile().getVirtualFile(), true);
95-
attribute.separator = separator;
106+
setFileSeparator(psiFile.getProject(), psiFile.getOriginalFile().getVirtualFile(), separator);
96107
}
97108

98109
public void resetValueSeparator(@NotNull PsiFile psiFile) {
@@ -105,18 +116,51 @@ public void resetValueSeparator(@NotNull PsiFile psiFile) {
105116
}
106117
}
107118

119+
private @NotNull
120+
CsvValueSeparator autoDetectOrGetDefaultValueSeparator(Project project, VirtualFile virtualFile) {
121+
return CsvEditorSettings.getInstance().isAutoDetectValueSeparator() ?
122+
autoDetectSeparator(project, virtualFile) :
123+
CsvEditorSettings.getInstance().getDefaultValueSeparator();
124+
}
125+
126+
private @NotNull
127+
CsvValueSeparator autoDetectSeparator(Project project, VirtualFile virtualFile) {
128+
Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
129+
final String text = document == null ? "" : document.getText();
130+
Pair<CsvValueSeparator, Integer> separatorWithCount =
131+
Arrays.stream(CsvValueSeparator.values())
132+
// count
133+
.map(separator -> {
134+
String character = separator.getCharacter();
135+
return Pair.of(separator, StringUtils.countMatches(text, character));
136+
})
137+
// ignore non-matched separators
138+
.filter(p -> p.getSecond() > 0)
139+
// get the one with most hits
140+
.max((p1, p2) -> p1.getSecond() - p2.getSecond())
141+
// failsafe (e.g. empty document)
142+
.orElse(null);
143+
144+
CsvValueSeparator valueSeparator = separatorWithCount != null ?
145+
separatorWithCount.getFirst() :
146+
CsvEditorSettings.getInstance().getDefaultValueSeparator();
147+
148+
setFileSeparator(project, virtualFile, valueSeparator);
149+
return valueSeparator;
150+
}
151+
108152
public @NotNull
109153
CsvValueSeparator getValueSeparator(Project project, VirtualFile virtualFile) {
110154
if (project == null || virtualFile == null || !(virtualFile.getFileType() instanceof LanguageFileType)) {
111155
return CsvEditorSettings.getInstance().getDefaultValueSeparator();
112156
}
113157
Language language = ((LanguageFileType) virtualFile.getFileType()).getLanguage();
114158
if (language instanceof CsvSeparatorHolder) {
115-
return ((CsvSeparatorHolder) language).getSeparator();
159+
return ((CsvSeparatorHolder) language).getSeparator();
116160
}
117161
Attribute attribute = getFileAttribute(project, virtualFile);
118162
return attribute == null || attribute.separator == null ?
119-
CsvEditorSettings.getInstance().getDefaultValueSeparator() :
163+
autoDetectOrGetDefaultValueSeparator(project, virtualFile) :
120164
attribute.separator;
121165
}
122166

@@ -127,7 +171,9 @@ public boolean hasValueSeparatorAttribute(@NotNull Project project, @NotNull Vir
127171

128172
public void setEscapeCharacter(@NotNull PsiFile psiFile, @NotNull CsvEscapeCharacter escapeCharacter) {
129173
Attribute attribute = getFileAttribute(psiFile.getProject(), psiFile.getOriginalFile().getVirtualFile(), true);
130-
attribute.escapeCharacter = escapeCharacter;
174+
if (attribute != null) {
175+
attribute.escapeCharacter = escapeCharacter;
176+
}
131177
}
132178

133179
public void resetEscapeSeparator(@NotNull PsiFile psiFile) {

src/main/java/net/seesharpsoft/intellij/plugins/csv/settings/CsvEditorSettings.java

+9
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ public static final class OptionSet {
8484
public boolean KEEP_TRAILING_SPACES = false;
8585
public String COMMENT_INDICATOR = COMMENT_INDICATOR_DEFAULT;
8686
public ValueColoring VALUE_COLORING = ValueColoring.RAINBOW;
87+
public boolean AUTO_DETECT_VALUE_SEPARATOR = true;
8788

8889
public OptionSet() {
8990
EditorSettingsExternalizable editorSettingsExternalizable = EditorSettingsExternalizable.getInstance();
@@ -312,6 +313,14 @@ public void setHeaderRowFixed(boolean headerRowFixed) {
312313
getState().TABLE_HEADER_ROW_FIXED = headerRowFixed;
313314
}
314315

316+
public boolean isAutoDetectValueSeparator() {
317+
return getState().AUTO_DETECT_VALUE_SEPARATOR;
318+
}
319+
320+
public void setAutoDetectValueSeparator(boolean autoDetectValueSeparator) {
321+
getState().AUTO_DETECT_VALUE_SEPARATOR = autoDetectValueSeparator;
322+
}
323+
315324
public boolean checkCurrentPluginVersion(String actualVersion) {
316325
if (!actualVersion.equals(getState().CURRENT_PLUGIN_VERSION)) {
317326
getState().CURRENT_PLUGIN_VERSION = actualVersion;

src/main/java/net/seesharpsoft/intellij/plugins/csv/settings/CsvEditorSettingsProvider.form

+10-2
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@
343343
</component>
344344
</children>
345345
</grid>
346-
<grid id="29095" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
346+
<grid id="29095" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
347347
<margin top="0" left="0" bottom="0" right="0"/>
348348
<constraints>
349349
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -363,7 +363,7 @@
363363
</component>
364364
<hspacer id="f2aa1">
365365
<constraints>
366-
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
366+
<grid row="0" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
367367
</constraints>
368368
</hspacer>
369369
<component id="65f7" class="javax.swing.JComboBox" binding="comboValueSeparator" custom-create="true">
@@ -372,6 +372,14 @@
372372
</constraints>
373373
<properties/>
374374
</component>
375+
<component id="aed54" class="javax.swing.JCheckBox" binding="cbAutoDetectSeparator">
376+
<constraints>
377+
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
378+
</constraints>
379+
<properties>
380+
<text value="auto detect initially"/>
381+
</properties>
382+
</component>
375383
</children>
376384
</grid>
377385
<grid id="7eea1" layout-manager="GridLayoutManager" row-count="1" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">

src/main/java/net/seesharpsoft/intellij/plugins/csv/settings/CsvEditorSettingsProvider.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public class CsvEditorSettingsProvider implements EditorOptionsProvider {
4343
private JTextField tfCommentIndicator;
4444
private JComboBox comboValueColoring;
4545
private JCheckBox cbHeaderRowFixed;
46+
private JCheckBox cbAutoDetectSeparator;
4647

4748
@NotNull
4849
@Override
@@ -94,7 +95,8 @@ public boolean isModified() {
9495
isModified(cbKeepTrailingWhitespaces, csvEditorSettings.getKeepTrailingSpaces()) ||
9596
isModified(tfCommentIndicator, csvEditorSettings.getCommentIndicator()) ||
9697
!Objects.equals(comboValueColoring.getSelectedItem(), csvEditorSettings.getValueColoring()) ||
97-
isModified(cbHeaderRowFixed, csvEditorSettings.isHeaderRowFixed());
98+
isModified(cbHeaderRowFixed, csvEditorSettings.isHeaderRowFixed()) ||
99+
isModified(cbAutoDetectSeparator, csvEditorSettings.isAutoDetectValueSeparator());
98100
}
99101

100102
@Override
@@ -120,6 +122,7 @@ public void reset() {
120122
tfCommentIndicator.setText(csvEditorSettings.getCommentIndicator());
121123
comboValueColoring.setSelectedItem(csvEditorSettings.getValueColoring());
122124
cbHeaderRowFixed.setSelected(csvEditorSettings.isHeaderRowFixed());
125+
cbAutoDetectSeparator.setSelected(csvEditorSettings.isAutoDetectValueSeparator());
123126
}
124127

125128
@Override
@@ -145,6 +148,7 @@ public void apply() throws ConfigurationException {
145148
csvEditorSettings.setCommentIndicator(tfCommentIndicator.getText());
146149
csvEditorSettings.setValueColoring((CsvEditorSettings.ValueColoring) comboValueColoring.getSelectedItem());
147150
csvEditorSettings.setHeaderRowFixed(cbHeaderRowFixed.isSelected());
151+
csvEditorSettings.setAutoDetectValueSeparator(cbAutoDetectSeparator.isSelected());
148152
}
149153

150154
protected void createUIComponents() {

src/main/resources/META-INF/plugin.xml

+1-3
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,7 @@
5050

5151
<change-notes><![CDATA[
5252
<pre style="font-family: sans-serif">
53-
NEW: Added default "Header row fixed" setting
54-
NEW: Support "Comment with line comment" #247
55-
FIX: "Value coloring" change not applied to open files
53+
NEW: Auto detect value separator (by count)
5654
</pre>
5755
]]>
5856
</change-notes>

src/test/java/net/seesharpsoft/intellij/plugins/csv/parser/CsvParsingTest.java

+29-8
Original file line numberDiff line numberDiff line change
@@ -13,49 +13,70 @@ public CsvParsingTest() {
1313
super("", "csv", new CsvParserDefinition());
1414
}
1515

16+
@Override
17+
protected void setUp() throws Exception {
18+
super.setUp();
19+
CsvEditorSettings.getInstance().setAutoDetectValueSeparator(false);
20+
}
21+
22+
@Override
23+
protected void tearDown() throws Exception {
24+
CsvEditorSettings.getInstance().setAutoDetectValueSeparator(true);
25+
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvEditorSettings.VALUE_SEPARATOR_DEFAULT);
26+
CsvEditorSettings.getInstance().setCommentIndicator(COMMENT_INDICATOR_DEFAULT);
27+
super.tearDown();
28+
}
29+
1630
public void testParsingTestData() {
1731
// without comment support, default lexer is used
1832
CsvEditorSettings.getInstance().setCommentIndicator("");
1933
doTest(true);
20-
CsvEditorSettings.getInstance().setCommentIndicator(COMMENT_INDICATOR_DEFAULT);
2134
}
2235

2336
public void testParsingTestDataWithCustomParser() {
2437
setName("ParsingTestData");
2538
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvValueSeparator.create(","));
2639
doTest(true);
27-
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvEditorSettings.VALUE_SEPARATOR_DEFAULT);
2840
}
2941

3042
public void testCustomMultiSymbolSeparator() {
3143
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvValueSeparator.create("~§"));
3244
doTest(true);
33-
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvEditorSettings.VALUE_SEPARATOR_DEFAULT);
3445
}
3546

3647
public void testColonSeparator() {
3748
// without comment support, default lexer is used
3849
CsvEditorSettings.getInstance().setCommentIndicator("");
3950
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvValueSeparator.COLON);
4051
doTest(true);
41-
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvEditorSettings.VALUE_SEPARATOR_DEFAULT);
42-
CsvEditorSettings.getInstance().setCommentIndicator(COMMENT_INDICATOR_DEFAULT);
4352
}
4453

4554
public void testAllSeparators() {
4655
// without comment support, default lexer is used
4756
CsvEditorSettings.getInstance().setCommentIndicator("");
4857
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvValueSeparator.COMMA);
4958
doTest(true);
50-
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvEditorSettings.VALUE_SEPARATOR_DEFAULT);
51-
CsvEditorSettings.getInstance().setCommentIndicator(COMMENT_INDICATOR_DEFAULT);
5259
}
5360

5461
public void testCsvWithComments() {
5562
// comment support by default (custom lexer is used)
5663
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvValueSeparator.COMMA);
5764
doTest(true);
58-
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvEditorSettings.VALUE_SEPARATOR_DEFAULT);
65+
}
66+
67+
public void testParsingTestDataWithAutoDetect() {
68+
setName("ParsingTestData");
69+
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvValueSeparator.PIPE);
70+
CsvEditorSettings.getInstance().setAutoDetectValueSeparator(true);
71+
doTest(true);
72+
}
73+
74+
public void testColonSeparatorWithAutoDetect() {
75+
setName("ColonSeparator");
76+
CsvEditorSettings.getInstance().setCommentIndicator("");
77+
CsvEditorSettings.getInstance().setDefaultValueSeparator(CsvValueSeparator.PIPE);
78+
CsvEditorSettings.getInstance().setAutoDetectValueSeparator(true);
79+
doTest(true);
5980
}
6081

6182
@Override

0 commit comments

Comments
 (0)