blob: b4839abc02664f437ca9b1ca212c65718632f0ef [file] [log] [blame]
/*
* 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.
*/
/*
* Created by IntelliJ IDEA.
* User: max
* Date: May 14, 2002
* Time: 7:18:30 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.actionSystem.DataContext;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntIntHashMap;
import org.jetbrains.annotations.NotNull;
public class DeleteToWordStartAction extends TextComponentEditorAction {
/**
* We need to provide special processing for quote symbols.
* <p/>
* Examples:
* <table border='1'>
* <tr>
* <th>Text before action call</td>
* <th>Text after action call</td>
* </tr>
* <tr>
* <td>one "two" [caret]</td>
* <td>one [caret]</td>
* </tr>
* <tr>
* <td>one "two[caret]"</td>
* <td>one "[caret]"</td>
* </tr>
* </table>
*/
private static final TIntHashSet QUOTE_SYMBOLS = new TIntHashSet();
static {
QUOTE_SYMBOLS.add('\'');
QUOTE_SYMBOLS.add('\"');
}
private static final int[] QUOTE_SYMBOLS_ARRAY = QUOTE_SYMBOLS.toArray();
public DeleteToWordStartAction() {
super(new Handler(false));
}
static class Handler extends EditorWriteActionHandler {
@NotNull private final TIntIntHashMap myQuotesNumber = new TIntIntHashMap();
private final boolean myNegateCamelMode;
Handler(boolean negateCamelMode) {
super(true);
myNegateCamelMode = negateCamelMode;
}
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
if (editor.getSelectionModel().hasSelection()) {
BackspaceAction.doBackspaceAction(editor);
return;
}
deleteToWordStart(editor);
}
private void deleteToWordStart(Editor editor) {
boolean camel = editor.getSettings().isCamelWords();
if (myNegateCamelMode) {
camel = !camel;
}
CharSequence text = editor.getDocument().getCharsSequence();
CaretModel caretModel = editor.getCaretModel();
int endOffset = caretModel.getOffset();
int minOffset = editor.getDocument().getLineStartOffset(caretModel.getLogicalPosition().line);
myQuotesNumber.clear();
for (int i : QUOTE_SYMBOLS_ARRAY) {
myQuotesNumber.put(i, 0);
}
countQuotes(myQuotesNumber, text, minOffset, endOffset);
EditorActionUtil.moveCaretToPreviousWord(editor, false, camel);
for (int offset = caretModel.getOffset(); offset > minOffset; offset = caretModel.getOffset()) {
char previous = text.charAt(offset - 1);
char current = text.charAt(offset);
if (QUOTE_SYMBOLS.contains(current)) {
if (Character.isWhitespace(previous)) {
break;
}
else if (offset < endOffset - 1 && !Character.isJavaIdentifierPart(text.charAt(offset + 1))) {
// Handle a situation like ' "one", "two", [caret] '. We want to delete up to the previous literal end here.
editor.getCaretModel().moveToOffset(offset + 1);
break;
}
if (myQuotesNumber.get(current) % 2 == 0) {
// Was 'one "two" [caret]', now 'one "two[caret]"', we want to get 'one [caret]"two"'
EditorActionUtil.moveCaretToPreviousWord(editor, false, camel);
continue;
}
break;
}
if (QUOTE_SYMBOLS.contains(previous)) {
if (myQuotesNumber.get(previous) % 2 == 0) {
// Was 'one "two[caret]", now 'one "[caret]two"', we want 'one [caret]"two"'
editor.getCaretModel().moveToOffset(offset - 1);
}
}
break;
}
int startOffset = caretModel.getOffset();
Document document = editor.getDocument();
document.deleteString(startOffset, endOffset);
}
}
private static void countQuotes(@NotNull TIntIntHashMap holder, @NotNull CharSequence text, int start, int end) {
for (int i = end - 1; i >= start; i--) {
char c = text.charAt(i);
if (holder.containsKey(c)) {
holder.put(c, holder.get(c) + 1);
}
}
}
}