Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ Allows to disable some conversions or change their order in the preferences.

Please see this example for a demonstration:

![Demonstration](https://raw.githubusercontent.com/netnexus/camelcaseplugin/assets/example.gif)
![Demonstration](https://github.com/user-attachments/assets/72001e9b-402d-4971-8a82-3375c70d858d)

## Install
Use your IDE. Preferences/Plugins/Browse repositories and search for "camelcase".

## Build
Just clone this repo and open the project it in IntelliJ IDEA.
Just clone this repo and open the project it in IntelliJ IDEA.
12 changes: 10 additions & 2 deletions src/de/netnexus/CamelCasePlugin/CamelCaseConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ public class CamelCaseConfig implements PersistentStateComponent<CamelCaseConfig
"camelCase",
"snake_case",
"space case",
"Camel Case",};
"Camel Case",
};
public String[] activeModel = model;


CamelCaseConfig() {
Expand Down Expand Up @@ -98,11 +100,17 @@ public boolean getcb7State() {
public String[] getmodel() {
return model;
}

public void setListModel(String[] model) {
this.model = model;
}

public String[] getActiveModel() {
return activeModel;
}

public void setActiveModel(String[] model) {
this.activeModel = model;
}
@Nullable
@Override
public CamelCaseConfig getState() {
Expand Down
153 changes: 79 additions & 74 deletions src/de/netnexus/CamelCasePlugin/CamelCaseEditorActionHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,30 @@
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.util.ThrowableRunnable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.Arrays;
import java.util.regex.Pattern;

import static de.netnexus.CamelCasePlugin.Conversion.*;

public class CamelCaseEditorActionHandler<T> extends EditorActionHandler {

CamelCaseEditorActionHandler() {
super(true);
}

private static void replaceText(final Editor editor, final String replacement) {

try {
WriteAction.run((ThrowableRunnable<Throwable>) () -> {
int start = editor.getSelectionModel().getSelectionStart();
EditorModificationUtil.insertStringAtCaret(editor, replacement);
editor.getSelectionModel().setSelection(start, start + replacement.length());
});
} catch (Throwable ignored) {

}
super(false);
}

@Override
protected final void doExecute(@NotNull final Editor editor, @Nullable final Caret caret, final DataContext dataContext) {

final Pair<Boolean, T> additionalParameter = beforeWriteAction(editor);
if (!additionalParameter.first) {
return;
Expand All @@ -57,81 +41,102 @@ public void executeWriteAction(@NotNull Editor editor1, @Nullable Caret caret1,

@NotNull
private Pair<Boolean, T> beforeWriteAction(Editor editor) {
String text = editor.getSelectionModel().getSelectedText();
String[] conversionList = ConversionList.toArray(new String[0]);
String[] activeConversionList = ConversionList.toArray(new String[0]);
Project project = editor.getProject();
if (project != null) {
CamelCaseConfig config = CamelCaseConfig.getInstance(project);
if (config != null && (config.getcb1State() || config.getcb2State() || config.getcb3State() || config.getcb4State() || config.getcb5State() || config.getcb6State())) {
activeConversionList = config.getActiveModel();
}
}

// Determine the target case type for the selected text(s).
// If all selected text with the same case type, target is set to the next case type in activeConversionList.
// Otherwise, target is set to the case which at last of selected text case type.
String target;
{
String commonCaseType = null;
String lastCaseType = null;
int lastIdx = -1;
for (Caret caret : editor.getCaretModel().getAllCarets()) {
String caseType = CaseType(selectedText(editor, caret));
commonCaseType = caseType;
int idx = Arrays.asList(conversionList).indexOf(caseType);
if (idx > lastIdx) {
lastCaseType = caseType;
lastIdx = idx;
}
}
if (lastCaseType == null) {
assert commonCaseType != null;
target = getNext(CaseType(commonCaseType), conversionList);
} else {
target = getNext(lastCaseType, conversionList);
}

// Make sure target is in activeConversionList
for (int i = 0; i < conversionList.length; i++) {
int idx = Arrays.asList(activeConversionList).indexOf(target);
if (idx != -1) {
break;
}
target = getNext(target, conversionList);
}
}

Document document = editor.getDocument();
for (Caret caret : editor.getCaretModel().getAllCarets()) {
String selected = caret.getSelectedText();
if (selected != null && !selected.isEmpty()) {
String newText = Conversion.transform(selected, target);

Runnable runnable = () -> document.replaceString(caret.getSelectionStart(), caret.getSelectionEnd(), newText);
ApplicationManager.getApplication().runWriteAction(getRunnableWrapper(project, runnable));
}
}

return continueExecution();
}

private String selectedText(Editor editor, Caret caret) {
String text = caret.getSelectedText();
if (text == null || text.isEmpty()) {
editor.getSelectionModel().selectWordAtCaret(true);
int start = caret.getOffset();
int end = start;
boolean moveLeft = true;
boolean moveRight = true;
int start = editor.getSelectionModel().getSelectionStart();
int end = editor.getSelectionModel().getSelectionEnd();
Pattern p = Pattern.compile("[^A-z0-9.\\-]");
Pattern p = Pattern.compile("[^A-Za-z0-9.\\-]");

// move caret left
while (moveLeft && start != 0) {
while (moveLeft && start > 0) {
start--;
EditorActionUtil.moveCaret(editor.getCaretModel().getCurrentCaret(), start, true);
Matcher m = p.matcher(Objects.requireNonNull(editor.getSelectionModel().getSelectedText()));
if (m.find()) {
caret.setSelection(start, end);
String selected = caret.getSelectedText();
if (selected == null || p.matcher(selected).find()) {
start++;
moveLeft = false;
}
}

editor.getSelectionModel().setSelection(end - 1, end);

// move caret right
while (moveRight && end != editor.getDocument().getTextLength()) {
while (moveRight && end < editor.getDocument().getTextLength()) {
end++;
EditorActionUtil.moveCaret(editor.getCaretModel().getCurrentCaret(), end, true);
Matcher m = p.matcher(Objects.requireNonNull(editor.getSelectionModel().getSelectedText()));
if (m.find()) {
caret.setSelection(start, end);
String selected = caret.getSelectedText();
if (selected == null || p.matcher(selected).find()) {
end--;
moveRight = false;
}
}
editor.getSelectionModel().setSelection(start, end);

text = editor.getSelectionModel().getSelectedText();
}
Project project = editor.getProject();

String newText;
if (project != null) {
CamelCaseConfig config = CamelCaseConfig.getInstance(project);
if (config != null && (config.getcb1State() || config.getcb2State() || config.getcb3State() || config.getcb4State() || config.getcb5State() || config.getcb6State())) {
newText = Conversion.transform(text, config.getcb7State(), // pascal case with space
config.getcb6State(), // space case
config.getcb1State(), // kebab case
config.getcb2State(), // upper snake case
config.getcb3State(), // pascal case
config.getcb4State(), // camel case
config.getcb5State(), // lower snake case
config.getmodel());
} else {
newText = this.runWithoutConfig(text);
}
} else {
newText = this.runWithoutConfig(text);
caret.setSelection(start, end);
text = caret.getSelectedText();
}

final Editor fEditor = editor;
final String fReplacement = newText;
Runnable runnable = () -> CamelCaseEditorActionHandler.replaceText(fEditor, fReplacement);
ApplicationManager.getApplication().runWriteAction(getRunnableWrapper(fEditor.getProject(), runnable));
return continueExecution();
return text;
}

private String runWithoutConfig(String text) {
String[] conversionList = {"kebab-case", "SNAKE_CASE", "CamelCase", "camelCase", "snake_case", "space case", "Camel Case"};
return Conversion.transform(text, true, // pascal case with space
true, // space case
true, // kebab case
true, // upper snake case
true, // pascal case
true, // camel case
true, // lower snake case
conversionList);
}

private Pair<Boolean, T> continueExecution() {
return new Pair<>(true, null);
Expand Down
Loading