IDEA-87318 Backspace should delete whitespace to chosen indent level, or be configurable

This commit is contained in:
Dmitry Batrak
2014-12-17 10:39:05 +03:00
parent af14f248ab
commit 7f015b4ee1
16 changed files with 212 additions and 62 deletions
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.editorActions;
public abstract class BackspaceModeOverride {
/**
* @see SmartBackspaceMode
*/
public abstract int getBackspaceMode(int modeFromSettings);
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.editorActions;
import com.intellij.lang.LanguageExtension;
public class LanguageBackspaceModeOverride extends LanguageExtension<BackspaceModeOverride> {
public static final LanguageBackspaceModeOverride INSTANCE = new LanguageBackspaceModeOverride();
private LanguageBackspaceModeOverride() {
super("com.intellij.editor.backspaceModeOverride");
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.editorActions;
public class SmartBackspaceMode {
public static final int OFF = 0;
public static final int AUTOINDENT = 1;
public static final int INDENT = 2;
private SmartBackspaceMode() {}
}
@@ -223,10 +223,6 @@ public abstract class LanguageCodeStyleSettingsProvider {
return fieldCollector.getCollectedFields();
}
public boolean isIndentBasedLanguageSemantics() {
return false;
}
private final class SupportedFieldCollector implements CodeStyleSettingsCustomizable {
private final Set<String> myCollectedFields = new HashSet<String>();
private SettingsType myCurrSettingsType;
@@ -3,7 +3,7 @@
<grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="12" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
<xy x="20" y="20" width="500" height="437"/>
</constraints>
<properties/>
<border type="none"/>
@@ -33,7 +33,7 @@
</component>
<component id="67fc" class="javax.swing.JCheckBox" binding="myCbInsertPairBracket">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" 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="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
@@ -42,7 +42,7 @@
</component>
<component id="7263c" class="javax.swing.JCheckBox" binding="myCbInsertPairQuote">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" 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="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
@@ -51,7 +51,7 @@
</component>
<component id="278d0" class="javax.swing.JCheckBox" binding="myCbCamelWords">
<constraints>
<grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/ApplicationBundle" key="checkbox.use.camelhumps.words"/>
@@ -94,7 +94,24 @@
<border type="none"/>
<children/>
</grid>
<grid id="5344e" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<component id="a64de" class="javax.swing.JCheckBox" binding="myCbReformatBlockOnTypingRBrace">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text resource-bundle="messages/ApplicationBundle" key="checkbox.reformat.on.typing.rbrace"/>
</properties>
</component>
<component id="158ea" class="javax.swing.JCheckBox" binding="myCbSurroundSelectionOnTyping" default-binding="true">
<constraints>
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Surround selection on typing quote or brace"/>
</properties>
</component>
<grid id="e1eb4" layout-manager="GridLayoutManager" row-count="1" 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="8" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -103,6 +120,38 @@
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="none" title="Backspace"/>
<children>
<component id="25dab" class="javax.swing.JLabel">
<constraints>
<grid row="0" 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 resource-bundle="messages/ApplicationBundle" key="combobox.smart.backspace"/>
</properties>
</component>
<component id="b86e4" class="javax.swing.JComboBox" binding="mySmartBackspaceCombo">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<hspacer id="4cc37">
<constraints>
<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"/>
</constraints>
</hspacer>
</children>
</grid>
<grid id="5344e" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="7" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<clientProperties>
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
</clientProperties>
<border type="none" title="Enter"/>
<children>
<component id="6293d" class="javax.swing.JCheckBox" binding="myCbSmartIndentOnEnter">
@@ -135,35 +184,9 @@
</grid>
<hspacer id="6cc57">
<constraints>
<grid row="8" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="7" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="a64de" class="javax.swing.JCheckBox" binding="myCbReformatBlockOnTypingRBrace">
<constraints>
<grid row="5" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text resource-bundle="messages/ApplicationBundle" key="checkbox.reformat.on.typing.rbrace"/>
</properties>
</component>
<component id="158ea" class="javax.swing.JCheckBox" binding="myCbSurroundSelectionOnTyping" default-binding="true">
<constraints>
<grid row="7" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Surround selection on typing quote or brace"/>
</properties>
</component>
<component id="87366" class="javax.swing.JCheckBox" binding="myCbIndentingBackspace">
<constraints>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="true"/>
<text resource-bundle="messages/ApplicationBundle" key="checkbox.indenting.backspace"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -17,6 +17,7 @@
package com.intellij.application.options.editor;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.editorActions.SmartBackspaceMode;
import com.intellij.lang.CodeDocumentationAwareCommenter;
import com.intellij.lang.Commenter;
import com.intellij.lang.Language;
@@ -63,7 +64,7 @@ public class EditorSmartKeysConfigurable extends CompositeConfigurable<UnnamedCo
private JCheckBox myCbInsertJavadocStubOnEnter;
private JCheckBox myCbSurroundSelectionOnTyping;
private JCheckBox myCbReformatBlockOnTypingRBrace;
private JCheckBox myCbIndentingBackspace;
private JComboBox mySmartBackspaceCombo;
private boolean myAddonsInitialized = false;
private static final String NO_REFORMAT = ApplicationBundle.message("combobox.paste.reformat.none");
@@ -71,12 +72,20 @@ public class EditorSmartKeysConfigurable extends CompositeConfigurable<UnnamedCo
private static final String INDENT_EACH_LINE = ApplicationBundle.message("combobox.paste.reformat.indent.each.line");
private static final String REFORMAT_BLOCK = ApplicationBundle.message("combobox.paste.reformat.reformat.block");
private static final String OFF = ApplicationBundle.message("combobox.smart.backspace.off");
private static final String SIMPLE = ApplicationBundle.message("combobox.smart.backspace.simple");
private static final String SMART = ApplicationBundle.message("combobox.smart.backspace.smart");
public EditorSmartKeysConfigurable() {
myReformatOnPasteCombo.addItem(NO_REFORMAT);
myReformatOnPasteCombo.addItem(INDENT_BLOCK);
myReformatOnPasteCombo.addItem(INDENT_EACH_LINE);
myReformatOnPasteCombo.addItem(REFORMAT_BLOCK);
mySmartBackspaceCombo.addItem(OFF);
mySmartBackspaceCombo.addItem(SIMPLE);
mySmartBackspaceCombo.addItem(SMART);
myCbInsertJavadocStubOnEnter.setVisible(hasAnyDocAwareCommenters());
}
@@ -161,7 +170,19 @@ public class EditorSmartKeysConfigurable extends CompositeConfigurable<UnnamedCo
myCbSurroundSelectionOnTyping.setSelected(codeInsightSettings.SURROUND_SELECTION_ON_QUOTE_TYPED);
myCbIndentingBackspace.setSelected(codeInsightSettings.SMART_BACKSPACE == CodeInsightSettings.AUTOINDENT);
switch (codeInsightSettings.SMART_BACKSPACE) {
case SmartBackspaceMode.OFF:
mySmartBackspaceCombo.setSelectedItem(OFF);
break;
case SmartBackspaceMode.INDENT:
mySmartBackspaceCombo.setSelectedItem(SIMPLE);
break;
case SmartBackspaceMode.AUTOINDENT:
mySmartBackspaceCombo.setSelectedItem(SMART);
break;
default:
LOG.error("Unexpected smart backspace mode value: " + codeInsightSettings.SMART_BACKSPACE);
}
super.reset();
}
@@ -182,7 +203,7 @@ public class EditorSmartKeysConfigurable extends CompositeConfigurable<UnnamedCo
codeInsightSettings.SURROUND_SELECTION_ON_QUOTE_TYPED = myCbSurroundSelectionOnTyping.isSelected();
editorSettings.setCamelWords(myCbCamelWords.isSelected());
codeInsightSettings.REFORMAT_ON_PASTE = getReformatPastedBlockValue();
codeInsightSettings.SMART_BACKSPACE = myCbIndentingBackspace.isSelected() ? CodeInsightSettings.AUTOINDENT : CodeInsightSettings.OFF;
codeInsightSettings.SMART_BACKSPACE = getSmartBackspaceModeValue();
super.apply();
}
@@ -208,7 +229,7 @@ public class EditorSmartKeysConfigurable extends CompositeConfigurable<UnnamedCo
isModified |= isModified(myCbSurroundSelectionOnTyping, codeInsightSettings.SURROUND_SELECTION_ON_QUOTE_TYPED);
isModified |= isModified(myCbIndentingBackspace, codeInsightSettings.SMART_BACKSPACE == CodeInsightSettings.AUTOINDENT);
isModified |= (getSmartBackspaceModeValue() != codeInsightSettings.SMART_BACKSPACE);
return isModified;
@@ -237,6 +258,23 @@ public class EditorSmartKeysConfigurable extends CompositeConfigurable<UnnamedCo
return -1;
}
}
private int getSmartBackspaceModeValue() {
Object selectedItem = mySmartBackspaceCombo.getSelectedItem();
if (OFF.equals(selectedItem)){
return SmartBackspaceMode.OFF;
}
else if (SIMPLE.equals(selectedItem)){
return SmartBackspaceMode.INDENT;
}
else if (SMART.equals(selectedItem)){
return SmartBackspaceMode.AUTOINDENT;
}
else{
LOG.error("Unexpected smart backspace item value: " + selectedItem);
return SmartBackspaceMode.OFF;
}
}
@Override
@NotNull
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight;
import com.intellij.codeInsight.editorActions.SmartBackspaceMode;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.ArrayUtil;
@@ -76,11 +77,8 @@ public class CodeInsightSettings implements PersistentStateComponent<Element>, C
public boolean SHOW_FULL_SIGNATURES_IN_PARAMETER_INFO = false;
@MagicConstant(intValues = {OFF, AUTOINDENT, INDENT})
public int SMART_BACKSPACE = AUTOINDENT;
public static final int OFF = 0;
public static final int AUTOINDENT = 1;
public static final int INDENT = 2;
@MagicConstant(intValues = {SmartBackspaceMode.OFF, SmartBackspaceMode.AUTOINDENT, SmartBackspaceMode.INDENT})
public int SMART_BACKSPACE = SmartBackspaceMode.AUTOINDENT;
public boolean SMART_INDENT_ON_ENTER = true;
public boolean INSERT_BRACE_ON_ENTER = true;
@@ -20,7 +20,6 @@ import com.intellij.lang.Language;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
abstract class AbstractIndentingBackspaceHandler extends BackspaceHandlerDelegate {
private final int myMode;
@@ -57,12 +56,11 @@ abstract class AbstractIndentingBackspaceHandler extends BackspaceHandlerDelegat
protected abstract boolean doCharDeleted(char c, PsiFile file, Editor editor);
private static int getBackspaceMode(Language language) {
LanguageCodeStyleSettingsProvider codeStyleSettingsProvider = LanguageCodeStyleSettingsProvider.forLanguage(language);
if (codeStyleSettingsProvider != null && codeStyleSettingsProvider.isIndentBasedLanguageSemantics()) {
return CodeInsightSettings.INDENT;
}
else {
return CodeInsightSettings.getInstance().SMART_BACKSPACE;
int mode = CodeInsightSettings.getInstance().SMART_BACKSPACE;
BackspaceModeOverride override = LanguageBackspaceModeOverride.INSTANCE.forLanguage(language);
if (override != null) {
mode = override.getBackspaceMode(mode);
}
return mode;
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.psi.PsiFile;
@@ -24,7 +23,7 @@ public class SimpleIndentingBackspaceHandler extends AbstractIndentingBackspaceH
private LogicalPosition myTargetPosition;
public SimpleIndentingBackspaceHandler() {
super(CodeInsightSettings.INDENT);
super(SmartBackspaceMode.INDENT);
}
@Override
@@ -0,0 +1,23 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.editorActions;
public class SmartBackspaceDisabler extends BackspaceModeOverride {
@Override
public int getBackspaceMode(int modeFromSettings) {
return modeFromSettings == SmartBackspaceMode.AUTOINDENT ? SmartBackspaceMode.INDENT : modeFromSettings;
}
}
@@ -15,7 +15,6 @@
*/
package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.formatting.FormatterEx;
import com.intellij.formatting.FormattingModel;
@@ -42,7 +41,7 @@ public class SmartIndentingBackspaceHandler extends AbstractIndentingBackspaceHa
private int myStartOffset;
public SmartIndentingBackspaceHandler() {
super(CodeInsightSettings.AUTOINDENT);
super(SmartBackspaceMode.AUTOINDENT);
}
@Override
@@ -33,7 +33,7 @@ public class SimpleIndentingBackspaceHandlerTest extends LightPlatformCodeInsigh
private void doTest(String before, String after) {
int savedMode = CodeInsightSettings.getInstance().SMART_BACKSPACE;
try {
CodeInsightSettings.getInstance().SMART_BACKSPACE = CodeInsightSettings.INDENT;
CodeInsightSettings.getInstance().SMART_BACKSPACE = SmartBackspaceMode.INDENT;
configureFromFileText(getTestName(false) + ".txt", before);
executeAction(IdeActions.ACTION_EDITOR_BACKSPACE);
checkResultByText(after);
@@ -327,6 +327,10 @@ combobox.paste.reformat.none=None
combobox.paste.reformat.indent.block=Indent Block
combobox.paste.reformat.indent.each.line=Indent Each Line
combobox.paste.reformat.reformat.block=Reformat Block
combobox.smart.backspace=Unindent:
combobox.smart.backspace.off=Off
combobox.smart.backspace.simple=Simple
combobox.smart.backspace.smart=Smart
combobox.tab.placement.none=None
combobox.tab.placement.top=Top
combobox.tab.placement.left=Left
@@ -74,6 +74,9 @@
interface="com.intellij.codeInsight.editorActions.JoinLinesHandlerDelegate"/>
<extensionPoint name="enterHandlerDelegate" interface="com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegate"/>
<extensionPoint name="backspaceHandlerDelegate" interface="com.intellij.codeInsight.editorActions.BackspaceHandlerDelegate"/>
<extensionPoint name="editor.backspaceModeOverride" beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.codeInsight.editorActions.BackspaceModeOverride"/>
</extensionPoint>
<extensionPoint name="codeStyleSettingsProvider"
interface="com.intellij.psi.codeStyle.CodeStyleSettingsProvider"/>
+1
View File
@@ -43,6 +43,7 @@
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PythonEnterHandler"/>
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PyEnterAtIndentHandler" order="first"/>
<enterHandlerDelegate implementation="com.jetbrains.python.editor.PyEnterBetweenBracketsHandler"/>
<editor.backspaceModeOverride language="Python" implementationClass="com.intellij.codeInsight.editorActions.SmartBackspaceDisabler"/>
<sdkType implementation="com.jetbrains.python.sdk.PythonSdkType"/>
<gotoClassContributor implementation="com.jetbrains.python.PyGotoClassContributor"/>
<gotoSymbolContributor implementation="com.jetbrains.python.PyGotoSymbolContributor"/>
@@ -124,11 +124,6 @@ public class PyLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettin
return PlatformUtils.isPyCharm() ? DisplayPriority.KEY_LANGUAGE_SETTINGS : DisplayPriority.LANGUAGE_SETTINGS;
}
@Override
public boolean isIndentBasedLanguageSemantics() {
return true;
}
@SuppressWarnings("FieldCanBeLocal")
private static String SPACING_SETTINGS_PREVIEW = "def settings_preview(argument, key=value):\n" +
" dict = {1:'a', 2:'b', 3:'c'}\n" +