Skip to content
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

Fix #570 [clean branch] #589

Merged
merged 7 commits into from
Dec 21, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -2213,91 +2213,139 @@ public void actionPerformedImpl(ActionEvent e, RTextArea textArea) {
return;
}

RSyntaxDocument doc = (RSyntaxDocument)textArea.getDocument();
RSyntaxDocument doc = (RSyntaxDocument) textArea.getDocument();
Element map = doc.getDefaultRootElement();
Caret c = textArea.getCaret();
int dot = c.getDot();
int mark = c.getMark();
int line1 = map.getElementIndex(dot);
int line2 = map.getElementIndex(mark);
int start = Math.min(line1, line2);
int end = Math.max(line1, line2);
int end = Math.max(line1, line2);

Token t = doc.getTokenListForLine(start);
int languageIndex = t!=null ? t.getLanguageIndex() : 0;
int languageIndex = t != null ? t.getLanguageIndex() : 0;
String[] startEnd = doc.getLineCommentStartAndEnd(languageIndex);

if (startEnd==null) {
if (startEnd == null) {
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
return;
}

// Don't toggle comment on last line if there is no
// text selected on it.
if (start!=end) {
if (start != end) {
Element elem = map.getElement(end);
if (Math.max(dot, mark)==elem.getStartOffset()) {
if (Math.max(dot, mark) == elem.getStartOffset()) {
end--;
}
}

textArea.beginAtomicEdit();
try {
boolean add = getDoAdd(doc,map, start,end, startEnd);
for (line1=start; line1<=end; line1++) {
for (line1 = end; line1 >= start; line1--) {
Element elem = map.getElement(line1);
handleToggleComment(elem, doc, startEnd, add);
String lineText = doc.getText(elem.getStartOffset(),
elem.getEndOffset() - elem.getStartOffset() - 1);
int[] pos = searchMarkers(lineText, startEnd);
handleToggleComment(elem, doc, lineText, startEnd, pos);
}
} catch (BadLocationException ble) {
ble.printStackTrace();
UIManager.getLookAndFeel().provideErrorFeedback(textArea);
} finally {
textArea.endAtomicEdit();
}

}

private boolean getDoAdd(Document doc, Element map, int startLine,
int endLine, String[] startEnd)
throws BadLocationException {
boolean doAdd = false;
for (int i=startLine; i<=endLine; i++) {
Element elem = map.getElement(i);
int start = elem.getStartOffset();
String t = doc.getText(start, elem.getEndOffset()-start-1);
if (!t.startsWith(startEnd[0]) ||
(startEnd[1]!=null && !t.endsWith(startEnd[1]))) {
doAdd = true;
/**
* Search the end-comment mark, skipping trailing whitespaces.
*
* @param text The line text.
* @param startEnd The start/end comment marks.
* @return The index of the mark if present, otherwise -1.
*/
int endMatch(String text, String[] startEnd) {
if (startEnd[1] == null) {
return -1;
}

char c;
int i = text.length() - 1;

while (i >= 0) {
c = text.charAt(i);

if (!Character.isWhitespace(c)) {
break;
}

i--;
}

i = i - startEnd[1].length() + 1;

if (text.lastIndexOf(startEnd[1]) == i) {
return i;
} else {
return -1;
}
return doAdd;
}

private void handleToggleComment(Element elem, Document doc,
String[] startEnd, boolean add) throws BadLocationException {
int start = elem.getStartOffset();
int end = elem.getEndOffset() - 1;
if (add) {
if (startEnd[1]!=null) {
doc.insertString(end, startEnd[1], null);
}
doc.insertString(start, startEnd[0], null);
/**
* Search the start-comment mark, skipping leading whitespaces.
*
* @param text The line text.
* @param startEnd The start/end comment marks.
* @return The index of the mark if present, otherwise -1.
*/
int startMatch(String text, String[] startEnd) {
String ws = RSyntaxUtilities.getLeadingWhitespace(text);

if (text.indexOf(startEnd[0]) == ws.length()) {
return ws.length();
} else {
return -1;
}
else {
if (startEnd[1]!=null) {
int temp = startEnd[1].length();
doc.remove(end-temp, temp);
}

private int[] searchMarkers(String line, String[] startEnd) {
int startOffset = startMatch(line, startEnd);
int endOffset = endMatch(line, startEnd);

return new int[]{startOffset, endOffset};
}

private void handleToggleComment(Element elem, Document doc, String line, String[] startEnd, int[] pos)
throws BadLocationException {

int startOffset = elem.getStartOffset();

if (pos[0] >= 0 && ((pos[1] >= 0 && startEnd[1] != null) || (pos[1] < 0 && startEnd[1] == null))) {
// start-mark found (and also the end-mark for two-mark comments)
if (startEnd[1] != null && pos[1] >= 0) {
doc.remove(startOffset + pos[1], startEnd[1].length());
}
doc.remove(start, startEnd[0].length());

if (pos[0] >= 0) {
doc.remove(startOffset + pos[0], startEnd[0].length());
}
} else {
if (startEnd[1] != null) {
// add the mark after the last char of the line
doc.insertString(elem.getEndOffset() - 1, startEnd[1], null);
}

// insert the mark right before the first non-ws char
int n = RSyntaxUtilities.getLeadingWhitespace(line).length();
doc.insertString(startOffset + n, startEnd[0], null);
}
}

@Override
public final String getMacroID() {
return rstaToggleCommentAction;
}

}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import java.awt.event.ActionEvent;


/**
* Unit tests for the {@link RSyntaxTextAreaEditorKit.ToggleCommentAction} class.
Expand Down Expand Up @@ -144,4 +146,76 @@ void testGetMacroID() {
Assertions.assertEquals(RSyntaxTextAreaEditorKit.rstaToggleCommentAction,
new RSyntaxTextAreaEditorKit.ToggleCommentAction().getMacroID());
}
}

@Test
void testLeadingTrailingWhitespaces() {
RSyntaxTextAreaEditorKit.ToggleCommentAction commentAction = new RSyntaxTextAreaEditorKit.ToggleCommentAction();
RSyntaxTextArea textArea = createTextArea(SyntaxConstants.SYNTAX_STYLE_C, "");
ActionEvent e = new ActionEvent(textArea, 0, "command");

// multiline with leading WS
textArea.setText(" //line 1\n//line 2\nline 3");
textArea.setCaretPosition(2);
textArea.moveCaretPosition(15);

commentAction.actionPerformedImpl(e, textArea);

String expectedText = " line 1\nline 2\nline 3";
Assertions.assertEquals(expectedText, textArea.getText());

// start/end marks and leading and trailing WS
textArea.setText(" <!-- xml --> ");
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
textArea.setCaretPosition(0);
textArea.moveCaretPosition(0);

commentAction.actionPerformedImpl(e, textArea);

expectedText = " xml ";
Assertions.assertEquals(expectedText, textArea.getText());

// comment
textArea.setText(" int a = 2; ");
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVA);
textArea.setCaretPosition(0);
textArea.moveCaretPosition(5);

commentAction.actionPerformedImpl(e, textArea);

expectedText = " //int a = 2; ";
Assertions.assertEquals(expectedText, textArea.getText());

// multiline with leading and trailing WS and start/end marks
textArea.setText(" <!-- line 1 -->\n<!--line 2 --> ");
textArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_XML);
textArea.setCaretPosition(0);
textArea.moveCaretPosition(textArea.getDocument().getLength());

commentAction.actionPerformedImpl(e, textArea);

expectedText = " line 1 \nline 2 ";
Assertions.assertEquals(expectedText, textArea.getText());
}

/**
* Test for {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit.ToggleCommentAction#startMatch(String, String[])}
* and {@link org.fife.ui.rsyntaxtextarea.RSyntaxTextAreaEditorKit.ToggleCommentAction#endMatch(String, String[])}
*/
@Test
void startEndSearch() {
String[] markers = {"<!--", "-->"};
RSyntaxTextAreaEditorKit.ToggleCommentAction action = new RSyntaxTextAreaEditorKit.ToggleCommentAction();

Assertions.assertEquals(0, action.startMatch("<!-- text -->", markers));
Assertions.assertEquals(2, action.startMatch(" <!-- text -->", markers));
Assertions.assertEquals(-1, action.startMatch("// text", markers));
Assertions.assertEquals(-1, action.startMatch(" // text", markers));
Assertions.assertEquals(-1, action.startMatch("", markers));

Assertions.assertEquals(10, action.endMatch("<!-- text -->", markers));
Assertions.assertEquals(12, action.endMatch(" <!-- text -->", markers));
Assertions.assertEquals(-1, action.endMatch("// text", markers));
Assertions.assertEquals(-1, action.endMatch(" // text", markers));
Assertions.assertEquals(-1, action.endMatch("", markers));
}
}
Loading