/**
* Copyright (C) 2013 - 2015 Eric Van Dewoestine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.eclim.plugin.pydev.command.complete;
import java.io.File;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclim.annotation.Command;
import org.eclim.command.CommandLine;
import org.eclim.plugin.core.command.complete.AbstractCodeCompleteCommand;
import org.eclim.plugin.core.command.complete.CodeCompleteResult;
import org.eclim.plugin.core.util.ProjectUtils;
import org.eclipse.core.resources.IProject;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.source.ISourceViewer;
import org.python.pydev.core.IIndentPrefs;
import org.python.pydev.core.IPythonNature;
import org.python.pydev.core.MisconfigurationException;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.editor.IPySyntaxHighlightingAndCodeCompletionEditor;
import org.python.pydev.editor.PyEditConfigurationWithoutEditor;
import org.python.pydev.editor.codecompletion.CompletionError;
import org.python.pydev.editor.codecompletion.PyContentAssistant;
import org.python.pydev.editor.codecompletion.PythonCompletionProcessor;
import org.python.pydev.plugin.nature.PythonNature;
import org.python.pydev.ui.ColorAndStyleCache;
import com.python.pydev.analysis.CtxInsensitiveImportComplProposal;
/**
* Command to perform python code completion.
*
* @author Eric Van Dewoestine
*/
@Command(
name = "python_complete",
options =
"REQUIRED p project ARG," +
"REQUIRED f file ARG," +
"REQUIRED o offset ARG," +
"REQUIRED e encoding ARG"
)
public class CodeCompleteCommand
extends AbstractCodeCompleteCommand
{
private static final Pattern PREFIX =
Pattern.compile("^*?\\W(\\w*)$");
@Override
protected ICompletionProposal[] getCompletionProposals(
CommandLine commandLine, String projectName, String fileName, int offset)
throws Exception
{
ISourceViewer viewer = getTextViewer(commandLine, projectName, fileName);
IProject project = ProjectUtils.getProject(projectName);
File file = new File(ProjectUtils.getFilePath(project, fileName));
IPySyntaxHighlightingAndCodeCompletionEditor editor =
new PyEditor(project, file, viewer);
PyContentAssistant assistant = new PyContentAssistant();
PythonCompletionProcessor processor =
new PythonCompletionProcessor(editor, assistant);
ICompletionProposal[] results =
processor.computeCompletionProposals(viewer, offset);
// pydev completions are case insensitive, so filter out the insensitive
// matches
if(results != null && results.length > 0){
IDocument document = ProjectUtils.getDocument(project, fileName);
IRegion region = document.getLineInformationOfOffset(offset);
String prefix = document.get(region.getOffset(), offset - region.getOffset());
Matcher matcher = PREFIX.matcher(prefix);
if (matcher.find()){
prefix = matcher.group(1);
}
ArrayList<ICompletionProposal> filtered =
new ArrayList<ICompletionProposal>();
for (ICompletionProposal proposal : results){
if (proposal.getDisplayString().startsWith(prefix)){
filtered.add(proposal);
}
}
results = filtered.toArray(new ICompletionProposal[filtered.size()]);
}
return results;
}
@Override
protected CodeCompleteResult createCodeCompletionResult(
ICompletionProposal proposal)
{
if (proposal instanceof CompletionError){
return null;
}
if (proposal instanceof CtxInsensitiveImportComplProposal){
return null;
}
return super.createCodeCompletionResult(proposal);
}
@Override
protected String getCompletion(ICompletionProposal proposal)
{
String completion = proposal.getDisplayString();
int open = completion.indexOf('(');
if (open != -1){
int close = completion.indexOf(')');
if (close != open + 1){
completion = completion.substring(0, open + 1);
}
}
return completion;
}
static class PyEditor
implements IPySyntaxHighlightingAndCodeCompletionEditor
{
private IProject project;
private File file;
private ISourceViewer viewer;
public PyEditor(IProject project, File file, ISourceViewer viewer)
{
this.project = project;
this.file = file;
}
@Override
public File getEditorFile()
{
return file;
}
@Override
public IPythonNature getPythonNature()
throws MisconfigurationException
{
return PythonNature.getPythonNature(project);
}
@Override
public ISourceViewer getEditorSourceViewer()
{
return viewer;
}
@Override
public void resetForceTabs()
{
}
@Override
public void resetIndentPrefixes()
{
}
@Override
public IIndentPrefs getIndentPrefs()
{
return null;
}
@Override
public PyEditConfigurationWithoutEditor getEditConfiguration()
{
return null;
}
@Override
public ColorAndStyleCache getColorCache()
{
return null;
}
@Override
public PySelection createPySelection()
{
return null;
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public Object getAdapter(Class adapter)
{
return null;
}
@Override
public int getGrammarVersion()
throws MisconfigurationException
{
return getPythonNature().getGrammarVersion();
}
}
}