mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-12 10:45:37 +02:00
Fix string double click selection
This commit is contained in:
parent
32163b8508
commit
bf61f08fdb
4 changed files with 142 additions and 216 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2000 2006 IBM Corporation and others.
|
* Copyright (c) 2000, 2007 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -12,7 +12,6 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.text;
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.ITextDoubleClickStrategy;
|
import org.eclipse.jface.text.ITextDoubleClickStrategy;
|
||||||
|
@ -23,111 +22,35 @@ import org.eclipse.jface.text.ITextViewer;
|
||||||
*/
|
*/
|
||||||
public class CDoubleClickSelector implements ITextDoubleClickStrategy {
|
public class CDoubleClickSelector implements ITextDoubleClickStrategy {
|
||||||
|
|
||||||
protected ITextViewer fText;
|
protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '<', '>'};
|
||||||
protected int fPos;
|
private CPairMatcher fPairMatcher= new CPairMatcher(fgBrackets);
|
||||||
protected int fStartPos;
|
|
||||||
protected int fEndPos;
|
|
||||||
private CPairMatcher fPairMatcher;
|
|
||||||
|
|
||||||
|
|
||||||
protected static char[] fgBrackets= {'{', '}', '(', ')', '[', ']', '"', '"'};
|
|
||||||
|
|
||||||
public CDoubleClickSelector() {
|
public CDoubleClickSelector() {
|
||||||
super();
|
super();
|
||||||
fPairMatcher= new CPairMatcher(fgBrackets);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
/**
|
* @see org.eclipse.jface.text.ITextDoubleClickStrategy#doubleClicked(org.eclipse.jface.text.ITextViewer)
|
||||||
* @see ITextDoubleClickStrategy#doubleClicked
|
|
||||||
*/
|
*/
|
||||||
public void doubleClicked(ITextViewer text) {
|
public void doubleClicked(ITextViewer textViewer) {
|
||||||
fPos= text.getSelectedRange().x;
|
int offset= textViewer.getSelectedRange().x;
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
if (fPos < 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
IDocument document= textViewer.getDocument();
|
||||||
|
|
||||||
fText= text;
|
IRegion region= fPairMatcher.match(document, offset);
|
||||||
|
if (region != null && region.getLength() >= 2) {
|
||||||
|
textViewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2);
|
||||||
if (!selectBracketBlock())
|
} else {
|
||||||
selectWord();
|
region= selectWord(document, offset);
|
||||||
|
textViewer.setSelectedRange(region.getOffset(), region.getLength());
|
||||||
fText= null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected boolean matchBracketsAt() {
|
|
||||||
IRegion region= fPairMatcher.match(fText.getDocument(), fPos);
|
|
||||||
if (region != null && region.getLength() > 0) {
|
|
||||||
fStartPos= region.getOffset();
|
|
||||||
fEndPos= fStartPos + region.getLength() - 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected boolean matchWord() {
|
|
||||||
IDocument doc= fText.getDocument();
|
|
||||||
try {
|
|
||||||
int pos= fPos;
|
|
||||||
char c;
|
|
||||||
|
|
||||||
|
|
||||||
while (pos >= 0) {
|
|
||||||
c= doc.getChar(pos);
|
|
||||||
if (!Character.isJavaIdentifierPart(c))
|
|
||||||
break;
|
|
||||||
--pos;
|
|
||||||
}
|
|
||||||
fStartPos= pos;
|
|
||||||
|
|
||||||
|
|
||||||
pos= fPos;
|
|
||||||
int length= doc.getLength();
|
|
||||||
|
|
||||||
|
|
||||||
while (pos < length) {
|
|
||||||
c= doc.getChar(pos);
|
|
||||||
if (!Character.isJavaIdentifierPart(c))
|
|
||||||
break;
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
fEndPos= pos;
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
|
|
||||||
} catch (BadLocationException x) {
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected boolean selectBracketBlock() {
|
|
||||||
if (matchBracketsAt()) {
|
|
||||||
if (fStartPos == fEndPos)
|
|
||||||
fText.setSelectedRange(fStartPos, 0);
|
|
||||||
else
|
|
||||||
fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
|
|
||||||
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void selectWord() {
|
|
||||||
if (matchWord()) {
|
|
||||||
if (fStartPos == fEndPos)
|
|
||||||
fText.setSelectedRange(fStartPos, 0);
|
|
||||||
else
|
|
||||||
fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected IRegion selectWord(IDocument document, int offset) {
|
||||||
|
return CWordFinder.findWord(document, offset);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2000 2006 IBM Corporation and others.
|
* Copyright (c) 2000, 2007 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -12,132 +12,17 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.text;
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
import org.eclipse.jface.text.BadLocationException;
|
import org.eclipse.jface.text.source.DefaultCharacterPairMatcher;
|
||||||
import org.eclipse.jface.text.IDocument;
|
|
||||||
import org.eclipse.jface.text.IRegion;
|
|
||||||
import org.eclipse.jface.text.Region;
|
|
||||||
import org.eclipse.jface.text.TextUtilities;
|
|
||||||
import org.eclipse.jface.text.source.ICharacterPairMatcher;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.ui.text.ICPartitions;
|
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for match pairs of characters.
|
* Helper class for match pairs of characters.
|
||||||
*/
|
*/
|
||||||
public class CPairMatcher implements ICharacterPairMatcher {
|
public class CPairMatcher extends DefaultCharacterPairMatcher {
|
||||||
|
|
||||||
protected char[] fPairs;
|
|
||||||
protected IDocument fDocument;
|
|
||||||
protected int fOffset;
|
|
||||||
|
|
||||||
protected int fStartPos;
|
|
||||||
protected int fEndPos;
|
|
||||||
protected int fAnchor;
|
|
||||||
|
|
||||||
public CPairMatcher(char[] pairs) {
|
public CPairMatcher(char[] pairs) {
|
||||||
fPairs = pairs;
|
super(pairs, ICPartitions.C_PARTITIONING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#match(org.eclipse.jface.text.IDocument, int)
|
|
||||||
*/
|
|
||||||
public IRegion match(IDocument document, int offset) {
|
|
||||||
|
|
||||||
fOffset = offset;
|
|
||||||
|
|
||||||
if (fOffset < 0)
|
|
||||||
return null;
|
|
||||||
|
|
||||||
fDocument = document;
|
|
||||||
|
|
||||||
if (matchPairsAt() && fStartPos != fEndPos)
|
|
||||||
return new Region(fStartPos, fEndPos - fStartPos + 1);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#getAnchor()
|
|
||||||
*/
|
|
||||||
public int getAnchor() {
|
|
||||||
return fAnchor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
|
|
||||||
*/
|
|
||||||
public void clear() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.jface.text.source.ICharacterPairMatcher#dispose()
|
|
||||||
*/
|
|
||||||
public void dispose() {
|
|
||||||
clear();
|
|
||||||
fDocument = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean matchPairsAt() {
|
|
||||||
|
|
||||||
int i;
|
|
||||||
int pairIndex1= fPairs.length;
|
|
||||||
int pairIndex2= fPairs.length;
|
|
||||||
|
|
||||||
fStartPos= -1;
|
|
||||||
fEndPos= -1;
|
|
||||||
|
|
||||||
// get the chars preceding and following the start position
|
|
||||||
try {
|
|
||||||
|
|
||||||
char prevChar= fDocument.getChar(Math.max(fOffset - 1, 0));
|
|
||||||
|
|
||||||
// search for opening peer character next to the activation point
|
|
||||||
for (i= 0; i < fPairs.length; i= i + 2) {
|
|
||||||
if (prevChar == fPairs[i]) {
|
|
||||||
fStartPos= fOffset - 1;
|
|
||||||
pairIndex1= i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// search for closing peer character next to the activation point
|
|
||||||
for (i= 1; i < fPairs.length; i= i + 2) {
|
|
||||||
if (prevChar == fPairs[i]) {
|
|
||||||
fEndPos= fOffset - 1;
|
|
||||||
pairIndex2= i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fEndPos > -1) {
|
|
||||||
fAnchor= RIGHT;
|
|
||||||
fStartPos= searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument);
|
|
||||||
if (fStartPos > -1)
|
|
||||||
return true;
|
|
||||||
fEndPos= -1;
|
|
||||||
} else if (fStartPos > -1) {
|
|
||||||
fAnchor= LEFT;
|
|
||||||
fEndPos= searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument);
|
|
||||||
if (fEndPos > -1)
|
|
||||||
return true;
|
|
||||||
fStartPos= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (BadLocationException x) {
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected int searchForClosingPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException {
|
|
||||||
CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false));
|
|
||||||
return scanner.findClosingPeer(offset + 1, openingPeer, closingPeer);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int searchForOpeningPeer(int offset, char openingPeer, char closingPeer, IDocument document) throws BadLocationException {
|
|
||||||
CHeuristicScanner scanner= new CHeuristicScanner(document, ICPartitions.C_PARTITIONING, TextUtilities.getContentType(document, ICPartitions.C_PARTITIONING, offset, false));
|
|
||||||
int peer= scanner.findOpeningPeer(offset - 1, openingPeer, closingPeer);
|
|
||||||
if (peer == CHeuristicScanner.NOT_FOUND)
|
|
||||||
return -1;
|
|
||||||
return peer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.eclipse.jface.dialogs.IDialogSettings;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.jface.text.AbstractInformationControlManager;
|
import org.eclipse.jface.text.AbstractInformationControlManager;
|
||||||
import org.eclipse.jface.text.DefaultInformationControl;
|
import org.eclipse.jface.text.DefaultInformationControl;
|
||||||
|
import org.eclipse.jface.text.DefaultTextDoubleClickStrategy;
|
||||||
import org.eclipse.jface.text.IAutoEditStrategy;
|
import org.eclipse.jface.text.IAutoEditStrategy;
|
||||||
import org.eclipse.jface.text.IDocument;
|
import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.IInformationControl;
|
import org.eclipse.jface.text.IInformationControl;
|
||||||
|
@ -451,6 +452,14 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
|
||||||
* @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer, String)
|
* @see SourceViewerConfiguration#getDoubleClickStrategy(ISourceViewer, String)
|
||||||
*/
|
*/
|
||||||
public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) {
|
public ITextDoubleClickStrategy getDoubleClickStrategy(ISourceViewer sourceViewer, String contentType) {
|
||||||
|
if (ICPartitions.C_MULTI_LINE_COMMENT.equals(contentType) ||
|
||||||
|
ICPartitions.C_SINGLE_LINE_COMMENT.equals(contentType))
|
||||||
|
return new DefaultTextDoubleClickStrategy();
|
||||||
|
else if (ICPartitions.C_STRING.equals(contentType) ||
|
||||||
|
ICPartitions.C_CHARACTER.equals(contentType))
|
||||||
|
return new CStringDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer));
|
||||||
|
else if (ICPartitions.C_PREPROCESSOR.equals(contentType))
|
||||||
|
return new CStringDoubleClickSelector(getConfiguredDocumentPartitioning(sourceViewer), new CDoubleClickSelector());
|
||||||
return new CDoubleClickSelector();
|
return new CDoubleClickSelector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2007 Wind River Systems, Inc. and others.
|
||||||
|
* All rights reserved. This program and the accompanying materials
|
||||||
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
* which accompanies this distribution, and is available at
|
||||||
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
*
|
||||||
|
* Contributors:
|
||||||
|
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
|
import org.eclipse.jface.text.Document;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.ITextDoubleClickStrategy;
|
||||||
|
import org.eclipse.jface.text.ITextViewer;
|
||||||
|
import org.eclipse.jface.text.ITypedRegion;
|
||||||
|
import org.eclipse.jface.text.Region;
|
||||||
|
import org.eclipse.jface.text.TextUtilities;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.CDocumentSetupParticipant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Double click strategy aware of string and character syntax rules.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class CStringDoubleClickSelector extends CDoubleClickSelector {
|
||||||
|
|
||||||
|
private String fPartitioning;
|
||||||
|
private ITextDoubleClickStrategy fFallbackStrategy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new string double click selector for the given document partitioning.
|
||||||
|
*
|
||||||
|
* @param partitioning the document partitioning
|
||||||
|
*/
|
||||||
|
public CStringDoubleClickSelector(String partitioning) {
|
||||||
|
this(partitioning, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new string double click selector for the given document partitioning.
|
||||||
|
*
|
||||||
|
* @param partitioning the document partitioning
|
||||||
|
* @param doubleClickStrategy the fallback double click strategy
|
||||||
|
*/
|
||||||
|
public CStringDoubleClickSelector(String partitioning,
|
||||||
|
ITextDoubleClickStrategy doubleClickStrategy) {
|
||||||
|
fPartitioning= partitioning;
|
||||||
|
fFallbackStrategy= doubleClickStrategy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see ITextDoubleClickStrategy#doubleClicked(ITextViewer)
|
||||||
|
*/
|
||||||
|
public void doubleClicked(ITextViewer textViewer) {
|
||||||
|
int offset= textViewer.getSelectedRange().x;
|
||||||
|
|
||||||
|
if (offset < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IDocument document= textViewer.getDocument();
|
||||||
|
|
||||||
|
IRegion region= matchString(document, offset);
|
||||||
|
if (region != null) {
|
||||||
|
if (region.getLength() >= 2) {
|
||||||
|
textViewer.setSelectedRange(region.getOffset() + 1, region.getLength() - 2);
|
||||||
|
}
|
||||||
|
} else if (fFallbackStrategy != null) {
|
||||||
|
fFallbackStrategy.doubleClicked(textViewer);
|
||||||
|
} else {
|
||||||
|
region= selectWord(document, offset);
|
||||||
|
if (region != null) {
|
||||||
|
textViewer.setSelectedRange(region.getOffset(), region.getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IRegion matchString(IDocument document, int offset) {
|
||||||
|
try {
|
||||||
|
if ((document.getChar(offset) == '"') || (document.getChar(offset) == '\'') ||
|
||||||
|
(document.getChar(offset - 1) == '"') || (document.getChar(offset - 1) == '\''))
|
||||||
|
{
|
||||||
|
ITypedRegion region= TextUtilities.getPartition(document, fPartitioning, offset, true);
|
||||||
|
// little hack: in case this strategy is used in preprocessor partitions, the string
|
||||||
|
// partition inside the preprocessor partition must be computed in an extra step
|
||||||
|
if (ICPartitions.C_PREPROCESSOR.equals(region.getType())) {
|
||||||
|
String ppDirective= document.get(region.getOffset(), region.getLength());
|
||||||
|
int hashIdx= ppDirective.indexOf('#');
|
||||||
|
document= new Document(ppDirective.substring(hashIdx+1));
|
||||||
|
new CDocumentSetupParticipant().setup(document);
|
||||||
|
int delta= region.getOffset() + hashIdx + 1;
|
||||||
|
region= TextUtilities.getPartition(document, fPartitioning, offset - delta, true);
|
||||||
|
return new Region(region.getOffset() + delta, region.getLength());
|
||||||
|
}
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue