Commits

sk  committed cae60c1 Merge

Merge main with lispdev.

  • Participants
  • Parent commits 1561677, 7423324

Comments (0)

Files changed (73)

+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
+syntax: glob
+.DS_Store
+bin/**
+.settings/**
+.metadata/**
+
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.lispdev.main</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>

File META-INF/MANIFEST.MF

+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Main
+Bundle-SymbolicName: org.lispdev.main;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.lispdev.main.LispPlugin
+Require-Bundle: org.eclipse.core.runtime,
+ org.eclipse.core.resources,
+ org.eclipse.ui,
+ org.eclipse.ui.ide,
+ org.eclipse.ui.console;bundle-version="3.4.0",
+ org.eclipse.debug.ui;bundle-version="3.5.2",
+ org.lispdev.editor;bundle-version="0.0.1",
+ org.lispdev.preferences;bundle-version="0.0.0",
+ org.lispdev.swank;bundle-version="1.0.0",
+ org.lispdev.log;bundle-version="1.0.0"
+Bundle-ActivationPolicy: lazy
+Bundle-RequiredExecutionEnvironment: JavaSE-1.6
+Export-Package: org.lispdev.main
+Import-Package: org.eclipse.ui.dialogs

File build.properties

+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml

File icons/apropos.gif

Added
New image

File icons/asd.gif

Added
New image

File icons/backward-nav.gif

Added
New image

File icons/clear.gif

Added
New image

File icons/create-exe.gif

Added
New image

File icons/defaction.gif

Added
New image

File icons/defclass.gif

Added
New image

File icons/defconstant.gif

Added
New image

File icons/defgeneric.gif

Added
New image

File icons/define-alien-routine.gif

Added
New image

File icons/define-alien-type.gif

Added
New image

File icons/define-alien-variable.gif

Added
New image

File icons/define-condition.gif

Added
New image

File icons/defmacro.gif

Added
New image

File icons/defmethod.gif

Added
New image

File icons/defother.gif

Added
New image

File icons/defpackage.gif

Added
New image

File icons/defparameter.gif

Added
New image

File icons/defstruct.gif

Added
New image

File icons/defsystem.gif

Added
New image

File icons/deftype.gif

Added
New image

File icons/defun.gif

Added
New image

File icons/defvar.gif

Added
New image

File icons/disconnected.gif

Added
New image

File icons/error.gif

Added
New image

File icons/exec-lisp.gif

Added
New image

File icons/forward-nav.gif

Added
New image

File icons/in-package.gif

Added
New image

File icons/inspector.gif

Added
New image

File icons/lisp-file.gif

Added
New image

File icons/lisp-nature.gif

Added
New image

File icons/lisp-nav.gif

Added
New image

File icons/load-asd.gif

Added
New image

File icons/load-package.gif

Added
New image

File icons/other.gif

Added
New image

File icons/reconnect.gif

Added
New image

File icons/refresh.gif

Added
New image

File icons/run-tests.gif

Added
New image

File icons/sample.gif

Added
New image

File icons/sort-alpha.gif

Added
New image

File icons/sort-position.gif

Added
New image

File icons/sort-type.gif

Added
New image

File icons/step.gif

Added
New image

File icons/test-results.gif

Added
New image

File icons/thread-debug.gif

Added
New image

File icons/thread-kill.gif

Added
New image

File icons/threads.gif

Added
New image

File icons/warning.gif

Added
New image

File icons/xref.gif

Added
New image
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+   <extension
+         point="org.eclipse.ui.perspectives">
+      <perspective
+            class="org.lispdev.main.LispPerspectiveFactory"
+            icon="icons/lisp-nature.gif"
+            id="org.lispdev.main.LispPerspective"
+            name="Lisp">
+      </perspective>
+   </extension>
+   <extension
+         id="org.lispdev.lispNature"
+         name="Lisp Nature"
+         point="org.eclipse.core.resources.natures">
+      <runtime>
+         <run
+               class="org.lispdev.main.LispNature">
+         </run>
+      </runtime>
+   </extension>
+   <extension
+         point="org.eclipse.ui.ide.projectNatureImages">
+      <image
+            icon="icons/lisp-nature.gif"
+            id="org.lispdev.main.LispNatureImage"
+            natureId="org.lispdev.lispNature">
+      </image>
+   </extension>
+   <extension
+         point="org.eclipse.ui.newWizards">
+      <category
+            id="org.lispdev.wizards"
+            name="Lisp">
+      </category>
+      <wizard
+            category="org.lispdev.wizards"
+            class="org.lispdev.main.NewFileWizard"
+            finalPerspective="org.lispdev.main.LispPerspective"
+            icon="icons/lisp-file.gif"
+            id="org.lispdev.wizards.newFileWizard"
+            name="Lisp File"
+            preferredPerspectives="org.lispdev.main.LispPerspective">
+         <selection
+               class="org.eclipse.core.resources.IResource">
+         </selection>
+      </wizard>
+      <wizard
+            category="org.lispdev.wizards"
+            class="org.lispdev.main.NewProjectWizard"
+            finalPerspective="org.lispdev.main.LispPerspective"
+            icon="icons/lisp-file.gif"
+            id="org.lispdev.wizards.newProjectWizard"
+            name="Lisp Project"
+            preferredPerspectives="org.lispdev.main.LispPerspective"
+            project="true">
+         <selection
+               class="org.eclipse.core.resources.IResource">
+         </selection>
+      </wizard>
+   </extension>
+   <extension
+         point="org.eclipse.ui.popupMenus">
+      <objectContribution
+            adaptable="false"
+            id="org.lispdev.main.LoadProjectAction.folder"
+            objectClass="org.eclipse.core.resources.IResource">
+         <action
+               class="org.lispdev.main.LoadProjectAction"
+               enablesFor="1"
+               icon="icons/load-asd.gif"
+               id="org.lispdev.main.LoadProjectAction"
+               label="Load In"
+               menubarPath="group.add"
+               style="pulldown">
+         </action>
+         <filter
+               name="projectNature"
+               value="org.lispdev.lispNature">
+         </filter>
+      </objectContribution>
+      <objectContribution
+            id="org.lispdev.main.DeleteCompilerOutputs.folder"
+            objectClass="org.eclipse.core.resources.IProject">
+         <action
+               class="org.lispdev.main.DeleteCompilerOutputs"
+               enablesFor="1"
+               icon="icons/clear.gif"
+               id="org.lispdev.main.DeleteCompilerOutputs"
+               label="Delete Compiler Outputs"
+               menubarPath="group.add">
+         </action>
+         <filter
+               name="projectNature"
+               value="org.lispdev.lispNature">
+         </filter>
+      </objectContribution>
+      <objectContribution
+            id="org.lispdev.main.ToggleNatureAction.folder"
+            objectClass="org.eclipse.core.resources.IProject">
+         <action
+               class="org.lispdev.main.ToggleNatureAction"
+               enablesFor="+"
+               id="org.lispdev.main.ToggleNatureAction"
+               label="Add/Remove Lisp Nature"
+               menubarPath="group.add">
+         </action>
+      </objectContribution>
+      <objectContribution
+            adaptable="false"
+            id="org.lispdev.main.LoadLispFileAction.folder"
+            nameFilter="*.lisp"
+            objectClass="org.eclipse.core.resources.IFile">
+         <action
+               class="org.lispdev.main.LoadFileInAction"
+               enablesFor="+"
+               icon="icons/lisp-file.gif"
+               id="org.lispdev.main.LoadLispFileAction"
+               label="Load In"
+               menubarPath="group.add"
+               style="pulldown">
+         </action>
+      </objectContribution>
+      <objectContribution
+            adaptable="false"
+            id="org.lispdev.main.LoadCLFileAction.folder"
+            nameFilter="*.cl"
+            objectClass="org.eclipse.core.resources.IFile">
+         <action
+               class="org.lispdev.main.LoadFileInAction"
+               enablesFor="+"
+               icon="icons/lisp-file.gif"
+               id="org.lispdev.main.LoadCLFileAction"
+               label="Load In"
+               menubarPath="group.add"
+               style="pulldown">
+         </action>
+      </objectContribution>
+   </extension>
+   <extension
+         point="org.eclipse.ui.decorators">
+      <decorator
+            adaptable="false"
+            class="org.lispdev.main.LispProjectDecorator"
+            id="org.lispdev.main.projectDecorator"
+            label="Lisp Project Decorator"
+            lightweight="true"
+            location="TOP_LEFT"
+            state="true">
+         <description>
+            Adds label of associated lisp runtime.
+         </description>
+         <enablement>
+            <objectClass
+                  name="org.eclipse.core.resources.IProject">
+            </objectClass>
+         </enablement>
+      </decorator>
+   </extension>
+   <extension
+         id="org.lispdev.marker.compile"
+         point="org.eclipse.core.resources.markers">
+      <super
+            type="org.eclipse.core.resources.problemmarker">
+      </super>
+      <super
+            type="org.lispdev.marker">
+      </super>
+      <persistent
+            value="true">
+      </persistent>
+   </extension>
+
+</plugin>

File src/org/lispdev/main/DeleteCompilerOutputs.java

+package org.lispdev.main;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.lispdev.log.Log;
+import org.lispdev.swank.BaseLocalLispLaunchDelegate;
+import org.lispdev.swank.SwankPlugin;
+
+public class DeleteCompilerOutputs implements IObjectActionDelegate
+{
+  private IStructuredSelection selection;
+  private ILaunchConfiguration config;
+
+  @Override
+  public void run(IAction action)
+  {
+    if( selection != null && selection.size() == 1 )
+    {
+      Object obj = selection.getFirstElement();
+      if( obj instanceof IProject )
+      {
+        final IProject project = (IProject)obj;
+        if( project.isOpen() )
+        {
+          IRunnableWithProgress op = new IRunnableWithProgress(){
+            public void run(IProgressMonitor monitor)
+                throws InvocationTargetException
+            {
+              monitor.beginTask("Deleting fasls...", 10);
+              try
+              {
+                project.refreshLocal(IResource.DEPTH_INFINITE, monitor);
+              }
+              catch(CoreException e)
+              {
+                Log.logException(e);
+              }
+              monitor.worked(2);
+              cleanFasls(project, monitor);
+              monitor.done();
+            }
+          };
+          try
+          {
+            LispPlugin.get().getWorkbench().getProgressService()
+              .run(true, false, op);
+          }
+          catch(InvocationTargetException e)
+          {
+            e.printStackTrace();
+          }
+          catch(InterruptedException e)
+          {
+            e.printStackTrace();
+          }
+        }
+      }
+    }
+  }
+
+  private void cleanFasls(IContainer folder, IProgressMonitor monitor)
+  {
+    if( folder.exists() && config != null )
+    {
+      try
+      {
+        for(IResource resource : folder.members())
+        {
+          if( resource instanceof IContainer )
+          {
+            cleanFasls((IContainer)resource, monitor);
+          }
+          else if( resource instanceof IFile )
+          {
+            IFile file = (IFile)resource;
+            String fname = file.getName();
+
+            if( file.exists() &&
+                (BaseLocalLispLaunchDelegate.isCompilerOutput(config, fname)
+                    || "fasl".equals(file.getFileExtension()))) // should remove
+            {
+              file.delete(true, monitor);
+            }
+          }
+        }
+      }
+      catch(CoreException e)
+      {
+        e.printStackTrace();
+      }
+    }
+  }
+
+  @Override
+  public void selectionChanged(IAction action, ISelection selection)
+  {
+    if( selection instanceof IStructuredSelection )
+    {
+      this.selection = (IStructuredSelection)selection;
+    }
+    config = SwankPlugin.get().getActiveConfig();
+    action.setEnabled(config != null);
+  }
+
+  @Override
+  public void setActivePart(IAction action, IWorkbenchPart targetPart)
+  {}
+}

File src/org/lispdev/main/LispNature.java

+package org.lispdev.main;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectNature;
+import org.eclipse.core.runtime.CoreException;
+
+public class LispNature implements IProjectNature
+{
+
+  public static final String ID = "org.lispdev.lispNature";
+  private IProject project;
+
+  @Override
+  public void configure() throws CoreException
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public void deconfigure() throws CoreException
+  {
+    // TODO Auto-generated method stub
+
+  }
+
+  @Override
+  public IProject getProject()
+  {
+    return project;
+  }
+
+  @Override
+  public void setProject(IProject project)
+  {
+    this.project = project;
+  }
+
+}

File src/org/lispdev/main/LispPerspectiveFactory.java

+package org.lispdev.main;
+
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.ui.IFolderLayout;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+import org.eclipse.ui.console.IConsoleConstants;
+
+public class LispPerspectiveFactory implements IPerspectiveFactory
+{
+  public static final String ID = "org.lispdev.main.LispPerspective";
+
+  @Override
+  public void createInitialLayout(IPageLayout layout)
+  {
+    //   Get the editor area.
+    final String editorArea = layout.getEditorArea();
+
+    // Top left: Resource Navigator view
+    final IFolderLayout topLeft =
+      layout.createFolder("topLeft", IPageLayout.LEFT, 0.25f, editorArea);
+    topLeft.addView(IPageLayout.ID_PROJECT_EXPLORER);
+
+    // Bottom left: Outline view and Property Sheet view
+    final IFolderLayout bottomLeft =
+      layout.createFolder("bottomLeft", IPageLayout.BOTTOM, 0.60f, "topLeft");
+    bottomLeft.addView(IPageLayout.ID_OUTLINE);
+
+    // Top right: Debug views
+    final IFolderLayout topRight =
+      layout.createFolder("topRight", IPageLayout.RIGHT, 0.60f, editorArea);
+    topRight.addView(IDebugUIConstants.ID_DEBUG_VIEW);
+
+    // Bottom left: Outline view and Property Sheet view
+    final IFolderLayout bottomRight =
+      layout.createFolder("bottomRight", IPageLayout.BOTTOM, 0.40f, "topRight");
+    bottomRight.addView(IDebugUIConstants.ID_VARIABLE_VIEW);
+    bottomRight.addView(IDebugUIConstants.ID_EXPRESSION_VIEW);
+
+    // Bottom right: Task List view
+    IFolderLayout bottom =
+      layout.createFolder("bottom", IPageLayout.BOTTOM, 0.60f, editorArea);
+    bottom.addView(IConsoleConstants.ID_CONSOLE_VIEW);
+    bottom.addView(IPageLayout.ID_PROBLEM_VIEW);
+    bottom.addView(IPageLayout.ID_TASK_LIST);
+
+    layout.addShowViewShortcut(IPageLayout.ID_PROBLEM_VIEW);
+    layout.addShowViewShortcut(IPageLayout.ID_TASK_LIST);
+    layout.addShowViewShortcut(IConsoleConstants.ID_CONSOLE_VIEW);
+    layout.addShowViewShortcut(IPageLayout.ID_OUTLINE);
+
+    layout.addActionSet(IDebugUIConstants.LAUNCH_ACTION_SET);
+
+  }
+
+}

File src/org/lispdev/main/LispPlugin.java

+package org.lispdev.main;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class LispPlugin extends AbstractUIPlugin
+{
+
+  // The plug-in ID
+  public static final String ID = "org.lispdev.main";
+
+  // The shared instance
+  private static LispPlugin plugin;
+
+  /**
+   * The constructor
+   */
+  public LispPlugin()
+  {}
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext
+   * )
+   */
+  @Override
+  public void start(BundleContext context) throws Exception
+  {
+    super.start(context);
+    plugin = this;
+  }
+
+  /*
+   * (non-Javadoc)
+   *
+   * @see
+   * org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
+   * )
+   */
+  @Override
+  public void stop(BundleContext context) throws Exception
+  {
+    plugin = null;
+    super.stop(context);
+  }
+
+  /**
+   * Returns the shared instance
+   *
+   * @return the shared instance
+   */
+  public static LispPlugin get()
+  {
+    return plugin;
+  }
+
+}

File src/org/lispdev/main/LispProjectDecorator.java

+package org.lispdev.main;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.viewers.IDecoration;
+import org.eclipse.jface.viewers.ILightweightLabelDecorator;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.lispdev.log.Log;
+
+
+public class LispProjectDecorator extends LabelProvider implements
+    ILightweightLabelDecorator
+{
+  public static final String ID = "org.lispdev.main.projectDecorator";
+
+  @Override
+  public void decorate(Object element, IDecoration decoration)
+  {
+    IProject p = (IProject)element;
+    try
+    {
+      if( p.getNature(LispNature.ID) != null )
+      {
+//        LispProcess pr = LispPlugin.get().getActiveProcess(p);
+//        decoration.addSuffix(" ["+(pr == null ? "" : pr.getLabel())+"]");
+      }
+    }
+    catch(CoreException e)
+    {
+      Log.logException("Could not decorate", e);
+    }
+  }
+
+  public void fireNotification(IProject notification)
+  {
+    LabelProviderChangedEvent event =
+        new LabelProviderChangedEvent(this, new Object[] {notification});
+    fireLabelProviderChanged(event);
+  }
+}

File src/org/lispdev/main/LoadFileInAction.java

+package org.lispdev.main;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.lispdev.swank.debug.LispProcess;
+
+public class LoadFileInAction implements IObjectActionDelegate, IMenuCreator
+{
+  private IAction action;
+  private IStructuredSelection selection;
+
+  @Override
+  public void run(IAction action)
+  {}
+
+  @Override
+  public void selectionChanged(IAction action, ISelection selection)
+  {
+    if( action != this.action )
+    {
+      action.setMenuCreator(this);
+      this.action = action;
+    }
+    if( selection instanceof IStructuredSelection )
+    {
+      this.selection = (IStructuredSelection)selection;
+    }
+    else
+    {
+      this.selection = null;
+    }
+  }
+
+  @Override
+  public void dispose()
+  {}
+
+  @Override
+  public Menu getMenu(Control parent)
+  {
+    return null;
+  }
+
+  @Override
+  public Menu getMenu(Menu parent)
+  {
+    Menu menu = new Menu(parent);
+//    for( LispProcess p : SwankPlugin.get().getProcesses() )
+//    {
+//      final String label = p.getLabel();
+//      final LispProcess pr = p;
+//      Action a = new Action(label){
+//        @Override
+//        public void run()
+//        {
+//          loadIn(selection,pr);
+//        }
+//      };
+//      a.setDescription("Load file(s) in " + label);
+//      ActionContributionItem item = new ActionContributionItem(a);
+//      item.fill(menu, -1);
+//    }
+    return menu;
+  }
+
+  private void loadIn(IStructuredSelection files, LispProcess pr)
+  {
+    if( files == null || pr == null ) return;
+    for( Object obj : files.toList() )
+    {
+      if( obj instanceof IFile )
+      {
+        IFile file = (IFile)obj;
+        String filePath = file.getLocation().toOSString().replace("\\", "\\\\");
+        String command = "(load \"" + filePath + "\")";
+
+        //pr.getSwank().sendEvalAndGrab(command,100000);
+      }
+    }
+  }
+
+  @Override
+  public void setActivePart(IAction action, IWorkbenchPart targetPart)
+  {}
+
+}

File src/org/lispdev/main/LoadProjectAction.java

+package org.lispdev.main;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchManager;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IMenuCreator;
+import org.eclipse.jface.dialogs.ProgressMonitorDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.ui.IObjectActionDelegate;
+import org.eclipse.ui.IWorkbenchPart;
+import org.lispdev.editor.LispMarkers;
+import org.lispdev.log.Log;
+import org.lispdev.swank.SwankPlugin;
+import org.lispdev.swank.debug.LispProcess;
+import org.lispdev.swank.runnables.SwankCompilationRunnable;
+import org.lispdev.swank.runnables.SwankCompilationRunnable.CompilationInfo;
+import org.lispdev.swank.runnables.SwankCompilationRunnable.CompileMessage;
+
+public class LoadProjectAction implements IObjectActionDelegate, IMenuCreator
+{
+  private IWorkbenchPart part;
+  private IAction action;
+  private IProject project;
+  private IFile file;
+
+
+  @Override
+  public void run(IAction action)
+  {}
+
+  @Override
+  public void selectionChanged(IAction action, ISelection selection)
+  {
+    if( action != this.action )
+    {
+      action.setMenuCreator(this);
+      this.action = action;
+    }
+    project = null;
+    file = null;
+    if( selection instanceof IStructuredSelection )
+    {
+      Object obj = ((IStructuredSelection)selection).getFirstElement();
+      if(obj instanceof IProject )
+      {
+        project = (IProject)obj;
+      }
+      else if( obj instanceof IFile
+          && ((IFile)obj).getFileExtension().equals("asd"))
+      {
+        file = (IFile)obj;
+      }
+    }
+  }
+
+  @Override
+  public void dispose()
+  {}
+
+  private void loadIn(final IFile asdfile, final ILaunchConfiguration config)
+  {
+    if( asdfile == null )
+    {
+      MessageBox mbox =
+          new MessageBox(part.getSite().getShell(), SWT.CANCEL | SWT.ICON_ERROR
+              | SWT.APPLICATION_MODAL);
+      mbox.setText("Error");
+      mbox.setMessage("No appropriate asd file was found.");
+      mbox.open();
+    }
+    LispProcess process = SwankPlugin.get().getProcess(config);
+    if( process == null )
+    {
+      final ILaunch[] launches = new ILaunch[1];
+      IRunnableWithProgress op = new IRunnableWithProgress(){
+        @Override
+        public void run(IProgressMonitor monitor) throws InvocationTargetException,
+            InterruptedException
+        {
+          try
+          {
+            launches[0] =
+              DebugUITools.buildAndLaunch(config, ILaunchManager.RUN_MODE, monitor);
+          }
+          catch(CoreException e)
+          {
+            Log.logException(e);
+          }
+        }
+      };
+      ProgressMonitorDialog progress =
+        new ProgressMonitorDialog(part.getSite().getShell());
+      try
+      {
+        progress.run(false, false, op);
+      }
+      catch(InvocationTargetException e)
+      {
+        Log.logException(e);
+      }
+      catch(InterruptedException e)
+      {
+        Log.logException(e);
+      }
+      process = (LispProcess)launches[0].getProcesses()[0];
+      if( process == null )
+      {
+        MessageBox mbox =
+          new MessageBox(part.getSite().getShell(), SWT.CANCEL | SWT.ICON_ERROR
+              | SWT.APPLICATION_MODAL);
+        mbox.setText("Error");
+        mbox.setMessage("Could not start " + config.getName());
+        mbox.open();
+        return;
+      }
+    }
+
+    if( !process.getSwank().isConnected() )
+    {
+      process.getSwank().connect();
+    }
+    process.getSwank().sendLoadASDF(asdfile.getLocation().toOSString(),
+        new SwankCompilationRunnable(process.getSwank().getLispImplementation())
+        {
+          @Override
+          public void run()
+          {
+            CompilationInfo info = getInfo();
+            final IProject proj = asdfile.getProject();
+            addCompilationMarkers(info, proj);
+          }
+        });
+  }
+
+  public static void addCompilationMarkers(CompilationInfo info,
+      final IProject proj)
+  {
+    for( CompileMessage cm : info.messages )
+    {
+      IPath path = new Path(cm.file);
+      IPath projPath = Platform.getLocation().append(proj.getFullPath());
+      if( projPath.isPrefixOf(path) )
+      {
+        IPath relativePath = path.makeRelativeTo(projPath);
+        IFile file = proj.getFile(relativePath);
+        if( file.exists() && cm.position >= 0 )
+        {
+          LispMarkers.addMarker(file, cm.position, 1, cm.message,
+              cm.severity, LispMarkers.COMPILE);
+        }
+        else
+        {
+          LispMarkers.addMarker((file == null ? proj : file),
+              cm.message, cm.severity, LispMarkers.COMPILE);
+        }
+      }
+      else
+      {
+        LispMarkers.addMarker(proj,
+            cm.message, cm.severity, LispMarkers.COMPILE);
+      }
+    }
+  }
+
+  private IFile getAsdFile()
+  {
+    if( file != null )
+    {
+      return file;
+    }
+    else if( project != null )
+    {
+      return project.getFile(project.getName()+".asd");
+    }
+    return null;
+  }
+
+  @Override
+  public Menu getMenu(Menu parent)
+  {
+    Menu menu = new Menu(parent);
+    for( ILaunchConfiguration p : SwankPlugin.get().getConfigs() )
+    {
+      final String label = p.getName();
+      final ILaunchConfiguration pr = p;
+      Action a = new Action(label){
+        @Override
+        public void run()
+        {
+          loadIn(getAsdFile(),pr);
+        }
+      };
+      a.setDescription("Load project in " + label);
+      ActionContributionItem item = new ActionContributionItem(a);
+      item.fill(menu, -1);
+    }
+    return menu;
+  }
+
+  @Override
+  public Menu getMenu(Control parent)
+  {
+    return null;
+  }
+
+  @Override
+  public void setActivePart(IAction action, IWorkbenchPart targetPart)
+  {
+    part = targetPart;
+  }
+
+}

File src/org/lispdev/main/NewFileWizard.java

+package org.lispdev.main;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
+
+public class NewFileWizard extends Wizard implements INewWizard
+{
+  public static final String ID = "org.lispdev.wizards.newFileWizard";
+
+  private NewFileWizardPage page;
+  private ISelection selection;
+
+  public NewFileWizard()
+  {
+    super();
+    setNeedsProgressMonitor(true);
+  }
+
+  @Override
+  public void addPages()
+  {
+    page = new NewFileWizardPage(selection);
+    addPage(page);
+  }
+
+  @Override
+  public void init(IWorkbench workbench, IStructuredSelection selection)
+  {
+    this.selection = selection;
+  }
+
+  @Override
+  public boolean performFinish()
+  {
+    final String containerName = page.getContainerName();
+    final String fileName = page.getFileName();
+    IRunnableWithProgress op = new IRunnableWithProgress(){
+      public void run(IProgressMonitor monitor)
+          throws InvocationTargetException
+      {
+        try
+        {
+          doFinish(containerName, fileName, monitor);
+        }
+        catch(CoreException e)
+        {
+          throw new InvocationTargetException(e);
+        }
+        finally
+        {
+          monitor.done();
+        }
+      }
+    };
+    try
+    {
+      getContainer().run(true, false, op);
+    }
+    catch(InterruptedException e)
+    {
+      return false;
+    }
+    catch(InvocationTargetException e)
+    {
+      Throwable realException = e.getTargetException();
+      MessageDialog.openError(getShell(), "Error", realException.getMessage());
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * The worker method. It will find the container, create the
+   * file if missing or just replace its contents, and open
+   * the editor on the newly created file.
+   */
+  private void doFinish(String containerName, String fileName,
+      IProgressMonitor monitor) throws CoreException
+  {
+    // create a sample file
+    monitor.beginTask("Creating " + fileName, 2);
+    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+    IResource resource = root.findMember(new Path(containerName));
+    if( !resource.exists() || !(resource instanceof IContainer) )
+    {
+      throwCoreException("Container \"" + containerName + "\" does not exist.");
+    }
+    IContainer container = (IContainer)resource;
+    final IFile file = container.getFile(new Path(fileName));
+    try
+    {
+      InputStream stream = openContentStream();
+      if( file.exists() )
+      {
+        file.setContents(stream, true, true, monitor);
+      }
+      else
+      {
+        file.create(stream, true, monitor);
+      }
+      stream.close();
+    }
+    catch(IOException e)
+    {}
+    monitor.worked(1);
+    monitor.setTaskName("Opening file for editing...");
+    getShell().getDisplay().asyncExec(new Runnable(){
+      public void run()
+      {
+        IWorkbenchPage page =
+            PlatformUI.getWorkbench().getActiveWorkbenchWindow()
+              .getActivePage();
+        try
+        {
+          IDE.openEditor(page, file, true);
+        }
+        catch(PartInitException e)
+        {}
+      }
+    });
+    monitor.worked(1);
+  }
+
+  /**
+   * We will initialize file contents with a sample text.
+   */
+  private InputStream openContentStream()
+  {
+    Calendar cal = Calendar.getInstance(TimeZone.getDefault());
+    String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    java.text.SimpleDateFormat sdf =
+        new java.text.SimpleDateFormat(DATE_FORMAT);
+    sdf.setTimeZone(TimeZone.getDefault());
+
+    String contents = ";;;; Created on " + sdf.format(cal.getTime()) + "\n";
+    return new ByteArrayInputStream(contents.getBytes());
+  }
+
+  private void throwCoreException(String message) throws CoreException
+  {
+    IStatus status =
+        new Status(IStatus.ERROR, LispPlugin.ID, IStatus.OK, message, null);
+    throw new CoreException(status);
+  }
+
+}

File src/org/lispdev/main/NewFileWizardPage.java

+package org.lispdev.main;
+
+import org.eclipse.core.resources.IContainer;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.dialogs.IDialogPage;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.dialogs.ContainerSelectionDialog;
+
+public class NewFileWizardPage extends WizardPage
+{
+  private Text containerText;
+
+  private Text fileText;
+
+  private final ISelection selection;
+
+  /**
+   * Constructor for SampleNewWizardPage.
+   *
+   * @param pageName
+   */
+  public NewFileWizardPage(ISelection selection)
+  {
+    super("wizardPage");
+    setTitle("Lisp File");
+    setDescription("This wizard creates a new lisp file.");
+    this.selection = selection;
+  }
+
+  /**
+   * @see IDialogPage#createControl(Composite)
+   */
+  public void createControl(Composite parent)
+  {
+    Composite container = new Composite(parent, SWT.NULL);
+    GridLayout layout = new GridLayout();
+    container.setLayout(layout);
+    layout.numColumns = 3;
+    layout.verticalSpacing = 9;
+    Label label = new Label(container, SWT.NULL);
+    label.setText("&Container:");
+
+    containerText = new Text(container, SWT.BORDER | SWT.SINGLE);
+    GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+    containerText.setLayoutData(gd);
+    containerText.addModifyListener(new ModifyListener(){
+      public void modifyText(ModifyEvent e)
+      {
+        dialogChanged();
+      }
+    });
+
+    Button button = new Button(container, SWT.PUSH);
+    button.setText("Browse...");
+    button.addSelectionListener(new SelectionAdapter(){
+      @Override
+      public void widgetSelected(SelectionEvent e)
+      {
+        handleBrowse();
+      }
+    });
+    label = new Label(container, SWT.NULL);
+    label.setText("&File name:");
+
+    fileText = new Text(container, SWT.BORDER | SWT.SINGLE);
+    gd = new GridData(GridData.FILL_HORIZONTAL);
+    fileText.setLayoutData(gd);
+    fileText.addModifyListener(new ModifyListener(){
+      public void modifyText(ModifyEvent e)
+      {
+        dialogChanged();
+      }
+    });
+    initialize();
+    dialogChanged();
+    setControl(container);
+    fileText.setFocus();
+  }
+
+  /**
+   * Tests if the current workbench selection is a suitable container to use.
+   */
+
+  private void initialize()
+  {
+    if( selection != null && selection.isEmpty() == false
+        && selection instanceof IStructuredSelection )
+    {
+      IStructuredSelection ssel = (IStructuredSelection)selection;
+      if( ssel.size() > 1 ) return;
+      Object obj = ssel.getFirstElement();
+      if( obj instanceof IResource )
+      {
+        IContainer container;
+        if( obj instanceof IContainer ) container = (IContainer)obj;
+        else container = ((IResource)obj).getParent();
+        containerText.setText(container.getFullPath().toString());
+      }
+    }
+    fileText.setText("new-file.lisp");
+    fileText.setFocus();
+  }
+
+  /**
+   * Uses the standard container selection dialog to choose the new value for
+   * the container field.
+   */
+
+  private void handleBrowse()
+  {
+    ContainerSelectionDialog dialog =
+        new ContainerSelectionDialog(getShell(), ResourcesPlugin.getWorkspace()
+          .getRoot(), false, "Select new file container");
+    if( dialog.open() == ContainerSelectionDialog.OK )
+    {
+      Object[] result = dialog.getResult();
+      if( result.length == 1 )
+      {
+        containerText.setText(((Path)result[0]).toString());
+      }
+    }
+  }
+
+  /**
+   * Ensures that both text fields are set.
+   */
+
+  private void dialogChanged()
+  {
+    IResource container =
+        ResourcesPlugin.getWorkspace().getRoot()
+          .findMember(new Path(getContainerName()));
+    String fileName = getFileName();
+
+    if( getContainerName().length() == 0 )
+    {
+      updateStatus("File container must be specified");
+      return;
+    }
+    if( container == null
+        || (container.getType() & (IResource.PROJECT | IResource.FOLDER)) == 0 )
+    {
+      updateStatus("File container must exist");
+      return;
+    }
+    if( !container.isAccessible() )
+    {
+      updateStatus("Project must be writable");
+      return;
+    }
+    if( fileName.length() == 0 )
+    {
+      updateStatus("File name must be specified");
+      return;
+    }
+    if( fileName.replace('\\', '/').indexOf('/', 1) > 0 )
+    {
+      updateStatus("File name must be valid");
+      return;
+    }
+    if( !fileName.endsWith(".lisp") && !fileName.endsWith(".cl")
+        && !fileName.endsWith(".asd") && !fileName.endsWith(".el") )
+    {
+      updateStatus("File extension must be lisp, cl, asd, or el.");
+      return;
+    }
+
+    // Make sure the file doesn't already exist
+
+    if( container instanceof IContainer )
+    {
+      final IFile file = ((IContainer)container).getFile(new Path(fileName));
+
+      if( file.exists() )
+      {
+        updateStatus("File already exists. Use another name.");
+        return;
+      } // if
+    }
+    updateStatus(null);
+  }
+
+  private void updateStatus(String message)
+  {
+    setErrorMessage(message);
+    setPageComplete(message == null);
+  }
+
+  public String getContainerName()
+  {
+    return containerText.getText();
+  }
+
+  public String getFileName()
+  {
+    return fileText.getText();
+  }
+}

File src/org/lispdev/main/NewProjectWizPage1.java

+package org.lispdev.main;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.DirectoryDialog;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Text;
+
+public class NewProjectWizPage1 extends WizardPage
+{
+  private Text projectName;
+  private Text customProjectPath;
+  public boolean useUnitTests = true;
+  public boolean makeExampleFunction = true;
+
+  /**
+   * Constructor.
+   *
+   * @param selection
+   *          The selection this wizard was called on.
+   */
+  public NewProjectWizPage1(ISelection selection)
+  {
+    super("wizardPage");
+    setTitle("New Lisp Project");
+    setDescription("This wizard creates a new Lisp project");
+    // this.selection = selection;
+  }
+
+  public void createControl(final Composite parent)
+  {
+    Composite container = new Composite(parent, SWT.NULL);
+    GridLayout layout = new GridLayout(3, false);
+    layout.verticalSpacing = 2;
+    container.setLayout(layout);
+    GridData gd;
+
+    Label label = new Label(container, SWT.NULL);
+    label.setText("Project name:");
+
+    projectName = new Text(container, SWT.BORDER | SWT.SINGLE);
+    projectName.addModifyListener(new ValidationListener());
+    projectName.setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+    gd.horizontalSpan = 2;
+
+    // GridData.horizontalSpan = 3 isn't cooperating; messy, but effective
+    new Label(container, SWT.NULL);
+    new Label(container, SWT.NULL);
+    new Label(container, SWT.NULL);
+
+    final Button useDefaultLocation = new Button(container, SWT.CHECK);
+    new Label(container, SWT.NULL);
+    new Label(container, SWT.NULL);
+
+    label = new Label(container, SWT.NULL);
+    label.setText("Location:");
+
+    customProjectPath = new Text(container, SWT.BORDER | SWT.SINGLE);
+    customProjectPath.setEditable(false);
+    customProjectPath.addModifyListener(new ValidationListener());
+    customProjectPath
+      .setLayoutData(gd = new GridData(GridData.FILL_HORIZONTAL));
+
+    final Button chooseLocation = new Button(container, SWT.PUSH);
+    chooseLocation.setEnabled(false);
+    customProjectPath.setEnabled(false);
+
+    final Button useTests = new Button(container, SWT.CHECK);
+    new Label(container, SWT.NULL);
+    new Label(container, SWT.NULL);
+
+    final Button makeExample = new Button(container, SWT.CHECK);
+    new Label(container, SWT.NULL);
+    new Label(container, SWT.NULL);
+
+    useDefaultLocation.setSelection(true);
+    useDefaultLocation.addSelectionListener(new SelectionListener(){
+      public void widgetDefaultSelected(SelectionEvent e)
+      {
+        widgetSelected(e);
+      }
+
+      public void widgetSelected(SelectionEvent e)
+      {
+        boolean useDefaultPath = useDefaultLocation.getSelection();
+        chooseLocation.setEnabled(!useDefaultPath);
+        customProjectPath.setEnabled(!useDefaultPath);
+      }
+    });
+    useDefaultLocation.setText("Use default location");
+
+    useTests.setSelection(true);
+    useTests.addSelectionListener(new SelectionListener(){
+      public void widgetDefaultSelected(SelectionEvent e)
+      {
+        widgetSelected(e);
+      }
+
+      public void widgetSelected(SelectionEvent e)
+      {
+        useUnitTests = useTests.getSelection();
+      }
+    });
+    useTests.setText("Use lisp-unit testing framework");
+
+    makeExample.setSelection(true);
+    makeExample.addSelectionListener(new SelectionListener(){
+      public void widgetDefaultSelected(SelectionEvent e)
+      {
+        widgetSelected(e);
+      }
+
+      public void widgetSelected(SelectionEvent e)
+      {
+        makeExampleFunction = makeExample.getSelection();
+      }
+    });
+    makeExample.setText("Generate code for an example function.");
+
+    chooseLocation.setText("Browse...");
+    chooseLocation.addMouseListener(new MouseAdapter(){
+      @Override
+      public void mouseDown(MouseEvent e)
+      {
+        DirectoryDialog fd = new DirectoryDialog(parent.getShell(), SWT.OPEN);
+        fd.setMessage("Choose Location for New Lisp Project");
+        String path = fd.open();
+        if( path != null ) customProjectPath.setText(path);
+      }
+    });
+
+    initialize();
+    setControl(container);
+  }
+
+  /**
+   * Initializes the project name to one that is available.
+   */
+  private void initialize()
+  {
+    String name;
+    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+    IProject project;
+    int projectNum = 1;
+
+    // Find an available project name to use as the default
+    do
+    {
+      name = "new-lisp" + projectNum;
+
+      project = root.getProject(name);
+
+      projectNum++;
+    }
+    while( project.exists() && projectNum <= 99 );
+
+    projectName.setText(name);
+    projectName.setFocus();
+  } // void initialize()
+
+  private class ValidationListener implements ModifyListener
+  {
+    public void modifyText(ModifyEvent e)
+    {
+      String projectName = getProjectName();
+      // Characters which cannot be used in a resource name:
+      char[] invalids = {'*', '\\', '/', '"', ':', '<', '>', '|', '?'};
+
+      if( projectName.length() == 0 )
+      {
+        updateStatus("Project name must be specified");
+        return;
+      } // if
+
+      for(int i = 0; i < invalids.length; i++)
+      {
+        if( projectName.indexOf(invalids[i]) != -1 )
+        {
+          updateStatus(invalids[i]
+              + " is an invalid character in the project name " + projectName);
+          return;
+        } // if
+      } // for i
+
+      if( projectName.charAt(projectName.length() - 1) == '.' )
+      {
+        updateStatus("Resource name cannot end in a period.");
+        return;
+      } // if
+
+      // Make sure the project doesn't already exist
+      IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+      IProject newProject = root.getProject(getProjectName());
+      if( newProject.exists() )
+      {
+        updateStatus("A project with that name already exists.");
+        return;
+      } // if
+
+      if( customProjectPath.isEnabled() )
+      {
+        if( new File(getCustomProjectPath(), getProjectName()).exists() )
+        {
+          updateStatus("A directory with that project name already exists in that location.");
+          return;
+        }
+      }
+
+      updateStatus(null);
+    } // void dialogChanged()
+  }
+
+  /**
+   * Updates the wizard status message.
+   *
+   * @param message
+   *          The new status message.
+   */
+  private void updateStatus(String message)
+  {
+    setErrorMessage(message);
+    setPageComplete(message == null);
+  }
+
+  /**
+   * Gets the name to be used for this project.
+   *
+   * @return The new project name.
+   */
+  public String getProjectName()
+  {
+    return projectName.getText();
+  }
+
+  public String getCustomProjectPath()
+  {
+    return customProjectPath.isEnabled() ? customProjectPath.getText() : null;
+  }
+}

File src/org/lispdev/main/NewProjectWizard.java

+package org.lispdev.main;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.WorkbenchException;
+import org.eclipse.ui.ide.IDE;
+
+public class NewProjectWizard extends Wizard implements INewWizard
+{
+  public static final String ID = "org.lispdev.wizards.newProjectWizard";
+
+  private NewProjectWizPage1 page;
+  private ISelection selection;
+  private IWorkbench workbench;
+
+  public NewProjectWizard()
+  {
+    super();
+    setNeedsProgressMonitor(true);
+  }
+
+  @Override
+  public void addPages()
+  {
+    page = new NewProjectWizPage1(selection);
+    addPage(page);
+  }
+
+  @Override
+  public void init(IWorkbench workbench, IStructuredSelection selection)
+  {
+    this.workbench = workbench;
+    this.selection = selection;
+  }
+
+  @Override
+  public boolean performFinish()
+  {
+    final String projectName = page.getProjectName();
+    final String customProjectPath = page.getCustomProjectPath();
+    final boolean useLispUnit = page.useUnitTests;
+    final boolean makeExampleFunction = page.makeExampleFunction;
+    IRunnableWithProgress op = new IRunnableWithProgress(){
+      public void run(IProgressMonitor monitor)
+          throws InvocationTargetException
+      {
+        try
+        {
+          doFinish(projectName, customProjectPath, useLispUnit,
+              makeExampleFunction, monitor);
+        }
+        catch(CoreException e)
+        {
+          e.printStackTrace();
+          throw new InvocationTargetException(e);
+        }
+        finally
+        {
+          monitor.done();
+        }
+      }
+    };
+    try
+    {
+      getContainer().run(true, false, op);
+      workbench.showPerspective(LispPerspectiveFactory.ID,
+          workbench.getWorkbenchWindows()[0]);
+    }
+    catch(InterruptedException e)
+    {
+      return false;
+    }
+    catch(InvocationTargetException e)
+    {
+      Throwable realException = e.getTargetException();
+      MessageDialog.openError(getShell(), "Error", realException.getMessage());
+      return false;
+    }
+    catch(WorkbenchException e)
+    {
+      MessageDialog.openError(getShell(), "Error", e.getMessage());
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * The worker method. It will create a new project, then
+   * create the appropriate Soar heirarchy and files.
+   */
+  private void doFinish(String projectName, String customProjectPath,
+      final boolean useLispUnit, boolean makeExample, IProgressMonitor monitor)
+      throws CoreException
+  {
+    monitor.beginTask("Creating " + projectName, 10);
+
+    IWorkspace workspace = ResourcesPlugin.getWorkspace();
+    IWorkspaceRoot root = workspace.getRoot();
+    IProject newProject = root.getProject(projectName);
+
+    // creation of the project
+    if( newProject.exists() )
+    {
+      throwCoreException("Project \"" + projectName + "\" already exists");
+    }
+    else
+    {
+      IProjectDescription pdesc =
+          workspace.newProjectDescription(newProject.getName());
+      pdesc.setLocation(customProjectPath != null ? new Path(new File(
+          customProjectPath, projectName).getAbsolutePath()) : null);
+
+      newProject.create(pdesc, monitor);
+      newProject.open(monitor);
+
+      try
+      {
+        String[] natures = pdesc.getNatureIds();
+        String[] newNatures = new String[natures.length + 1];
+        System.arraycopy(natures, 0, newNatures, 0, natures.length);
+        newNatures[natures.length] = LispNature.ID;
+        pdesc.setNatureIds(newNatures);
+
+        newProject.setDescription(pdesc, IResource.FORCE, monitor);
+      }
+      catch(CoreException e)
+      {
+        e.printStackTrace();
+      } // catch
+
+    } // else
+