blob: 09bd2cc44919fab8b372aaddaa7e0749ac6c586f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2011 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.docs.intent.client.ui.editor.completion;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collection;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.mylyn.docs.intent.client.ui.editor.scanner.IntentPartitionScanner;
import org.eclipse.mylyn.docs.intent.collab.handlers.adapters.RepositoryAdapter;
/**
* Computes the completion proposal for pure documentation zones.
*
* @author <a href="mailto:alex.lagarde@obeo.fr">Alex Lagarde</a>
*/
public class MarkupCompletionProcessor extends AbstractIntentCompletionProcessor {
/**
* Default constructor.
*
* @param repositoryAdapter
*/
public MarkupCompletionProcessor(RepositoryAdapter repositoryAdapter) {
super(repositoryAdapter);
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.client.ui.editor.completion.AbstractIntentCompletionProcessor#computeCompletionProposals()
*/
@Override
protected ICompletionProposal[] computeCompletionProposals() {
ArrayList<ICompletionProposal> proposals = Lists.newArrayList();
// Step 1: get last relevant char
String documentText = document.get().substring(0, offset);
int i = documentText.length() - 1;
ArrayList<Character> lastRelevantChar = new ArrayList<Character>();
while (i > 2) {
Character relevantChar = documentText.charAt(i);
i--;
if (relevantChar == '\n') {
break;
}
if (isRelevantChar(relevantChar)) {
if (lastRelevantChar.contains(relevantChar)) {
lastRelevantChar.remove(relevantChar);
} else {
lastRelevantChar.add(relevantChar);
}
}
}
// Step 2: add matching proposals
char relevantChar = '\n';
if (!lastRelevantChar.isEmpty()) {
relevantChar = lastRelevantChar.iterator().next();
}
addProposal(proposals, relevantChar, "Emphasis", "_");
addProposal(proposals, relevantChar, "Strong", "*");
addProposal(proposals, relevantChar, "Image", "!", "imagePath", true);
addProposal(proposals, relevantChar, "List (buletted)", "*", "", false);
addProposal(proposals, relevantChar, "List (numeric)", "#", "", false);
addProposal(proposals, relevantChar, "Code", "@");
addProposal(proposals, relevantChar, "Italic", "__ ");
addProposal(proposals, relevantChar, "Bold", "** ");
addProposal(proposals, relevantChar, "List (level 2, buletted)", "** ", "", false);
addProposal(proposals, relevantChar, "List (level 2, numeric)", "## ", "", false);
addProposal(proposals, relevantChar, "Citation", "??");
addProposal(proposals, relevantChar, "Deleted", "-");
addProposal(proposals, relevantChar, "Inserted", "+");
addProposal(proposals, relevantChar, "Superscript", "^");
addProposal(proposals, relevantChar, "Span", "%");
// Todo : subscript, link, footnote & table
return proposals.toArray(new ICompletionProposal[proposals.size()]);
}
/**
* Indicates if the given char indicates the beginning of a completion proposal.
*
* @param currentChar
* the current char
* @return true if the given char indicates the beginning of a completion proposal, false otherwise
*/
private boolean isRelevantChar(char currentChar) {
return currentChar == '_' || currentChar == '@' || currentChar == '*' || currentChar == '%'
|| currentChar == '+' || currentChar == '^' || currentChar == '-' || currentChar == '#'
|| currentChar == '!' || currentChar == '?';
}
/**
* Creates a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*'), only if the given relevant char is compatible with this
* proposal.
*
* @param proposals
* the current proposals
* @param relevantChar
* the relevant char
* @param fontDecorationName
* the name of the font decoration (e.g. 'Bold')
* @param fontDecorationSyntax
* the syntax of the font decoration (e.g. '*')
* @param variableName
* the name of the variable to be display as ${variable} (can be empty)
* @return a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*')
*/
private void addProposal(Collection<ICompletionProposal> proposals, char relevantChar,
String fontDecorationName, String fontDecorationSyntax) {
addProposal(proposals, relevantChar, fontDecorationName, fontDecorationSyntax, "", true);
}
/**
* Creates a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*'), only if the given relevant char is compatible with this
* proposal.
*
* @param proposals
* the current proposals
* @param relevantChar
* the relevant char
* @param fontDecorationName
* the name of the font decoration (e.g. 'Bold')
* @param fontDecorationSyntax
* the syntax of the font decoration (e.g. '*')
* @param variableName
* the name of the variable to be display as ${variable} (can be empty)
* @param biDirectionalSyntax
* indicates if the fontDecorationSyntax should be displayed before and after text (e.g.
* '*bold*') or just before (e.g. '# bullet')
* @return a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*')
*/
private void addProposal(Collection<ICompletionProposal> proposals, char relevantChar,
String fontDecorationName, String fontDecorationSyntax, String variableName,
boolean biDirectionalSyntax) {
if (relevantChar == '\n') {
proposals.add(createFontDecorationProposal(fontDecorationName, fontDecorationSyntax,
variableName, biDirectionalSyntax));
} else if (biDirectionalSyntax && fontDecorationSyntax.charAt(0) == relevantChar) {
String currenText = document.get().substring(0, offset);
currenText = currenText.substring(currenText.lastIndexOf(relevantChar));
proposals.add(createFontDecorationProposal(fontDecorationName, fontDecorationSyntax,
variableName, currenText));
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.mylyn.docs.intent.client.ui.editor.completion.AbstractIntentCompletionProcessor#getContextType()
*/
@Override
public String getContextType() {
return IntentPartitionScanner.INTENT_DESCRIPTIONUNIT;
}
/**
* Creates a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*').
*
* @param fontDecorationName
* the name of the font decoration (e.g. 'Bold')
* @param fontDecorationSyntax
* the syntax of the font decoration (e.g. '*')
* @param variableName
* the name of the variable to be display as ${variable} (can be empty)
* @param biDirectionalSyntax
* indicates if the fontDecorationSyntax should be displayed before and after text (e.g.
* '*bold*') or just before (e.g. '# bullet')
* @return a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*')
*/
private ICompletionProposal createFontDecorationProposal(String fontDecorationName,
String fontDecorationSyntax, String variableName, boolean biDirectionalSyntax) {
String templateName = "";
String templatePattern = "";
if (biDirectionalSyntax) {
templateName = fontDecorationSyntax + fontDecorationName.toLowerCase() + fontDecorationSyntax;
templatePattern = fontDecorationSyntax + "${ " + variableName + "}" + fontDecorationSyntax;
} else {
templateName = fontDecorationSyntax + " " + fontDecorationName.toLowerCase();
templatePattern = fontDecorationSyntax + " ${ " + variableName + "}";
}
return createTemplateProposal(templateName, fontDecorationName, templatePattern, null);
}
/**
* Creates a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*').
*
* @param fontDecorationName
* the name of the font decoration (e.g. 'Bold')
* @param fontDecorationSyntax
* the syntax of the font decoration (e.g. '*')
* @param variableName
* the name of the variable to be display as ${variable} (can be empty)
* @param beginningText
* the beginning text
* @return a font decoration proposal according to the given font decoration name (e.g. 'Bold') and the
* given font decoration Syntax (e.g. '*')
*/
private ICompletionProposal createFontDecorationProposal(String fontDecorationName,
String fontDecorationSyntax, String variableName, String beginningText) {
String templateName = fontDecorationSyntax + fontDecorationName.toLowerCase() + fontDecorationSyntax;
String templatePattern = "";
if (beginningText.contains(" ")) {
beginningText = beginningText.substring(beginningText.lastIndexOf(' ')).trim();
}
if (beginningText.contains(fontDecorationSyntax) && !(isSkipped(fontDecorationSyntax.charAt(0)))) {
beginningText = beginningText
.substring(
beginningText.lastIndexOf(fontDecorationSyntax.charAt(0))
+ fontDecorationSyntax.length()).trim();
}
templatePattern = beginningText + fontDecorationSyntax;
return createTemplateProposal(templateName, fontDecorationName, templatePattern, null);
}
/**
* Indicates if the completion consider given char as part of the proposal or not.
*
* @param currentChar
* the current char
* @return true if the completion consider given char as part of the proposal or not, false otherwise
*/
private boolean isSkipped(char currentChar) {
return currentChar == '_' || currentChar == '@';
}
}