Added remote debugging support for ruby and tcl, applied patch from bug #198190
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/MainLaunchConfigurationTab.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/MainLaunchConfigurationTab.java
index d16ab76..2b0c2da 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/MainLaunchConfigurationTab.java
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/MainLaunchConfigurationTab.java
@@ -10,278 +10,45 @@
 package org.eclipse.dltk.debug.ui.launchConfigurations;
 
 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.IStatus;
 import org.eclipse.debug.core.ILaunchConfiguration;
 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
-import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
-import org.eclipse.dltk.core.DLTKCore;
-import org.eclipse.dltk.core.DLTKLanguageManager;
-import org.eclipse.dltk.core.IDLTKLanguageToolkit;
 import org.eclipse.dltk.core.IScriptProject;
-import org.eclipse.dltk.core.IModelElement;
-import org.eclipse.dltk.core.IScriptModel;
-import org.eclipse.dltk.core.ModelException;
 import org.eclipse.dltk.debug.ui.messages.DLTKLaunchConfigurationsMessages;
-import org.eclipse.dltk.internal.corext.util.Messages;
 import org.eclipse.dltk.internal.launching.DLTKLaunchingPlugin;
-import org.eclipse.dltk.internal.ui.DLTKUIStatus;
 import org.eclipse.dltk.launching.ScriptLaunchConfigurationConstants;
-import org.eclipse.dltk.ui.DLTKUILanguageManager;
-import org.eclipse.dltk.ui.DLTKUIPlugin;
-import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.dltk.ui.DLTKPluginImages;
+import org.eclipse.dltk.ui.preferences.FieldValidators;
+import org.eclipse.dltk.ui.preferences.IFieldValidator;
 import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.viewers.ILabelProvider;
-import org.eclipse.jface.window.Window;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ModifyEvent;
 import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
 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.Group;
 import org.eclipse.swt.widgets.Text;
-import org.eclipse.ui.IEditorInput;
-import org.eclipse.ui.IEditorPart;
-import org.eclipse.ui.IWorkbenchPage;
-import org.eclipse.ui.dialogs.ElementListSelectionDialog;
 import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
 import org.eclipse.ui.model.WorkbenchContentProvider;
 import org.eclipse.ui.model.WorkbenchLabelProvider;
 import org.eclipse.ui.views.navigator.ResourceComparator;
 
 public abstract class MainLaunchConfigurationTab extends
-		AbstractLaunchConfigurationTab {
-	/**
-	 * A listener which handles widget change events for the controls in this
-	 * tab.
-	 */
-	private class WidgetListener implements ModifyListener, SelectionListener {
-		public void modifyText(ModifyEvent e) {
-			setErrorMessage(null);
-			if (e.getSource() == fProjText) {
-				IScriptProject proj = getProject();
-				if (proj != null) {
-					if (!validateProject(proj))
-						setErrorMessage(DLTKLaunchConfigurationsMessages.error_notAValidProject);
-				} else
-					setErrorMessage(DLTKLaunchConfigurationsMessages.error_selectProject);
-			}
-			updateLaunchConfigurationDialog();
-		}
+		ScriptLaunchConfigurationTab {
 
-		public void widgetDefaultSelected(SelectionEvent e) {/* do nothing */
-		}
-
-		public void widgetSelected(SelectionEvent e) {
-			Object source = e.getSource();
-			if (source == fProjButton) {
-				handleProjectButtonSelected();
-			} else {
-				updateLaunchConfigurationDialog();
-			}
-		}
-	}
-
-	protected static final String EMPTY_STRING = ""; //$NON-NLS-1$
-	// Project UI widgets
-	protected Text fProjText;
-	private Button fProjButton;
-	private WidgetListener fListener = new WidgetListener();
-
-	/**
-	 * chooses a project for the type of launch config that it is
-	 * 
-	 * @return
-	 */
-	protected IScriptProject chooseProject() {
-		ILabelProvider labelProvider = DLTKUILanguageManager
-				.createLabelProvider(getNatureID());
-		ElementListSelectionDialog dialog = new ElementListSelectionDialog(
-				getShell(), labelProvider);
-		dialog
-				.setTitle(DLTKLaunchConfigurationsMessages.mainTab_chooseProject_title);
-		dialog
-				.setMessage(DLTKLaunchConfigurationsMessages.mainTab_chooseProject_message);
-		try {
-			dialog.setElements(DLTKCore.create(getWorkspaceRoot())
-					.getScriptProjects());
-		}// end try
-		catch (ModelException jme) {
-			DLTKLaunchingPlugin.log(jme);
-		}
-		IScriptProject project = getProject();
-		if (project != null) {
-			dialog.setInitialSelections(new Object[] { project });
-		}// end if
-		if (dialog.open() == Window.OK) {
-			return (IScriptProject) dialog.getFirstResult();
-		}// end if
-		return null;
-	}
-
-	/**
-	 * Creates the widgets for specifying a main type.
-	 * 
-	 * @param parent
-	 *            the parent composite
-	 */
-	protected void createProjectEditor(Composite parent) {
-		Font font = parent.getFont();
-		Group group = new Group(parent, SWT.NONE);
-		group.setText(DLTKLaunchConfigurationsMessages.mainTab_projectGroup);
-		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
-		group.setLayoutData(gd);
-		GridLayout layout = new GridLayout();
-		layout.numColumns = 2;
-		group.setLayout(layout);
-		group.setFont(font);
-		fProjText = new Text(group, SWT.SINGLE | SWT.BORDER);
-		gd = new GridData(GridData.FILL_HORIZONTAL);
-		fProjText.setLayoutData(gd);
-		fProjText.setFont(font);
-		fProjText.addModifyListener(fListener);
-		fProjButton = createPushButton(group,
-				DLTKLaunchConfigurationsMessages.mainTab_projectButton, null);
-		fProjButton.addSelectionListener(fListener);
-	}
-
-	/**
-	 * Convenience method to get access to thescriptmodel.
-	 */
-	private IScriptModel getScriptModel() {
-		return DLTKCore.create(getWorkspaceRoot());
-	}
-
-	/**
-	 * Return the IScriptProject corresponding to the project name in the
-	 * project name text field, or null if the text does not match a project
-	 * name.
-	 */
-	protected IScriptProject getProject() {
-		String projectName = fProjText.getText().trim();
-		if (projectName.length() < 1) {
-			return null;
-		}// end if
-		return getScriptModel().getScriptProject(projectName);
-	}
-
-	/**
-	 * Convenience method to get the workspace root.
-	 */
-	protected IWorkspaceRoot getWorkspaceRoot() {
-		return ResourcesPlugin.getWorkspace().getRoot();
-	}
-
-	protected abstract boolean validateProject(IScriptProject project);
-
-	protected String getLanguageName() {
-		try {
-			IDLTKLanguageToolkit toolkit = DLTKLanguageManager
-					.getLanguageToolkit(getNatureID());
-			return toolkit.getLanguageName();
-		} catch (CoreException e) {
-			
-		}
-
-		return null;
-	}
-
-	protected abstract String getNatureID();
-
-	/**
-	 * Show a dialog that lets the user select a project. This in turn provides
-	 * context for the main type, allowing the user to key a main type name, or
-	 * constraining the search for main types to the specified project.
-	 */
-	protected void handleProjectButtonSelected() {
-		IScriptProject project = chooseProject();
-		if (project == null)
-			return;
-		if (!validateProject(project)) {
-			String msg = Messages
-					.format(
-							DLTKLaunchConfigurationsMessages.mainTab_errorDlg_notALangProject,
-							new String[] { getLanguageName() });
-			String reason = Messages
-					.format(
-							DLTKLaunchConfigurationsMessages.mainTab_errorDlg_reasonNotALangProject,
-							new String[] { getLanguageName() });
-			ErrorDialog
-					.openError(
-							getShell(),
-							DLTKLaunchConfigurationsMessages.mainTab_errorDlg_invalidProject,
-							msg, DLTKUIStatus.createError(IStatus.ERROR,
-									reason, null));
-			return;
-		}
-		String projectName = project.getElementName();
-		fProjText.setText(projectName);
-	}// end handle selected
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#initializeFrom(org.eclipse.debug.core.ILaunchConfiguration)
-	 */
-	public void initializeFrom(ILaunchConfiguration config) {
-		updateProjectFromConfig(config);
+	private Text fScriptText;
+	
+	protected void doInitializeForm(ILaunchConfiguration config) {
 		updateMainModuleFromConfig(config);
-		if (fProjText.getText().trim().length() == 0
-				&& fMainText.getText().trim().length() == 0) {
-			// try to fill-in
-			IWorkbenchPage page = DLTKUIPlugin.getActivePage();
-			if (page != null) {
-				IEditorPart editor = page.getActiveEditor();
-				if (editor != null) {
-					IEditorInput editorInput = editor.getEditorInput();
-					if (editorInput != null) {
-						IModelElement me = DLTKUIPlugin
-								.getEditorInputModelElement(editorInput);
-						IScriptProject project = me.getScriptProject();
-						if (project != null && validateProject(project)) {
-							String projectName = project.getProject().getName();
-							String scriptName = me.getResource()
-									.getProjectRelativePath()
-									.toPortableString();// me.getResource().getLocation().toPortableString();
-							// /*me.getResource().getFullPath().toPortableString();*/
-							if (scriptName.trim().length() > 0) {
-								fProjText.setText(projectName);
-								fMainText.setText(scriptName);
-							}
-						}
-					}
-				}
-			}
-		}
 	}
 
-	/**
-	 * updates the project text field form the configuration
-	 * 
-	 * @param config
-	 *            the configuration we are editing
-	 */
-	protected void updateProjectFromConfig(ILaunchConfiguration config) {
-		String projectName = EMPTY_STRING;
-		try {
-			projectName = config.getAttribute(
-					ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME,
-					EMPTY_STRING);
-		}// end try
-		catch (CoreException ce) {
-			DLTKLaunchingPlugin.log(ce);
-		}
-		fProjText.setText(projectName);
-	}
-
-	protected Text fMainText;
 	private Button fSearchButton;
 
 	/**
@@ -300,11 +67,11 @@
 		layout.numColumns = 2;
 		mainGroup.setLayout(layout);
 		mainGroup.setFont(font);
-		fMainText = new Text(mainGroup, SWT.SINGLE | SWT.BORDER);
+		fScriptText = new Text(mainGroup, SWT.SINGLE | SWT.BORDER);
 		gd = new GridData(GridData.FILL_HORIZONTAL);
-		fMainText.setLayoutData(gd);
-		fMainText.setFont(font);
-		fMainText.addModifyListener(new ModifyListener() {
+		fScriptText.setLayoutData(gd);
+		fScriptText.setFont(font);
+		fScriptText.addModifyListener(new ModifyListener() {
 			public void modifyText(ModifyEvent e) {
 				updateLaunchConfigurationDialog();
 			}
@@ -341,7 +108,7 @@
 			IResource resource = (IResource) dialog.getFirstResult();
 			String arg = resource.getProjectRelativePath().toPortableString();
 			// check extension
-			fMainText.setText(arg);
+			fScriptText.setText(arg);
 		}
 	}
 
@@ -357,79 +124,87 @@
 			mainModuleName = config.getAttribute(
 					ScriptLaunchConfigurationConstants.ATTR_MAIN_SCRIPT_NAME,
 					EMPTY_STRING);
-		}// end try
-		catch (CoreException ce) {
-			DLTKLaunchingPlugin.log(ce);
 		}
-		fMainText.setText(mainModuleName);
+		catch (CoreException ce) {
+			DLTKLaunchingPlugin.log(ce);			
+		}
+		
+		if (EMPTY_STRING.equals(mainModuleName))
+		{
+			String[] guesses = getProjectAndScriptNames();
+			if (guesses != null)
+			{
+				super.setProjectName(guesses[0]);
+				mainModuleName = guesses[1];
+			}
+		}
+		
+		fScriptText.setText(mainModuleName);
 	}
 
-	public void createControl(Composite parent) {
-		Font font = parent.getFont();
-		Composite comp = new Composite(parent, SWT.NONE);
-		setControl(comp);
-		// PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
-		// IScriptDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_MAIN_TAB);
-		GridLayout topLayout = new GridLayout();
-		topLayout.verticalSpacing = 0;
-		comp.setLayout(topLayout);
-		comp.setFont(font);
-		createProjectEditor(comp);
-		createVerticalSpacer(comp, 1);
-		createMainModuleEditor(comp,
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#doCreateControl(org.eclipse.swt.widgets.Composite)
+	 */
+	protected void doCreateControl(Composite composite) {
+		createMainModuleEditor(composite,
 				DLTKLaunchConfigurationsMessages.mainTab_mainModule);
 	}
 
+	/*
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+	 */
 	public String getName() {
 		return DLTKLaunchConfigurationsMessages.mainTab_title;
 	}
 
-	public void performApply(ILaunchConfigurationWorkingCopy configuration) {
-		// Project name
-		final String project = fProjText.getText().trim();
-		configuration.setAttribute(
-				ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME, project);
-
-		// Script
-		final String mainModule = fMainText.getText().trim();
-		configuration.setAttribute(
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#doPerformApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+	 */
+	protected void doPerformApply(ILaunchConfigurationWorkingCopy config) {
+		config.setAttribute(
 				ScriptLaunchConfigurationConstants.ATTR_MAIN_SCRIPT_NAME,
-				mainModule);
+				getScriptName());
 	}
 
-	protected boolean validateProject() {
-		String projectName = fProjText.getText().trim();
-		if (projectName.length() == 0) {
-			setErrorMessage(DLTKLaunchConfigurationsMessages.error_selectProject);
-			return false;
-		}
+	private String getScriptName() {
+		return fScriptText.getText().trim();
+	}
+
+	/**
+	 * Validates the selected launch script.
+	 * 
+	 * @return true if the selected script is valid, false otherwise
+	 */
+	protected boolean validateScript() {
+		IFieldValidator validator = new FieldValidators.FilePathValidator();
+		
+		String projectName = getProjectName();
 		IScriptProject proj = getScriptModel().getScriptProject(projectName);
-		if (proj == null || !validateProject(proj)) {
-			setErrorMessage(DLTKLaunchConfigurationsMessages.error_notAValidProject);
+		
+		String script = proj.getProject().getLocation().toPortableString() + '/' + getScriptName();
+		IStatus result = validator.validate(script);
+
+		if (!result.isOK())
+		{
+			setErrorMessage(DLTKLaunchConfigurationsMessages.error_scriptNotFound);
 			return false;
 		}
+		
 		return true;
 	}
 
-	protected boolean validateModule() {
-		String mainModule = fMainText.getText().trim();
-		if (mainModule.length() == 0) {
-			setErrorMessage(DLTKLaunchConfigurationsMessages.error_selectScript);
-			return false;
-		}
-		return true;
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#doCanSave()
+	 */
+	protected boolean doCanSave() {
+		return validateScript();
 	}
 
-	public boolean canSave() {
-		return validateProject() && validateModule();
-	}
-
-	public boolean isValid(ILaunchConfiguration launchConfig) {
-		setMessage(null);
-		setErrorMessage(null);
-		return validateProject() && validateModule();
-	}
-
-	public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+	
+	/*
+	 * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage()
+	 */
+	public Image getImage() {
+		return DLTKPluginImages.get(DLTKPluginImages.IMG_OBJS_CLASS);
 	}
 }
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/RemoteLaunchConfigurationTab.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/RemoteLaunchConfigurationTab.java
new file mode 100644
index 0000000..ad2e90f
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/RemoteLaunchConfigurationTab.java
@@ -0,0 +1,153 @@
+package org.eclipse.dltk.debug.ui.launchConfigurations;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.IDebugUIConstants;
+import org.eclipse.dltk.debug.ui.messages.DLTKLaunchConfigurationsMessages;
+import org.eclipse.dltk.launching.ScriptLaunchConfigurationConstants;
+import org.eclipse.dltk.ui.preferences.FieldValidators;
+import org.eclipse.dltk.ui.util.SWTFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Text;
+
+public abstract class RemoteLaunchConfigurationTab extends
+		ScriptLaunchConfigurationTab {
+
+	private static int DEFAULT_PORT = 10000;
+	private static String DEFAULT_IDEKEY = "idekey";
+
+	private Text port;
+	private Text ideKey;
+
+	/*
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#getName()
+	 */
+	public String getName() {
+		return DLTKLaunchConfigurationsMessages.remoteTab_title;
+	}
+
+	/*
+	 * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#getImage()
+	 */
+	public Image getImage() {
+		return DebugUITools.getImage(IDebugUIConstants.IMG_LCL_DISCONNECT);
+	}
+
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#doInitializeForm(org.eclipse.debug.core.ILaunchConfiguration)
+	 */
+	protected void doInitializeForm(ILaunchConfiguration config) {
+		String text = null;
+		try {
+			text = config.getAttribute(
+					ScriptLaunchConfigurationConstants.ATTR_DLTK_DBGP_PORT,
+					Integer.toString(DEFAULT_PORT));
+		} catch (CoreException e) {
+			// log?
+			text = Integer.toString(DEFAULT_PORT);
+		}
+
+		port.setText(text);
+
+		try {
+			text = config
+					.getAttribute(
+							ScriptLaunchConfigurationConstants.ATTR_DLTK_DBGP_SESSION_ID,
+							DEFAULT_IDEKEY);
+		} catch (CoreException e) {
+			// log?
+			text = DEFAULT_IDEKEY;
+		}
+
+		ideKey.setText(text);
+	}
+
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#doPerformApply(org.eclipse.debug.core.ILaunchConfigurationWorkingCopy)
+	 */
+	protected void doPerformApply(ILaunchConfigurationWorkingCopy config) {
+		config.setAttribute(
+				ScriptLaunchConfigurationConstants.ATTR_DLTK_DBGP_PORT, port
+						.getText().trim());
+		config.setAttribute(
+				ScriptLaunchConfigurationConstants.ATTR_DLTK_DBGP_SESSION_ID,
+				ideKey.getText().trim());
+	}
+
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#doCanSave()
+	 */
+	protected boolean doCanSave() {
+		return validatePort() && validateIdeKey();
+	}
+
+	
+	protected boolean validatePort() {
+		IStatus result = FieldValidators.PORT_VALIDATOR
+				.validate(port.getText());
+
+		if (!result.isOK()) {
+			setErrorMessage(result.getMessage());
+			return false;
+		}
+
+		return true;
+	}
+
+	protected boolean validateIdeKey() {
+		String projectName = ideKey.getText().trim();
+		if (projectName.length() == 0) {
+			setErrorMessage(DLTKLaunchConfigurationsMessages.remoteError_ideKeyEmpty);
+			return false;
+		}
+
+		return true;
+	}
+
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#guessProjectName()
+	 */
+	protected String guessProjectName() {
+		String[] guesses = getProjectAndScriptNames();
+
+		return (guesses == null) ? EMPTY_STRING : guesses[0];
+	}
+
+	/*
+	 * @see org.eclipse.dltk.debug.ui.launchConfigurations.ScriptLaunchConfigurationTab#doCreateControl(org.eclipse.swt.widgets.Composite)
+	 */
+	protected void doCreateControl(Composite composite) {
+		Group group = SWTFactory
+				.createGroup(
+						composite,
+						DLTKLaunchConfigurationsMessages.remoteTab_connectionProperties,
+						2, 1, GridData.FILL_HORIZONTAL);
+
+		SWTFactory.createLabel(group,
+				DLTKLaunchConfigurationsMessages.remoteTab_connectionPort, 1);
+		port = SWTFactory.createText(group, SWT.BORDER, 1, EMPTY_STRING);
+		port.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				updateLaunchConfigurationDialog();
+			}
+		});
+
+		SWTFactory.createLabel(group,
+				DLTKLaunchConfigurationsMessages.remoteTab_connectionIdeKey, 1);
+		ideKey = SWTFactory.createText(group, SWT.BORDER, 1, EMPTY_STRING);
+		ideKey.addModifyListener(new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				updateLaunchConfigurationDialog();
+			}
+		});
+	}
+}
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/ScriptLaunchConfigurationTab.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/ScriptLaunchConfigurationTab.java
new file mode 100644
index 0000000..616964a
--- /dev/null
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/launchConfigurations/ScriptLaunchConfigurationTab.java
@@ -0,0 +1,414 @@
+package org.eclipse.dltk.debug.ui.launchConfigurations;
+
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
+import org.eclipse.dltk.core.DLTKCore;
+import org.eclipse.dltk.core.DLTKLanguageManager;
+import org.eclipse.dltk.core.IDLTKLanguageToolkit;
+import org.eclipse.dltk.core.IModelElement;
+import org.eclipse.dltk.core.IScriptModel;
+import org.eclipse.dltk.core.IScriptProject;
+import org.eclipse.dltk.core.ModelException;
+import org.eclipse.dltk.debug.ui.messages.DLTKLaunchConfigurationsMessages;
+import org.eclipse.dltk.internal.corext.util.Messages;
+import org.eclipse.dltk.internal.launching.DLTKLaunchingPlugin;
+import org.eclipse.dltk.internal.ui.DLTKUIStatus;
+import org.eclipse.dltk.launching.ScriptLaunchConfigurationConstants;
+import org.eclipse.dltk.ui.DLTKUILanguageManager;
+import org.eclipse.dltk.ui.DLTKUIPlugin;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Font;
+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.Group;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.dialogs.ElementListSelectionDialog;
+
+public abstract class ScriptLaunchConfigurationTab extends
+		AbstractLaunchConfigurationTab {
+
+	protected static final String EMPTY_STRING = "";
+
+	private Text fProjText;
+	private Button fProjButton;
+	private WidgetListener fListener = new WidgetListener();
+
+	// protected Text fMainText;
+
+	/**
+	 * A listener which handles widget change events for the controls in this
+	 * tab.
+	 */
+	class WidgetListener implements ModifyListener, SelectionListener {
+		public void modifyText(ModifyEvent e) {
+			setErrorMessage(null);
+			if (e.getSource() == fProjText) {
+				IScriptProject proj = getProject();
+				if (proj != null) {
+					if (!validateProject(proj))
+						setErrorMessage(DLTKLaunchConfigurationsMessages.error_notAValidProject);
+				} else
+					setErrorMessage(DLTKLaunchConfigurationsMessages.error_selectProject);
+			}
+			updateLaunchConfigurationDialog();
+		}
+
+		public void widgetDefaultSelected(SelectionEvent e) {/* do nothing */
+		}
+
+		public void widgetSelected(SelectionEvent e) {
+			Object source = e.getSource();
+			if (source == fProjButton) {
+				handleProjectButtonSelected();
+			} else {
+				updateLaunchConfigurationDialog();
+			}
+		}
+	}
+
+	/*
+	 * @see org.eclipse.debug.ui.ILaunchConfigurationTab#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public final void createControl(Composite parent) {
+		Font font = parent.getFont();
+		Composite comp = new Composite(parent, SWT.NONE);
+		setControl(comp);
+
+		GridLayout topLayout = new GridLayout();
+		topLayout.verticalSpacing = 0;
+		comp.setLayout(topLayout);
+		comp.setFont(font);
+
+		createProjectEditor(comp);
+		createVerticalSpacer(comp, 1);
+
+		doCreateControl(comp);
+
+		// PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(),
+		// IScriptDebugHelpContextIds.LAUNCH_CONFIGURATION_DIALOG_MAIN_TAB);
+	}
+
+	public final void initializeFrom(ILaunchConfiguration config) {
+		updateProjectFromConfig(config);
+		doInitializeForm(config);
+	}
+
+	public final void performApply(ILaunchConfigurationWorkingCopy config) {
+		String project = fProjText.getText().trim();
+		config.setAttribute(
+				ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME, project);
+
+		doPerformApply(config);
+	}
+
+	protected abstract void doPerformApply(
+			ILaunchConfigurationWorkingCopy config);
+
+	/**
+	 * Performs the sub-class specific configuration tab initialization.
+	 * 
+	 * @param config
+	 *            launch configuration
+	 * 
+	 * @see #initializeFrom(ILaunchConfiguration)
+	 */
+	protected abstract void doInitializeForm(ILaunchConfiguration config);
+
+	/**
+	 * Creates the sub-class specific control.
+	 * 
+	 * <p>
+	 * Sub-classes can widgets directly to the <code>composite</code> object
+	 * that is passed to them.
+	 * </p>
+	 * 
+	 * @param composite
+	 *            control composite
+	 * 
+	 * @see #createControl(Composite)
+	 */
+	protected abstract void doCreateControl(Composite composite);
+
+	/**
+	 * Creates a project editor
+	 * 
+	 * <p>
+	 * Creates a group containing an input text field and 'Browse' button to
+	 * select a project from the workspace.
+	 * </p>
+	 * 
+	 * @param parent
+	 *            the parent composite
+	 */
+	protected void createProjectEditor(Composite parent) {
+		Font font = parent.getFont();
+		Group group = new Group(parent, SWT.NONE);
+		group.setText(DLTKLaunchConfigurationsMessages.mainTab_projectGroup);
+		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+		group.setLayoutData(gd);
+		GridLayout layout = new GridLayout();
+		layout.numColumns = 2;
+		group.setLayout(layout);
+		group.setFont(font);
+		fProjText = new Text(group, SWT.SINGLE | SWT.BORDER);
+		gd = new GridData(GridData.FILL_HORIZONTAL);
+		fProjText.setLayoutData(gd);
+		fProjText.setFont(font);
+		fProjText.addModifyListener(fListener);
+		fProjButton = createPushButton(group,
+				DLTKLaunchConfigurationsMessages.mainTab_projectButton, null);
+		fProjButton.addSelectionListener(fListener);
+	}
+
+	/**
+	 * Return the IScriptProject corresponding to the project name in the
+	 * project name text field, or null if the text does not match a project
+	 * name.
+	 */
+	protected IScriptProject getProject() {
+		String projectName = fProjText.getText().trim();
+		if (projectName.length() < 1) {
+			return null;
+		}// end if
+		return getScriptModel().getScriptProject(projectName);
+	}
+
+	/**
+	 * chooses a project for the type of launch config that it is
+	 * 
+	 * @return
+	 */
+	protected IScriptProject chooseProject() {
+		final ILabelProvider labelProvider = DLTKUILanguageManager
+				.createLabelProvider(getNatureID());
+		final ElementListSelectionDialog dialog = new ElementListSelectionDialog(
+				getShell(), labelProvider);
+		dialog
+				.setTitle(DLTKLaunchConfigurationsMessages.mainTab_chooseProject_title);
+		dialog
+				.setMessage(DLTKLaunchConfigurationsMessages.mainTab_chooseProject_message);
+
+		try {
+			IScriptProject[] projects = DLTKCore.create(getWorkspaceRoot())
+					.getOpenedScriptProjects(getNatureID());
+			dialog.setElements(projects);
+		} catch (ModelException e) {
+			DLTKLaunchingPlugin.log(e);
+		}
+
+		final IScriptProject project = getProject();
+		if (project != null) {
+			dialog.setInitialSelections(new Object[] { project });
+		}
+
+		if (dialog.open() == Window.OK) {
+			return (IScriptProject) dialog.getFirstResult();
+		}
+
+		return null;
+	}
+
+	/**
+	 * Convenience method to get access to thescriptmodel.
+	 */
+	protected IScriptModel getScriptModel() {
+		return DLTKCore.create(getWorkspaceRoot());
+	}
+
+	/**
+	 * Convenience method to get the workspace root.
+	 */
+	protected IWorkspaceRoot getWorkspaceRoot() {
+		return ResourcesPlugin.getWorkspace().getRoot();
+	}
+
+	protected abstract boolean validateProject(IScriptProject project);
+
+	protected String getLanguageName() {
+		try {
+			IDLTKLanguageToolkit toolkit = DLTKLanguageManager
+					.getLanguageToolkit(getNatureID());
+			return toolkit.getLanguageName();
+		} catch (CoreException e) {
+
+		}
+
+		return null;
+	}
+
+	protected abstract String getNatureID();
+
+	/**
+	 * Show a dialog that lets the user select a project. This in turn provides
+	 * context for the main type, allowing the user to key a main type name, or
+	 * constraining the search for main types to the specified project.
+	 */
+	protected void handleProjectButtonSelected() {
+		IScriptProject project = chooseProject();
+		if (project == null)
+			return;
+		if (!validateProject(project)) {
+			String msg = Messages
+					.format(
+							DLTKLaunchConfigurationsMessages.mainTab_errorDlg_notALangProject,
+							new String[] { getLanguageName() });
+			String reason = Messages
+					.format(
+							DLTKLaunchConfigurationsMessages.mainTab_errorDlg_reasonNotALangProject,
+							new String[] { getLanguageName() });
+			ErrorDialog
+					.openError(
+							getShell(),
+							DLTKLaunchConfigurationsMessages.mainTab_errorDlg_invalidProject,
+							msg, DLTKUIStatus.createError(IStatus.ERROR,
+									reason, null));
+			return;
+		}
+		String projectName = project.getElementName();
+		fProjText.setText(projectName);
+	}
+
+	/**
+	 * Attemps to guess the current project and script being launched.
+	 * 
+	 * <p>
+	 * If the project and script are able to be determined, the string array
+	 * returned will contain the project name in position 0 and the script name
+	 * in position 1.
+	 * </p>
+	 * 
+	 * @return project name and script name as string array, or
+	 *         <code>null</code> if they could not be determined.
+	 */
+	protected String[] getProjectAndScriptNames() {
+		IWorkbenchPage page = DLTKUIPlugin.getActivePage();
+		if (page == null) {
+			return null;
+		}
+
+		IEditorPart editor = page.getActiveEditor();
+		if (editor == null) {
+			return null;
+		}
+
+		IEditorInput editorInput = editor.getEditorInput();
+		if (editorInput == null) {
+			return null;
+		}
+
+		IModelElement me = DLTKUIPlugin.getEditorInputModelElement(editorInput);
+		IScriptProject project = me.getScriptProject();
+		if (project != null && validateProject(project)) {
+			String projectName = project.getProject().getName();
+
+			/*
+			 * TODO: validate script is an executable and not library/module
+			 * otherwise, return null and make user select
+			 */
+			String scriptName = me.getResource().getProjectRelativePath()
+					.toPortableString();
+			// me.getResource().getLocation().toPortableString();
+			// /*me.getResource().getFullPath().toPortableString();*/
+
+			return new String[] { projectName, scriptName };
+		}
+		return null;
+	}
+
+	/**
+	 * Sets the name of the project associated with the launch configuration
+	 * 
+	 * @param name
+	 *            project name
+	 */
+	protected final void setProjectName(String name) {
+		fProjText.setText(name);
+	}
+
+	protected final String getProjectName() {
+		return fProjText.getText().trim();
+	}
+
+	/**
+	 * updates the project text field form the configuration
+	 * 
+	 * @param config
+	 *            the configuration we are editing
+	 */
+	protected void updateProjectFromConfig(ILaunchConfiguration config) {
+		String projectName = EMPTY_STRING;
+		try {
+			projectName = config.getAttribute(
+					ScriptLaunchConfigurationConstants.ATTR_PROJECT_NAME,
+					EMPTY_STRING);
+		} catch (CoreException ce) {
+			DLTKLaunchingPlugin.log(ce);
+		}
+
+		if (EMPTY_STRING.equals(projectName)) {
+			projectName = guessProjectName();
+		}
+
+		fProjText.setText(projectName);
+	}
+
+	protected String guessProjectName() {
+		return EMPTY_STRING;
+	}
+
+	protected boolean validateProject() {
+		String projectName = getProjectName();
+		if (projectName.length() == 0) {
+			setErrorMessage(DLTKLaunchConfigurationsMessages.error_selectProject);
+			return false;
+		}
+		IScriptProject proj = getScriptModel().getScriptProject(projectName);
+		if (proj == null || !validateProject(proj)) {
+			setErrorMessage(DLTKLaunchConfigurationsMessages.error_notAValidProject);
+			return false;
+		}
+		return true;
+	}
+
+	public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
+	}
+
+	/*
+	 * @see org.eclipse.debug.ui.AbstractLaunchConfigurationTab#canSave()
+	 */
+	public boolean canSave() {
+		return validateProject() && doCanSave();
+	}
+
+	protected abstract boolean doCanSave();
+
+	public boolean isValid(ILaunchConfiguration launchConfig) {
+		// clear the error messages first
+		setMessage(null);
+		setErrorMessage(null);
+
+		// if the configuration can be saved, it can be launched
+		boolean canSave = canSave();
+
+		// TODO: check launch configuration?
+		return canSave;
+	}
+
+}
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/DLTKLaunchConfigurationsMessages.java b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/DLTKLaunchConfigurationsMessages.java
index 11fd8c1..2bef4ad 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/DLTKLaunchConfigurationsMessages.java
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/DLTKLaunchConfigurationsMessages.java
@@ -28,7 +28,15 @@
 	public static String mainTab_errorDlg_notALangProject;
 	public static String mainTab_errorDlg_reasonNotALangProject;
 	public static String error_selectScript;
+	public static String error_scriptNotFound;
 
+	public static String remoteTab_title;
+	public static String remoteTab_connectionProperties;
+	public static String remoteTab_connectionPort;
+	public static String remoteTab_connectionIdeKey;
+	public static String remoteError_ideKeyEmpty;
+	
+	
 	private DLTKLaunchConfigurationsMessages() {
 	// dont instatiate
 	}
diff --git a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/ScriptLaunchConfigurationsMessages.properties b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/ScriptLaunchConfigurationsMessages.properties
index 5e824db..8300936 100644
--- a/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/ScriptLaunchConfigurationsMessages.properties
+++ b/core/plugins/org.eclipse.dltk.debug.ui/src/org/eclipse/dltk/debug/ui/messages/ScriptLaunchConfigurationsMessages.properties
@@ -17,8 +17,15 @@
 mainTab_searchButton_title=Script selection
 mainTab_searchButton_message=Select a script to launch
 error_selectProject=Select project
-error_notAValidProject=It is not a valid project name
+error_notAValidProject=Please select a valid project
 mainTab_errorDlg_invalidProject=Invalid project
 mainTab_errorDlg_notALangProject=It is not a {0} project
 mainTab_errorDlg_reasonNotALangProject=You have selected not a {0} project
-error_selectScript=Select a script to launch 
\ No newline at end of file
+error_selectScript=Select a script to launch 
+error_scriptNotFound=The selected script does not exist.
+
+remoteTab_title=Connect
+remoteTab_connectionProperties=Connection Properties:
+remoteTab_connectionPort=Port:
+remoteTab_connectionIdeKey=Ide Key:
+remoteError_ideKeyEmpty=Please specify an ide key.
\ No newline at end of file