/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * 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: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.ide.command.editor.page.text; import org.eclipse.che.ide.Resources; import org.eclipse.che.ide.api.editor.codeassist.CodeAssistCallback; import org.eclipse.che.ide.api.editor.codeassist.CodeAssistProcessor; import org.eclipse.che.ide.api.editor.codeassist.CompletionProposal; import org.eclipse.che.ide.api.editor.document.Document; import org.eclipse.che.ide.api.editor.text.TextPosition; import org.eclipse.che.ide.api.editor.texteditor.TextEditor; import org.eclipse.che.ide.api.macro.Macro; import org.eclipse.che.ide.api.macro.MacroRegistry; import org.eclipse.che.ide.filters.FuzzyMatches; import org.eclipse.che.ide.filters.Match; import javax.inject.Inject; import java.util.ArrayList; import java.util.List; /** Code assist processor for macro names. */ public class MacroCodeAssistProcessor implements CodeAssistProcessor { private MacroRegistry registry; private FuzzyMatches fuzzyMatches; private Resources resources; private LastCompletion lastCompletion; @Inject public MacroCodeAssistProcessor(MacroRegistry registry, FuzzyMatches fuzzyMatches, Resources resources) { this.registry = registry; this.fuzzyMatches = fuzzyMatches; this.resources = resources; lastCompletion = new LastCompletion(); } @Override public void computeCompletionProposals(TextEditor editor, int offset, boolean triggered, CodeAssistCallback callback) { Document document = editor.getDocument(); TextPosition position = document.getPositionFromIndex(offset); String currentLine = editor.getDocument().getLineContent(position.getLine()); final String currentWord = getCurrentWord(currentLine, position.getCharacter()); List<CompletionProposal> result = new ArrayList<>(); if (triggered && !lastCompletion.isGoodFor(currentWord, offset)) { lastCompletion.offset = offset; lastCompletion.wordStartOffset = offset - currentWord.length(); // start completion word lastCompletion.word = currentWord; } List<Macro> macros = registry.getMacros(); for (Macro macro : macros) { List<Match> matches = fuzzyMatches.fuzzyMatch(currentWord, macro.getName()); if (matches != null) { MacroCompletionProposal proposal = new MacroCompletionProposal(macro, matches, resources, lastCompletion.wordStartOffset, currentWord.length()); result.add(proposal); } } result.sort((o1, o2) -> { MacroCompletionProposal p1 = ((MacroCompletionProposal)o1); MacroCompletionProposal p2 = ((MacroCompletionProposal)o2); return p1.getMacro().getName().compareTo(p2.getMacro().getName()); }); callback.proposalComputed(result); } private String getCurrentWord(String text, int offset) { int i = offset - 1; while (i >= 0 && isWordChar(text.charAt(i))) { i--; } return text.substring(i + 1, offset); } private boolean isWordChar(char c) { return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c >= '\u007f' && c <= '\u00ff' || c == '$' || c == '{' || c == '.' || c == '_' || c == '-'; } @Override public String getErrorMessage() { return null; } private class LastCompletion { String word = ""; int wordStartOffset; int offset; boolean isGoodFor(String currentWord, int offset) { return currentWord.startsWith(word) && offset - this.offset == currentWord.length() - word.length(); } } }