blob: eb93f0da83549180660d497cbc7a81f2301cfb64 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.texteditor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ContextInformationValidator;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContentAssistProcessorExtension;
import org.eclipse.jface.text.contentassist.IContentAssistSubject;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
/**
* Content assist processor for regular expressions.
*
* @since 3.0
*/
final class RegExContentAssistProcessor implements IContentAssistProcessor, IContentAssistProcessorExtension {
/**
* The available proposal strings.
*/
private final static HashMap fgProposalStrings= new HashMap();
/**
* The available proposal keys.
*/
private final static ArrayList fgProposalKeys= new ArrayList();
static {
//---------- Proposal Keys ----------
fgProposalKeys.add("\\\\"); //$NON-NLS-1$
fgProposalKeys.add("\\0"); //$NON-NLS-1$
fgProposalKeys.add("\\x"); //$NON-NLS-1$
fgProposalKeys.add("\\u"); //$NON-NLS-1$
fgProposalKeys.add("\\t"); //$NON-NLS-1$
fgProposalKeys.add("\\n"); //$NON-NLS-1$
fgProposalKeys.add("\\r"); //$NON-NLS-1$
fgProposalKeys.add("\\f"); //$NON-NLS-1$
fgProposalKeys.add("\\a"); //$NON-NLS-1$
fgProposalKeys.add("\\e"); //$NON-NLS-1$
fgProposalKeys.add("\\c"); //$NON-NLS-1$
fgProposalKeys.add("."); //$NON-NLS-1$
fgProposalKeys.add("\\d"); //$NON-NLS-1$
fgProposalKeys.add("\\D"); //$NON-NLS-1$
fgProposalKeys.add("\\s"); //$NON-NLS-1$
fgProposalKeys.add("\\S"); //$NON-NLS-1$
fgProposalKeys.add("\\w"); //$NON-NLS-1$
fgProposalKeys.add("\\W"); //$NON-NLS-1$
fgProposalKeys.add("^"); //$NON-NLS-1$
fgProposalKeys.add("$"); //$NON-NLS-1$
fgProposalKeys.add("\\b"); //$NON-NLS-1$
fgProposalKeys.add("\\B"); //$NON-NLS-1$
fgProposalKeys.add("\\A"); //$NON-NLS-1$
fgProposalKeys.add("\\G"); //$NON-NLS-1$
// fgProposalKeys.add("\\Z"); //$NON-NLS-1$
fgProposalKeys.add("\\z"); //$NON-NLS-1$
fgProposalKeys.add("?"); //$NON-NLS-1$
fgProposalKeys.add("*"); //$NON-NLS-1$
fgProposalKeys.add("+"); //$NON-NLS-1$
fgProposalKeys.add("{n}"); //$NON-NLS-1$
fgProposalKeys.add("{n,}"); //$NON-NLS-1$
fgProposalKeys.add("{n,m}"); //$NON-NLS-1$
fgProposalKeys.add("??"); //$NON-NLS-1$
fgProposalKeys.add("*?"); //$NON-NLS-1$
fgProposalKeys.add("+?"); //$NON-NLS-1$
fgProposalKeys.add("{n}?"); //$NON-NLS-1$
fgProposalKeys.add("{n,}?"); //$NON-NLS-1$
fgProposalKeys.add("{n,m}?"); //$NON-NLS-1$
fgProposalKeys.add("?+"); //$NON-NLS-1$
fgProposalKeys.add("*+"); //$NON-NLS-1$
fgProposalKeys.add("++"); //$NON-NLS-1$
fgProposalKeys.add("{n}+"); //$NON-NLS-1$
fgProposalKeys.add("{n,}+"); //$NON-NLS-1$
fgProposalKeys.add("{n,m}+"); //$NON-NLS-1$
fgProposalKeys.add("UV"); //$NON-NLS-1$
fgProposalKeys.add("U|V"); //$NON-NLS-1$
fgProposalKeys.add("(U)"); //$NON-NLS-1$
fgProposalKeys.add("\\i"); //$NON-NLS-1$
fgProposalKeys.add("$i"); //$NON-NLS-1$
fgProposalKeys.add("\\"); //$NON-NLS-1$
fgProposalKeys.add("\\Q"); //$NON-NLS-1$
fgProposalKeys.add("\\E"); //$NON-NLS-1$
fgProposalKeys.add("[ecq]"); //$NON-NLS-1$
fgProposalKeys.add("[^ecq]"); //$NON-NLS-1$
fgProposalKeys.add("[e-q]"); //$NON-NLS-1$
fgProposalKeys.add("&&"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Lower}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Upper}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{ASCII}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Alpha}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Digit}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Alnum}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Punct}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Graph}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Print}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Blank}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Cntrl}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{XDigit}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Space}"); //$NON-NLS-1$
//
// fgProposalKeys.add("\\p{InGreek}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Lu}"); //$NON-NLS-1$
// fgProposalKeys.add("\\p{Sc}"); //$NON-NLS-1$
// fgProposalKeys.add("\\P{InGreek}"); //$NON-NLS-1$
// fgProposalKeys.add("[\\p{L}&&[^\\p{Lu}]"); //$NON-NLS-1$
// fgProposalKeys.add("(?idmsux-idmsux)"); //$NON-NLS-1$
// fgProposalKeys.add("(?idmsux-idmsux:U)"); //$NON-NLS-1$
// fgProposalKeys.add("(?:U)"); //$NON-NLS-1$
// fgProposalKeys.add("(?=U)"); //$NON-NLS-1$
// fgProposalKeys.add("(?!U)"); //$NON-NLS-1$
// fgProposalKeys.add("(?<=U)"); //$NON-NLS-1$
// fgProposalKeys.add("(?<!U)"); //$NON-NLS-1$
// fgProposalKeys.add("(?>U)"); //$NON-NLS-1$
//---------- Proposals ----------
fgProposalStrings.put("\\\\", "\\\\"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\0", "\\0"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\x", "\\x"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\u", "\\u"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\t", "\\t"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\n", "\\n"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\r", "\\r"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\f", "\\f"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\a", "\\a"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\e", "\\e"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\c", "\\c"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put(".", "."); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\d", "\\d"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\D", "\\D"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\s", "\\s"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\S", "\\S"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\w", "\\w"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\W", "\\W"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("^", "^"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("$", "$"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\b", "\\b"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\B", "\\B"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\A", "\\A"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\G", "\\G"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\Z", "\\Z"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\z", "\\z"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("?", "?"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("*", "*"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("+", "+"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n}", "{}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n,}", "{,}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n,m}", "{,}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("??", "??"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("*?", "*?"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("+?", "+?"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n}?", "{}?"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n,}?", "{,}?"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n,m}?", "{,}?"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("?+", "?+"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("*+", "*+"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("++", "++"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n}+", "{}+"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n,}+", "{,}+"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("{n,m}+", "{,}+"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("UV", ""); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("U|V", "|"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(U)", "()"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\i", "\\"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("$i", "$"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\", "\\"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\Q", "\\Q"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\E", "\\E"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("[ecq]", "[]"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("[^ecq]", "^"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("[e-q]", "[]"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("&&", "&&"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Lower}", "\\p{Lower}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Upper}", "\\p{Upper}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{ASCII}", "\\p{ASCII}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Alpha}", "\\p{Alpha}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Digit}", "\\p{Digit}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Alnum}", "\\p{Alnum}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Punct}", "\\p{Punct}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Graph}", "\\p{Graph}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Print}", "\\p{Print}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Blank}", "\\p{Blank}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Cntrl}", "\\p{Cntrl}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{XDigit}", "\\p{XDigit}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Space}", "\\p{Space}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{InGreek}", "\\p{InGreek}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Lu}", "\\p{Lu}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\p{Sc}", "\\p{Sc}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("\\P{InGreek}", "\\P{InGreek}"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("[\\p{L}&&[^\\p{Lu}]","[\\p{L}&&[^\\p{Lu}]"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?:U)", "(?:)"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?idmsux-idmsux)", "(?)"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?idmsux-idmsux:U)", "(?:)"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?=U)", "(?=)"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?!U)", "(?!)"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?<=U)", "(?<=)"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?<!U)", "(?<!)"); //$NON-NLS-1$ //$NON-NLS-2$
fgProposalStrings.put("(?>U)", "(?>)"); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* The context information validator.
*/
private IContextInformationValidator fValidator= new ContextInformationValidator(this);
/*
* @see IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)
*/
public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int documentOffset) {
return computeCompletionProposals((IContentAssistSubject)null, documentOffset);
}
/*
* @see IContentAssistProcessor#computeContextInformation(ITextViewer, int)
*/
public IContextInformation[] computeContextInformation(ITextViewer viewer, int documentOffset) {
return computeContextInformation((IContentAssistSubject)null, documentOffset);
}
/*
* @see IContentAssistProcessor#getCompletionProposalAutoActivationCharacters()
*/
public char[] getCompletionProposalAutoActivationCharacters() {
return new char[] {'\\', '[', '('};
}
/*
* @see IContentAssistProcessor#getContextInformationAutoActivationCharacters()
*/
public char[] getContextInformationAutoActivationCharacters() {
return new char[] { };
}
/*
* @see IContentAssistProcessor#getContextInformationValidator()
*/
public IContextInformationValidator getContextInformationValidator() {
return fValidator;
}
/*
* @see IContentAssistProcessor#getErrorMessage()
*/
public String getErrorMessage() {
return null;
}
/*
* @see IContentAssistProcessorExtension#computeCompletionProposals(IContentAssistSubject, int)
*/
public ICompletionProposal[] computeCompletionProposals(IContentAssistSubject contentAssistSubject, int documentOffset) {
List results= new ArrayList(fgProposalKeys.size());
Iterator iter= fgProposalKeys.iterator();
while (iter.hasNext())
addProposal((String)iter.next(), contentAssistSubject, documentOffset, results, true);
if (results.isEmpty()) {
iter= fgProposalKeys.iterator();
while (iter.hasNext())
addProposal((String)iter.next(), contentAssistSubject, documentOffset, results, false);
}
return (ICompletionProposal[])results.toArray(new ICompletionProposal[results.size()]);
}
/*
* @see IContentAssistProcessorExtension#computeContextInformation(IContentAssistSubject, int)
*/
public IContextInformation[] computeContextInformation(IContentAssistSubject contentAssistSubject, int documentOffset) {
return null;
}
private void addProposal(String proposalKey, IContentAssistSubject contentAssistSubject, int documentOffset, List results, boolean filter) {
String proposal= (String)fgProposalStrings.get(proposalKey);
// compute correct replacement
if (filter) {
String selection= null;
try {
selection = contentAssistSubject.getDocument().get(documentOffset - 1, 1);
} catch (BadLocationException e) {
return ;
}
if (selection == null || selection.length() == 0 || proposal.length() == 0 || proposal.charAt(0) != selection.charAt(0))
return;
proposal= proposal.substring(1);
}
String displayString= getString(proposalKey, "displayString"); //$NON-NLS-1$
String additionalInfo= getString(proposalKey, "additionalInfo"); //$NON-NLS-1$
IContextInformation info= createContextInformation(proposalKey);
// // Move cursor on to the left if the proposal ends with '}'
int relativeOffset= proposal.length();
// XXX: currently there's no smartness: position the cursor after the proposal
// if (relativeOffset > 0 && proposal.charAt(relativeOffset - 1) == '}')
// relativeOffset--;
results.add(new CompletionProposal(proposal, documentOffset, 0, Math.max(0, relativeOffset), null, displayString, info, additionalInfo));
}
private IContextInformation createContextInformation(String proposalKey) {
return null;
}
private String getString(String proposalKey, String type) {
return EditorMessages.getString("FindReplace.regExContentAssist." + type + "." + proposalKey); //$NON-NLS-1$//$NON-NLS-2$
}
}