From 284107e1eb28c9499a30ba093559ce0f7b951c01 Mon Sep 17 00:00:00 2001 From: lathapatil Date: Mon, 8 Jul 2024 12:14:52 +0530 Subject: [PATCH] Typing open bracket should surround the selected text with brackets Review points incorporated --- .../text/SurroundWithBracketsStrategy.java | 66 +++++++++++++++++++ .../jface/text/source/SourceViewer.java | 12 +++- .../jface/text/tests/TextViewerTest.java | 22 ++++++- 3 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/SurroundWithBracketsStrategy.java diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/SurroundWithBracketsStrategy.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/SurroundWithBracketsStrategy.java new file mode 100644 index 00000000000..91bed183f44 --- /dev/null +++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/SurroundWithBracketsStrategy.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) ETAS GmbH 2024, all rights reserved. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * ETAS GmbH - initial API and implementation + *******************************************************************************/ +package org.eclipse.jface.text; + +import java.util.Map; + +import org.eclipse.swt.SWT; + +import org.eclipse.jface.text.source.ISourceViewer; + +/** + * @since 3.26 This strategy supports surrounding the selected text with similar opening and closing + * brackets when the text is selected and an opening bracket is inserted. + */ +public class SurroundWithBracketsStrategy implements IAutoEditStrategy { + + private ISourceViewer sourceViewer; + + @SuppressWarnings("nls") + private final Map bracketsMap= Map.of("(", ")", "[", "]", "{", "}", "<", ">", "\"", "\"", "'", "'", "`", "`"); + + public SurroundWithBracketsStrategy(ISourceViewer sourceViewer) { + this.sourceViewer= sourceViewer; + } + + @Override + public void customizeDocumentCommand(IDocument document, DocumentCommand command) { + if (bracketsMap.containsKey(command.text)) { + try { + ITextSelection selection= (ITextSelection) sourceViewer.getSelectionProvider().getSelection(); + if (selection != null && selection.getLength() > 0) { + String selectedText= document.get(selection.getOffset(), selection.getLength()); + String closingBracket= bracketsMap.get(command.text); + command.text= command.text + selectedText + closingBracket; + command.offset= selection.getOffset(); + command.length= selection.getLength(); + + // Set the caret offset after the opening bracket but before the closing bracket + command.caretOffset= command.offset + command.text.length() - closingBracket.length(); + command.shiftsCaret= false; + + // Run this in a UI thread asynchronously to ensure the selection is updated correctly + sourceViewer.getTextWidget().getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + sourceViewer.setSelectedRange(command.offset + 1, selectedText.length()); + } + }); + } + } catch (BadLocationException e) { + SWT.error(SWT.ERROR_INVALID_ARGUMENT); + } + } + } +} diff --git a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java index af5eae570c9..527a9d1891c 100644 --- a/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java +++ b/bundles/org.eclipse.jface.text/src/org/eclipse/jface/text/source/SourceViewer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2016 IBM Corporation and others. + * Copyright (c) 2000, 2024 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,10 +14,12 @@ * Tom Hofmann (Perspectix AG) - bug 297572 * Sergey Prigogin (Google) - bug 441448 * Angelo Zerr - [CodeMining] Add CodeMining support in SourceViewer - Bug 527515 + * Latha Patil (ETAS GmbH) - Issue 865 - Surround the selected text with brackets on inserting a opening bracket *******************************************************************************/ package org.eclipse.jface.text.source; import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Stack; @@ -57,6 +59,7 @@ import org.eclipse.jface.text.ITextViewerLifecycle; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.Region; +import org.eclipse.jface.text.SurroundWithBracketsStrategy; import org.eclipse.jface.text.TextViewer; import org.eclipse.jface.text.codemining.ICodeMiningProvider; import org.eclipse.jface.text.contentassist.IContentAssistant; @@ -543,7 +546,12 @@ public void configure(SourceViewerConfiguration configuration) { String[] types= configuration.getConfiguredContentTypes(this); for (String t : types) { - doSetAutoEditStrategies(configuration.getAutoEditStrategies(this, t), t); + IAutoEditStrategy[] autoEditStrategies= configuration.getAutoEditStrategies(this, t); + List autoEditStrategiesList= new ArrayList<>(Arrays.asList(autoEditStrategies)); + autoEditStrategiesList.add(new SurroundWithBracketsStrategy(this)); + IAutoEditStrategy[] newStrategies= autoEditStrategiesList.toArray(new IAutoEditStrategy[0]); + + doSetAutoEditStrategies(newStrategies, t); setTextDoubleClickStrategy(configuration.getDoubleClickStrategy(this, t), t); int[] stateMasks= configuration.getConfiguredTextHoverStateMasks(this, t); diff --git a/tests/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/TextViewerTest.java b/tests/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/TextViewerTest.java index 9fe54f86b56..45c3f9a1f23 100644 --- a/tests/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/TextViewerTest.java +++ b/tests/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/TextViewerTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2019 Google, Inc and others. + * Copyright (c) 2014, 2024 Google, Inc and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -12,6 +12,7 @@ * Sergey Prigogin (Google) - initial API and implementation * Mickael Istria (Red Hat Inc.) - [Bug 544708] Ctrl+Home * Paul Pazderski - [Bug 545530] Test for TextViewer's default IDocumentAdapter implementation. + * Latha Patil (ETAS GmbH) - Issue 865 - Test for Surround the selected text with brackets *******************************************************************************/ package org.eclipse.jface.text.tests; @@ -69,6 +70,7 @@ import org.eclipse.jface.text.hyperlink.URLHyperlink; import org.eclipse.jface.text.hyperlink.URLHyperlinkDetector; import org.eclipse.jface.text.source.SourceViewer; +import org.eclipse.jface.text.source.SourceViewerConfiguration; import org.eclipse.jface.text.tests.util.DisplayHelper; /** @@ -454,4 +456,20 @@ public void testSelectionFromViewerState() { textSelection= (ITextSelection) textViewer.getSelection(); assertEquals(113, textSelection.getOffset()); } -} + + @Test + public void testSurroundwithBracketsStrategy() { + fShell= new Shell(); + final SourceViewer sourceViewer= new SourceViewer(fShell, null, SWT.NONE); + sourceViewer.configure(new SourceViewerConfiguration()); + sourceViewer.setDocument(new Document("Test sample to surround the selected text with brackets")); + StyledText text= sourceViewer.getTextWidget(); + text.setText("Test sample to surround the selected text with brackets"); + text.setSelection(15, 23); + assertEquals(23, text.getCaretOffset()); + assertEquals("surround", text.getSelectionText()); + text.insert("["); + assertEquals("Test sample to [surround] the selected text with brackets", text.getText()); + assertEquals(24, text.getCaretOffset()); + } +} \ No newline at end of file