Skip to content

Add the ability to manually format Javascript code (#87) #90

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import com.mirth.connect.client.ui.components.rsta.actions.ExpandFoldAction;
import com.mirth.connect.client.ui.components.rsta.actions.FindNextAction;
import com.mirth.connect.client.ui.components.rsta.actions.FindReplaceAction;
import com.mirth.connect.client.ui.components.rsta.actions.FormatCodeAction;
import com.mirth.connect.client.ui.components.rsta.actions.GoToMatchingBracketAction;
import com.mirth.connect.client.ui.components.rsta.actions.HorizontalPageAction;
import com.mirth.connect.client.ui.components.rsta.actions.InsertBreakAction;
Expand Down Expand Up @@ -127,6 +128,9 @@ public class MirthRSyntaxTextArea extends RSyntaxTextArea implements MirthTextIn
private CustomJCheckBoxMenuItem showWhitespaceMenuItem;
private CustomJCheckBoxMenuItem showLineEndingsMenuItem;
private CustomJCheckBoxMenuItem wrapLinesMenuItem;
private JMenu codeMenu;
private CustomMenuItem formatCodeMenuItem;
private CustomMenuItem toggleCommentMenuItem;
private JMenu macroMenu;
private CustomMenuItem beginMacroMenuItem;
private CustomMenuItem endMacroMenuItem;
Expand Down Expand Up @@ -228,6 +232,9 @@ public void keyPressed(KeyEvent e) {
showWhitespaceMenuItem = new CustomJCheckBoxMenuItem(this, new ShowWhitespaceAction(this), ActionInfo.DISPLAY_SHOW_WHITESPACE);
showLineEndingsMenuItem = new CustomJCheckBoxMenuItem(this, new ShowLineEndingsAction(this), ActionInfo.DISPLAY_SHOW_LINE_ENDINGS);
wrapLinesMenuItem = new CustomJCheckBoxMenuItem(this, new WrapLinesAction(this), ActionInfo.DISPLAY_WRAP_LINES);
codeMenu = new JMenu("Code");
formatCodeMenuItem = new CustomMenuItem(this, new FormatCodeAction(this), ActionInfo.FORMAT_CODE);
toggleCommentMenuItem = new CustomMenuItem(this, new ToggleCommentAction(this), ActionInfo.TOGGLE_COMMENT);
macroMenu = new JMenu("Macro");
beginMacroMenuItem = new CustomMenuItem(this, new BeginMacroAction(), ActionInfo.MACRO_BEGIN);
endMacroMenuItem = new CustomMenuItem(this, new EndMacroAction(), ActionInfo.MACRO_END);
Expand All @@ -239,7 +246,8 @@ public void keyPressed(KeyEvent e) {
getActionMap().put(ActionInfo.DELETE_LINE.getActionMapKey(), new DeleteLineAction());
getActionMap().put(ActionInfo.JOIN_LINE.getActionMapKey(), new JoinLineAction());
getActionMap().put(ActionInfo.GO_TO_MATCHING_BRACKET.getActionMapKey(), new GoToMatchingBracketAction());
getActionMap().put(ActionInfo.TOGGLE_COMMENT.getActionMapKey(), new ToggleCommentAction());
getActionMap().put(ActionInfo.FORMAT_CODE.getActionMapKey(), new FormatCodeAction(this));
getActionMap().put(ActionInfo.TOGGLE_COMMENT.getActionMapKey(), new ToggleCommentAction(this));
getActionMap().put(ActionInfo.DOCUMENT_START.getActionMapKey(), new DocumentStartAction(false));
getActionMap().put(ActionInfo.DOCUMENT_SELECT_START.getActionMapKey(), new DocumentStartAction(true));
getActionMap().put(ActionInfo.DOCUMENT_END.getActionMapKey(), new DocumentEndAction(false));
Expand Down Expand Up @@ -489,6 +497,11 @@ protected JPopupMenu createPopupMenu() {
menu.add(displayMenu);
menu.addSeparator();

codeMenu.add(formatCodeMenuItem);
codeMenu.add(toggleCommentMenuItem);
menu.add(codeMenu);
menu.addSeparator();

macroMenu.add(beginMacroMenuItem);
macroMenu.add(endMacroMenuItem);
macroMenu.add(playbackMacroMenuItem);
Expand All @@ -514,6 +527,8 @@ protected void configurePopupMenu(JPopupMenu popupMenu) {
findNextMenuItem.setEnabled(findNextMenuItem.getAction().isEnabled() && CollectionUtils.isNotEmpty(rstaPreferences.getFindReplaceProperties().getFindHistory()));
clearMarkedOccurrencesMenuItem.setEnabled(clearMarkedOccurrencesMenuItem.getAction().isEnabled() && canType && ((RSyntaxTextAreaHighlighter) getHighlighter()).getMarkAllHighlightCount() > 0);
foldingMenu.setEnabled(getFoldManager().isCodeFoldingSupportedAndEnabled());
formatCodeMenuItem.setEnabled(formatCodeMenuItem.getAction().isEnabled());
toggleCommentMenuItem.setEnabled(toggleCommentMenuItem.getAction().isEnabled());
beginMacroMenuItem.setEnabled(!isRecordingMacro());
endMacroMenuItem.setEnabled(isRecordingMacro());
playbackMacroMenuItem.setEnabled(!isRecordingMacro() && getCurrentMacro() != null);
Expand All @@ -533,6 +548,8 @@ protected void configurePopupMenu(JPopupMenu popupMenu) {
collapseAllFoldsMenuItem.updateAccelerator();
collapseAllCommentFoldsMenuItem.updateAccelerator();
expandAllFoldsMenuItem.updateAccelerator();
formatCodeMenuItem.updateAccelerator();
toggleCommentMenuItem.updateAccelerator();
beginMacroMenuItem.updateAccelerator();
endMacroMenuItem.updateAccelerator();
playbackMacroMenuItem.updateAccelerator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ TOGGLE_COMMENT.Name=Toggle Comment
TOGGLE_COMMENT.Desc=Comments / uncomments the current selected line(s).
TOGGLE_COMMENT.Toggle=false

FORMAT_CODE.Mnemonic=F
FORMAT_CODE.Name=Format
FORMAT_CODE.Desc=Format the current script / selected line(s).
FORMAT_CODE.Toggle=false

VIEW_USER_API.Mnemonic=V
VIEW_USER_API.Name=View User API
VIEW_USER_API.Desc=Opens up the User API Javadoc in a browser.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ private void setDefaultKeyStrokeMap() {
putKeyStroke(ActionInfo.FOLD_EXPAND_ALL, KeyEvent.VK_MULTIPLY, defaultModifier);
putKeyStroke(ActionInfo.GO_TO_MATCHING_BRACKET, KeyEvent.VK_OPEN_BRACKET, defaultModifier);
putKeyStroke(ActionInfo.TOGGLE_COMMENT, KeyEvent.VK_SLASH, defaultModifier);
putKeyStroke(ActionInfo.FORMAT_CODE, KeyEvent.VK_F, ctrl + shift);
putKeyStroke(ActionInfo.AUTO_COMPLETE, KeyEvent.VK_SPACE, ctrl);

if (isOSX) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public enum ActionInfo {
DISPLAY_WRAP_LINES ("mirth-wrap-lines"),
GO_TO_MATCHING_BRACKET (RSyntaxTextAreaEditorKit.rstaGoToMatchingBracketAction),
TOGGLE_COMMENT (RSyntaxTextAreaEditorKit.rstaToggleCommentAction),
FORMAT_CODE ("mirth-format-code"),
VIEW_USER_API ("mirth-view-user-api"),
AUTO_COMPLETE ("AutoComplete"),
DOCUMENT_START (DefaultEditorKit.beginAction),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) Mirth Corporation. All rights reserved.
*
* http://www.mirthcorp.com
*
* The software in this package is published under the terms of the MPL license a copy of which has
* been included with this distribution in the LICENSE.txt file.
*/

package com.mirth.connect.client.ui.components.rsta.actions;

import java.awt.event.ActionEvent;

import javax.swing.UIManager;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.Element;

import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;

import com.mirth.connect.client.ui.components.rsta.MirthRSyntaxTextArea;
import com.mirth.connect.util.JavaScriptSharedUtil;

public class FormatCodeAction extends MirthRecordableTextAction {

public FormatCodeAction(MirthRSyntaxTextArea textArea) {
super(textArea, ActionInfo.FORMAT_CODE);
}

@Override
public void actionPerformedImpl(ActionEvent evt) {

if (!textArea.isEditable() || !textArea.isEnabled()) {
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
return;
}

Caret c = textArea.getCaret();
int start = Math.min(c.getDot(), c.getMark());
int end = Math.max(c.getDot(), c.getMark());
if (start == end) {
formatAll();
} else {
formatRange(start, end);
}

}

@Override
public boolean isEnabled() {
return textArea.isEditable() && textArea.isEnabled();
}

private void formatAll() {

String code = textArea.getText();
formatAndReplace(code, 0, code.length());
}

private void formatRange(int start, int end) {

// We want to format all the lines of the selection (not only the selected text)

try {
RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument();
Element map = doc.getDefaultRootElement();

// Get the lines indexes from the selected text indexes.
int startLine = map.getElementIndex(start);
int endLine = map.getElementIndex(end);

int replaceRangeStart = 0;
int replaceRangeEnd = 0;

// Build a string from the selected lines.
StringBuilder sb = new StringBuilder();
for (int line = startLine; line <= endLine; line++) {
Element elem = map.getElement(line);

int startOffset = elem.getStartOffset();
int endOffset = elem.getEndOffset() - 1;

// Save the start index of the first line for the final replacement.
if (line == startLine) {
replaceRangeStart = startOffset;
}

// Save the end index of the last line for the final replacement.
if (line == endLine) {
replaceRangeEnd = endOffset;
}

sb.append(doc.getText(startOffset, endOffset - startOffset + 1));
}

// Format the code and replace the selected lines.
formatAndReplace(sb.toString(), replaceRangeStart, replaceRangeEnd);

} catch (BadLocationException ble) {
ble.printStackTrace();
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
}
}

private void formatAndReplace(String code, int start, int end) {

String formattedCode = JavaScriptSharedUtil.prettyPrint(code);
textArea.replaceRange(formattedCode, start, end);
textArea.setCaretPosition(start);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,16 @@

public class ToggleCommentAction extends org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit.ToggleCommentAction {

public ToggleCommentAction() {
protected MirthRSyntaxTextArea textArea;

public ToggleCommentAction(MirthRSyntaxTextArea textArea) {
setProperties(MirthRSyntaxTextArea.getResourceBundle(), ActionInfo.TOGGLE_COMMENT.toString());

this.textArea = textArea;
}

@Override
public boolean isEnabled() {
return textArea.isEditable() && textArea.isEnabled();
}
}
6 changes: 3 additions & 3 deletions server/src/com/mirth/connect/util/JavaScriptSharedUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,14 +196,14 @@ public static String prettyPrint(String script) {
private static ScriptableObject getFormatterScope() {
Context context = getGlobalContextForValidation();
InputStream is = null;

try {
is = JavaScriptSharedUtil.class.getResourceAsStream("beautify-1.6.8.js");
is = JavaScriptSharedUtil.class.getResourceAsStream("beautify-1.15.3.js");
String script = IOUtils.toString(is);
ScriptableObject scope = context.initStandardObjects();
context.evaluateString(scope, "var global = {};", UUID.randomUUID().toString(), 1, null);
context.evaluateString(scope, script, UUID.randomUUID().toString(), 1, null);
context.evaluateString(scope, "var opts = { 'e4x': true };", UUID.randomUUID().toString(), 1, null);
context.evaluateString(scope, "var opts = { 'e4x': true, 'indent_with_tabs': true };", UUID.randomUUID().toString(), 1, null);
return scope;
} catch (Exception e) {
logger.error("Failed to load beautify library.");
Expand Down
Loading