/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.ui.actions.resources;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.console.MessageConsole;
import org.python.pydev.consoles.MessageConsoles;
import org.python.pydev.core.FontUtils;
import org.python.pydev.core.IFontUsage;
import org.python.pydev.core.docutils.StringUtils;
import org.python.pydev.core.log.Log;
import org.python.pydev.editor.actions.PyAction;
import org.python.pydev.plugin.nature.PythonNature;
import org.python.pydev.runners.UniversalRunner;
import org.python.pydev.runners.UniversalRunner.AbstractRunner;
import org.python.pydev.ui.UIConstants;
import com.aptana.shared_core.structure.Tuple;
/**
* Applies 2to3.py in the selected folder(s)/file(s)
*/
public class Py2To3 extends PyResourceAction implements IObjectActionDelegate {
public static final String RUN_2_TO_3_CODE = "" +
"from lib2to3.main import main\n" +
"import sys\n"
+
"import os\n" +
"\n" +
"sys.exit(main('lib2to3.fixes'))\n" +
"";
PythonNature natureUsed;
List<String> parameters;
List<IContainer> refresh;
protected boolean confirmRun() {
clearRunInput();
PythonNature nature = null;
for (IResource c : selectedResources) {
PythonNature n2 = PythonNature.getPythonNature(c);
if (n2 != null) {
if (nature == null) {
nature = n2;
} else {
if (n2 != nature) {
MessageBox message = new MessageBox(PyAction.getShell(), SWT.OK | SWT.ICON_ERROR);
message.setText("Multiple python natures");
message.setMessage("This action can only be applied in one project at a time.");
message.open();
return false;
}
}
}
}
if (nature == null) {
MessageBox message = new MessageBox(PyAction.getShell(), SWT.OK | SWT.ICON_ERROR);
message.setText("No nature found");
message.setMessage("This action can only be applied in a project that is configured as a Pydev project.");
message.open();
return false;
}
AbstractRunner runner = UniversalRunner.getRunner(nature);
Tuple<String, String> tup = runner.runCodeAndGetOutput(RUN_2_TO_3_CODE, new String[] { "--help" }, null,
new NullProgressMonitor());
if (tup.o1.indexOf("ImportError") != -1 || tup.o2.indexOf("ImportError") != -1) {
MessageBox message = new MessageBox(PyAction.getShell(), SWT.OK | SWT.ICON_ERROR);
message.setText("Unable to run 2to3");
message.setMessage("Unable to run 2to3. Details: \n" + tup.o1 + "\n" + tup.o2
+ "\n\nNotes: check if lib2to3 is properly installed in your Python install.");
message.open();
return false;
}
String msg = "Please enter the parameters to be passed for 2to3.py\n\n" + tup.o1 + "\n\n" + "E.g.: \n"
+ "Leave empty for preview\n" + "-w to apply with backup\n" + "-w -n to apply without backup.";
if (tup.o2.length() > 0) {
msg += "\n";
msg += tup.o2;
}
final List<String> splitInLines = StringUtils.splitInLines(msg);
int max = 10;
for (String string : splitInLines) {
max = Math.max(string.length(), max);
}
final int maxChars = max;
InputDialog d = new InputDialog(PyAction.getShell(), "Parameters for 2to3.py", msg, "", null) {
int averageCharWidth;
int height;
protected boolean isResizable() {
return true;
}
protected Control createDialogArea(Composite parent) {
try {
FontData labelFontData = FontUtils.getFontData(IFontUsage.DIALOG, false);
Display display = parent.getDisplay();
Font font = new Font(display, labelFontData);
parent.setFont(font);
GC gc = new GC(display);
gc.setFont(font);
FontMetrics fontMetrics = gc.getFontMetrics();
averageCharWidth = fontMetrics.getAverageCharWidth();
height = fontMetrics.getHeight();
gc.dispose();
} catch (Throwable e) {
//ignore
}
return super.createDialogArea(parent);
}
protected Point getInitialSize() {
Point result = super.getInitialSize();
//Check if we were able to get proper values before changing it.
if (averageCharWidth > 0 && maxChars > 0) {
result.x = (int) (averageCharWidth * maxChars * 1.15);
}
if (height > 0 && splitInLines.size() > 0) {
result.y = height * (splitInLines.size() + 6); //put some lines extra (we need the input line too)
}
return result;
}
};
int retCode = d.open();
if (retCode != InputDialog.OK) {
return false;
}
MessageConsole console = MessageConsoles.getConsole("2To3", UIConstants.PY_INTERPRETER_ICON);
console.clearConsole();
parameters = StringUtils.split(d.getValue(), " ");
natureUsed = nature;
return true;
}
protected void afterRun(int resourcesAffected) {
for (IContainer c : this.refresh) {
try {
c.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
Log.log(e);
}
}
clearRunInput();
}
private void clearRunInput() {
natureUsed = null;
refresh = null;
parameters = null;
}
protected int doActionOnResource(IResource next, IProgressMonitor monitor) {
this.refresh = new ArrayList<IContainer>();
AbstractRunner runner = UniversalRunner.getRunner(natureUsed);
if (next instanceof IContainer) {
this.refresh.add((IContainer) next);
} else {
this.refresh.add(next.getParent());
}
String dir = next.getLocation().toOSString();
File workingDir = new File(dir);
if (!workingDir.exists()) {
Log.log("Received file that does not exist for 2to3: " + workingDir);
return 0;
}
if (!workingDir.isDirectory()) {
workingDir = workingDir.getParentFile();
if (!workingDir.isDirectory()) {
Log.log("Unable to find working dir for 2to3. Found invalid: " + workingDir);
return 0;
}
}
ArrayList<String> parametersWithResource = new ArrayList<String>(parameters);
parametersWithResource.add(0, dir);
Tuple<String, String> tup = runner.runCodeAndGetOutput(RUN_2_TO_3_CODE,
parametersWithResource.toArray(new String[0]), workingDir, monitor);
IOConsoleOutputStream out = MessageConsoles.getConsoleOutputStream("2To3", UIConstants.PY_INTERPRETER_ICON);
try {
out.write(tup.o1);
out.write("\n");
out.write(tup.o2);
} catch (IOException e) {
Log.log(e);
}
return 1;
}
}