A separate option to keep trailing spaces on caret line, IDEA-164345 [IDEA-CR-16664]
authorRustam Vishnyakov <rustam.vishnyakov@jetbrains.com>
Wed, 14 Dec 2016 12:52:57 +0000 (15:52 +0300)
committerRustam Vishnyakov <rustam.vishnyakov@jetbrains.com>
Wed, 14 Dec 2016 13:33:22 +0000 (16:33 +0300)
platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.form
platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsPanel.java
platform/platform-impl/src/com/intellij/ide/actions/SaveAllAction.java
platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorSettingsExternalizable.java
platform/platform-impl/src/com/intellij/openapi/editor/impl/TrailingSpacesStripper.java
platform/platform-resources-en/src/messages/ApplicationBundle.properties
platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/TrailingSpacesStripperTest.java

index 8e7b1e34d8ac8d7d471ecc23b5dbeccb8f87f651..c196a467cd5ae1e2353ef1ef25e3c6b87533bcb3 100644 (file)
                   </component>
                 </children>
               </grid>
-              <grid id="7f3f5" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+              <grid id="7f3f5" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
                 <margin top="0" left="0" bottom="0" right="0"/>
                 <constraints>
                   <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
                 <children>
                   <component id="901e0" class="javax.swing.JCheckBox" binding="myCbEnsureBlankLineBeforeCheckBox" default-binding="true">
                     <constraints>
-                      <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                      <grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties>
                       <text value="Ensure line feed at file end on Save"/>
                   </component>
                   <component id="ce8e2" class="com.intellij.ui.components.JBCheckBox" binding="myCbShowQuickDocOnMouseMove">
                     <constraints>
-                      <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                      <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties>
                       <text value="Show quick documentation on mouse move"/>
                   </component>
                   <component id="ec4ad" class="javax.swing.JTextField" binding="myQuickDocDelayTextField">
                     <constraints>
-                      <grid row="2" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
+                      <grid row="3" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false">
                         <preferred-size width="50" height="-1"/>
                       </grid>
                     </constraints>
                   </component>
                   <component id="8691a" class="com.intellij.ui.components.JBLabel" binding="myQuickDocDelayLabel">
                     <constraints>
-                      <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+                      <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties>
                       <horizontalAlignment value="11"/>
                   </component>
                   <vspacer id="612dd">
                     <constraints>
-                      <grid row="5" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+                      <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
                     </constraints>
                   </vspacer>
                   <component id="95944" class="javax.swing.JCheckBox" binding="myShowLSTInGutterCheckBox">
                     <constraints>
-                      <grid row="3" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+                      <grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
                     </constraints>
                     <properties>
                       <text value="Highlight modified lines in gutter"/>
                   </component>
                   <component id="76ce4" class="javax.swing.JCheckBox" binding="myShowWhitespacesModificationsInLSTGutterCheckBox">
                     <constraints>
-                      <grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
+                      <grid row="5" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
                     </constraints>
                     <properties>
                       <text value="Different color for lines with whitespace-only modifications"/>
                     </properties>
                   </component>
+                  <component id="e6a86" class="javax.swing.JCheckBox" binding="myCbKeepTrailingSpacesOnCaretLine">
+                    <constraints>
+                      <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
+                    </constraints>
+                    <properties>
+                      <text resource-bundle="messages/ApplicationBundle" key="editor.settings.keep.trailing.spaces.on.caret.line"/>
+                    </properties>
+                  </component>
                 </children>
               </grid>
               <grid id="7bb4" layout-manager="GridLayoutManager" row-count="4" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
index 8cf9700be9c0666d0030cfdfb9fd262b9f80635f..6717077957d6f5578d2368967513ce14beb8439c 100644 (file)
@@ -55,6 +55,8 @@ import org.jetbrains.annotations.NotNull;
 
 import javax.swing.*;
 import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 
@@ -103,6 +105,7 @@ public class EditorOptionsPanel implements SearchableConfigurable {
   private JCheckBox    myCbEnableRichCopyByDefault;
   private JCheckBox    myShowLSTInGutterCheckBox;
   private JCheckBox    myShowWhitespacesModificationsInLSTGutterCheckBox;
+  private JCheckBox myCbKeepTrailingSpacesOnCaretLine;
 
   private static final String ACTIVE_COLOR_SCHEME = ApplicationBundle.message("combobox.richcopy.color.scheme.active");
   private static final UINumericRange RECENT_FILES_RANGE = new UINumericRange(50, 1, 500);
@@ -119,6 +122,13 @@ public class EditorOptionsPanel implements SearchableConfigurable {
     myStripTrailingSpacesCombo.addItem(STRIP_CHANGED);
     myStripTrailingSpacesCombo.addItem(STRIP_ALL);
     myStripTrailingSpacesCombo.addItem(STRIP_NONE);
+    
+    myStripTrailingSpacesCombo.addActionListener(new ActionListener() {
+      @Override
+      public void actionPerformed(ActionEvent e) {
+        myCbKeepTrailingSpacesOnCaretLine.setEnabled(!STRIP_NONE.equals(myStripTrailingSpacesCombo.getSelectedItem()));
+      }
+    });
 
 
     myHighlightSettingsPanel.setLayout(new BorderLayout());
@@ -191,6 +201,7 @@ public class EditorOptionsPanel implements SearchableConfigurable {
     else if (EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE.equals(stripTrailingSpaces)) {
       myStripTrailingSpacesCombo.setSelectedItem(STRIP_ALL);
     }
+    myCbKeepTrailingSpacesOnCaretLine.setSelected(editorSettings.isKeepTrailingSpacesOnCaretLine());
 
     myCbEnsureBlankLineBeforeCheckBox.setSelected(editorSettings.isEnsureNewLineAtEOF());
     myCbShowQuickDocOnMouseMove.setSelected(editorSettings.isShowQuickDocOnMouseOverElement());
@@ -290,6 +301,7 @@ public class EditorOptionsPanel implements SearchableConfigurable {
     else {
       editorSettings.setStripTrailingSpaces(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
     }
+    editorSettings.setKeepTrailingSpacesOnCaretLine(myCbKeepTrailingSpacesOnCaretLine.isSelected());
 
     editorSettings.setEnsureNewLineAtEOF(myCbEnsureBlankLineBeforeCheckBox.isSelected());
 
@@ -439,6 +451,8 @@ public class EditorOptionsPanel implements SearchableConfigurable {
 
     // Strip trailing spaces, ensure EOL on EOF on save
     isModified |= !getStripTrailingSpacesValue().equals(editorSettings.getStripTrailingSpaces());
+    isModified |= isModified(myCbKeepTrailingSpacesOnCaretLine, editorSettings.isKeepTrailingSpacesOnCaretLine());
+    
     isModified |= isModified(myCbEnsureBlankLineBeforeCheckBox, editorSettings.isEnsureNewLineAtEOF());
 
     isModified |= isModified(myCbShowQuickDocOnMouseMove, editorSettings.isShowQuickDocOnMouseOverElement());
index caced485e9cc2eaa2be8e68cd16ef5758e03b0e4..d5cb3935c92c0dfebae09d5d4be07a02fff9098a 100644 (file)
@@ -35,12 +35,14 @@ public class SaveAllAction extends AnAction implements DumbAware {
     }
     ApplicationManager.getApplication().saveAll();
   }
-  
+
   private static void stripSpacesFromCaretLines(@NotNull Editor editor) {
-    final String stripSpacesSetting = EditorSettingsExternalizable.getInstance().getStripTrailingSpaces();
-    if (!EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE.equals(stripSpacesSetting)) {
+    final EditorSettingsExternalizable editorSettings = EditorSettingsExternalizable.getInstance();
+    if (!EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE.equals(editorSettings.getStripTrailingSpaces())
+        && !editorSettings.isKeepTrailingSpacesOnCaretLine()) {
       Document document = editor.getDocument();
-      final boolean inChangedLinesOnly = EditorSettingsExternalizable.STRIP_TRAILING_SPACES_CHANGED.equals(stripSpacesSetting);
+      final boolean inChangedLinesOnly =
+        EditorSettingsExternalizable.STRIP_TRAILING_SPACES_CHANGED.equals(editorSettings.getStripTrailingSpaces());
       TrailingSpacesStripper.strip(document, inChangedLinesOnly, false);
     }
   }
index fb3268ecdcd737e1fefb82b2b78fef224dd1a65d..91e498429a3e2626d2128ba8f471b8163ed403fa 100644 (file)
@@ -94,6 +94,8 @@ public class EditorSettingsExternalizable implements PersistentStateComponent<Ed
     public boolean SHOW_PARAMETER_NAME_HINTS = true;
     public int MIN_PARAM_NAME_LENGTH_TO_SHOW = 3;
     public int MIN_PARAMS_TO_SHOW = 2;
+    
+    public boolean KEEP_TRAILING_SPACE_ON_CARET_LINE = true;
   }
 
   private static final String COMPOSITE_PROPERTY_SEPARATOR = ":";
@@ -561,4 +563,11 @@ public class EditorSettingsExternalizable implements PersistentStateComponent<Ed
     myOptions.MIN_PARAMS_TO_SHOW = minParamsToShow;
   }
 
+  public boolean isKeepTrailingSpacesOnCaretLine() {
+    return myOptions.KEEP_TRAILING_SPACE_ON_CARET_LINE;
+  }
+  
+  public void setKeepTrailingSpacesOnCaretLine(boolean keep) {
+    myOptions.KEEP_TRAILING_SPACE_ON_CARET_LINE = keep;
+  }
 }
index 3b63ee94374deb38abee5f71a82d679014b42aa2..ba46acd2c41997b8fdced3b551201958f830402a 100644 (file)
@@ -83,7 +83,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
 
     if (doStrip) {
       final boolean inChangedLinesOnly = !stripTrailingSpaces.equals(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
-      boolean success = strip(document, inChangedLinesOnly, true);
+      boolean success = strip(document, inChangedLinesOnly, settings.isKeepTrailingSpacesOnCaretLine());
       if (!success) {
         myDocumentsToStripLater.add(document);
       }
@@ -170,10 +170,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
     }
     Editor activeEditor = getActiveEditor(document);
 
-    // when virtual space enabled, we can strip whitespace anywhere
-    boolean isVirtualSpaceEnabled = activeEditor == null || activeEditor.getSettings().isVirtualSpace();
-
-    final List<Caret> carets = activeEditor == null ? Collections.<Caret>emptyList() : activeEditor.getCaretModel().getAllCarets();
+    final List<Caret> carets = activeEditor == null ? Collections.emptyList() : activeEditor.getCaretModel().getAllCarets();
     final List<VisualPosition> visualCarets = new ArrayList<>(carets.size());
     int[] caretOffsets = new int[carets.size()];
     for (int i = 0; i < carets.size(); i++) {
@@ -184,7 +181,7 @@ public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
 
     boolean markAsNeedsStrippingLater =
       ((DocumentImpl)document).stripTrailingSpaces(getProject(document, activeEditor),
-                                                   inChangedLinesOnly, !isVirtualSpaceEnabled && skipCaretLines, caretOffsets);
+                                                   inChangedLinesOnly, skipCaretLines, caretOffsets);
 
     if (activeEditor != null && !ShutDownTracker.isShutdownHookRunning()) {
       activeEditor.getCaretModel().runBatchCaretOperation(() -> {
index ee4332d1802e0edf4bb068fd4600c3f572da910d..dceef907270b61475ba14cfd89f53aca758d9724 100644 (file)
@@ -770,6 +770,7 @@ color.scheme.reset.title=Scheme Reset
 
 settings.code.style.reset.to.defaults.message=Change all code style settings to their default values?\nNote: all the changes you have made to the scheme will be lost.
 settings.code.style.reset.to.defaults.title=Scheme Reset
+editor.settings.keep.trailing.spaces.on.caret.line=Always keep trailing spaces on caret line
 settings.editor.scheme.copy=Duplicate
 settings.editor.scheme.delete=Delete
 settings.editor.scheme.import=Import Scheme
index a73eea7dad1f77a31bb5928e7be343899056f098..5d694071799c6836d0fa9dc3daa256e7410b08f1 100644 (file)
@@ -219,6 +219,7 @@ public class TrailingSpacesStripperTest extends LightPlatformCodeInsightTestCase
   public void testStripTrailingSpacesAtCaretLineOnExplicitSave() {
     EditorSettingsExternalizable settings = EditorSettingsExternalizable.getInstance();
     settings.setStripTrailingSpaces(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
+    settings.setKeepTrailingSpacesOnCaretLine(false);
     configureFromFileText(
       "x.txt",
       "xxx   <caret>\nyyy   "