diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 30629652201..02c0e62bcb2 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -456,9 +456,11 @@
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfiguration.kt b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfiguration.kt
new file mode 100644
index 00000000000..d7c3bf5ad4d
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfiguration.kt
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.run.script.standalone
+
+import com.intellij.execution.*
+import com.intellij.execution.application.BaseJavaApplicationCommandLineState
+import com.intellij.execution.configuration.EnvironmentVariablesComponent
+import com.intellij.execution.configurations.*
+import com.intellij.execution.runners.ExecutionEnvironment
+import com.intellij.execution.util.JavaParametersUtil
+import com.intellij.execution.util.ProgramParametersUtil
+import com.intellij.openapi.components.PathMacroManager
+import com.intellij.openapi.options.SettingsEditor
+import com.intellij.openapi.options.SettingsEditorGroup
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.DefaultJDOMExternalizer
+import com.intellij.openapi.vfs.LocalFileSystem
+import com.intellij.psi.PsiElement
+import com.intellij.refactoring.listeners.RefactoringElementAdapter
+import com.intellij.refactoring.listeners.RefactoringElementListener
+import org.jdom.Element
+import org.jetbrains.kotlin.idea.run.script.standalone.KotlinStandaloneScriptRunConfigurationProducer.Companion.pathFromPsiElement
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.utils.PathUtil
+import java.io.File
+import java.util.*
+
+class KotlinStandaloneScriptRunConfiguration(
+ project: Project,
+ factory: ConfigurationFactory,
+ name: String?
+) : LocatableConfigurationBase(project, factory, name), CommonJavaRunConfigurationParameters, RefactoringListenerProvider {
+ @JvmField
+ var filePath: String? = null
+ @JvmField
+ var vmParameters: String? = null
+ @JvmField
+ var alternativeJrePath: String? = null
+ @JvmField
+ var programParameters: String? = null
+ @JvmField
+ var envs: MutableMap = LinkedHashMap()
+ @JvmField
+ var passParentEnvs: Boolean = true
+ @JvmField
+ var workingDirectory: String? = null
+ @JvmField
+ var isAlternativeJrePathEnabled: Boolean = false
+
+ override fun getVMParameters() = vmParameters
+ override fun setVMParameters(value: String?) {
+ vmParameters = value
+ }
+
+ override fun getAlternativeJrePath() = alternativeJrePath
+ override fun setAlternativeJrePath(path: String?) {
+ alternativeJrePath = path
+ }
+
+ override fun getProgramParameters() = programParameters
+ override fun setProgramParameters(value: String?) {
+ programParameters = value
+ }
+
+ override fun getEnvs() = envs
+ override fun setEnvs(envs: MutableMap) {
+ this.envs = envs
+ }
+
+ override fun getWorkingDirectory() = workingDirectory
+ override fun setWorkingDirectory(value: String?) {
+ workingDirectory = value
+ }
+
+ override fun isPassParentEnvs() = passParentEnvs
+ override fun setPassParentEnvs(passParentEnvs: Boolean) {
+ this.passParentEnvs = passParentEnvs
+ }
+
+ override fun isAlternativeJrePathEnabled() = isAlternativeJrePathEnabled
+ override fun setAlternativeJrePathEnabled(enabled: Boolean) {
+ isAlternativeJrePathEnabled = enabled
+ }
+
+ override fun getState(executor: Executor, environment: ExecutionEnvironment): RunProfileState = ScriptCommandLineState(environment, this)
+
+ override fun suggestedName() = filePath?.let { File(it).nameWithoutExtension }
+
+ override fun getConfigurationEditor(): SettingsEditor {
+ val group = SettingsEditorGroup()
+ group.addEditor(ExecutionBundle.message("run.configuration.configuration.tab.title"), KotlinStandaloneScriptRunConfigurationEditor(project))
+ JavaRunConfigurationExtensionManager.getInstance().appendEditors(this, group)
+ return group
+ }
+
+ override fun writeExternal(element: Element) {
+ super.writeExternal(element)
+ JavaRunConfigurationExtensionManager.getInstance().writeExternal(this, element)
+ DefaultJDOMExternalizer.writeExternal(this, element)
+ EnvironmentVariablesComponent.writeExternal(element, getEnvs())
+ PathMacroManager.getInstance(project).collapsePathsRecursively(element)
+ }
+
+ override fun readExternal(element: Element) {
+ PathMacroManager.getInstance(project).expandPaths(element)
+ super.readExternal(element)
+ JavaRunConfigurationExtensionManager.getInstance().readExternal(this, element)
+ DefaultJDOMExternalizer.readExternal(this, element)
+ EnvironmentVariablesComponent.readExternal(element, getEnvs())
+ }
+
+ override fun checkConfiguration() {
+ JavaParametersUtil.checkAlternativeJRE(this)
+ ProgramParametersUtil.checkWorkingDirectoryExist(this, project, null)
+ JavaRunConfigurationExtensionManager.checkConfigurationIsValid(this)
+
+ if (filePath.isNullOrEmpty()) {
+ runtimeConfigurationWarning("File was not specified")
+ }
+ val virtualFile = LocalFileSystem.getInstance().findFileByIoFile(File(filePath))
+ if (virtualFile == null || virtualFile.isDirectory) {
+ runtimeConfigurationWarning("Could not find script file: $filePath")
+ }
+ }
+
+ private fun runtimeConfigurationWarning(message: String): Nothing {
+ throw RuntimeConfigurationWarning(message)
+ }
+
+ // NOTE: this is needed for coverage
+ override fun getRunClass() = null
+
+ override fun getPackage() = null
+
+ override fun getRefactoringElementListener(element: PsiElement): RefactoringElementListener? {
+ val file = element as? KtFile ?: return null
+ val pathFromElement = pathFromPsiElement(file) ?: return null
+
+ if (filePath != pathFromElement) {
+ return null
+ }
+
+ return object : RefactoringElementAdapter() {
+ override fun undoElementMovedOrRenamed(newElement: PsiElement, oldQualifiedName: String) {
+ filePath = pathFromPsiElement(newElement)
+ }
+
+ override fun elementRenamedOrMoved(newElement: PsiElement) {
+ filePath = pathFromPsiElement(newElement)
+ }
+ }
+ }
+
+}
+
+private class ScriptCommandLineState(environment: ExecutionEnvironment, configuration: KotlinStandaloneScriptRunConfiguration) :
+ BaseJavaApplicationCommandLineState(environment, configuration) {
+
+ override fun createJavaParameters(): JavaParameters? {
+ val params = commonParameters()
+
+ val kotlinPaths = PathUtil.getKotlinPathsForIdeaPlugin()
+ listOf(kotlinPaths.compilerPath, kotlinPaths.reflectPath, kotlinPaths.runtimePath)
+ .map { it.absolutePath }
+ .forEach { dependencyJar -> params.classPath.add(dependencyJar) }
+
+ params.mainClass = "org.jetbrains.kotlin.cli.jvm.K2JVMCompiler"
+ params.programParametersList.prepend(configuration.filePath ?: throw CantRunException("Script file was not specified"))
+ params.programParametersList.prepend("-script")
+
+ return params
+ }
+
+ private fun commonParameters(): JavaParameters {
+ val params = JavaParameters()
+ setupJavaParameters(params)
+ val jreHome = if (configuration.isAlternativeJrePathEnabled) myConfiguration.alternativeJrePath else null
+ JavaParametersUtil.configureProject(environment.project, params, JavaParameters.JDK_ONLY, jreHome)
+ return params
+ }
+}
diff --git a/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationEditor.form b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationEditor.form
new file mode 100644
index 00000000000..a2a3853fa0e
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationEditor.form
@@ -0,0 +1,39 @@
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationEditor.java b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationEditor.java
new file mode 100644
index 00000000000..5c358c2be6f
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationEditor.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.run.script.standalone;
+
+import com.intellij.execution.ui.AlternativeJREPanel;
+import com.intellij.execution.ui.CommonJavaParametersPanel;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.ui.LabeledComponent;
+import com.intellij.openapi.ui.TextComponentAccessor;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.PanelWithAnchor;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.kotlin.parsing.KotlinParserDefinition;
+
+import javax.swing.*;
+
+public class KotlinStandaloneScriptRunConfigurationEditor extends SettingsEditor implements PanelWithAnchor {
+ private JPanel mainPanel;
+ private CommonJavaParametersPanel commonProgramParameters;
+ private AlternativeJREPanel alternativeJREPanel;
+ private TextFieldWithBrowseButton chooseScriptFileTextField;
+ private LabeledComponent chooseScriptFileComponent;
+ private JComponent anchor;
+
+ public KotlinStandaloneScriptRunConfigurationEditor(Project project) {
+ initChooseFileField(project);
+ anchor = UIUtil.mergeComponentsWithAnchor(chooseScriptFileComponent, commonProgramParameters, alternativeJREPanel);
+ }
+
+ void initChooseFileField(Project project) {
+ FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor()
+ .withFileFilter(new Condition() {
+ @Override
+ public boolean value(VirtualFile file) {
+ return file.isDirectory() || KotlinParserDefinition.STD_SCRIPT_SUFFIX.equals(file.getExtension());
+ }
+ })
+ .withTreeRootVisible(true);
+
+ chooseScriptFileTextField.addBrowseFolderListener("Choose script file", null, project, descriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT);
+ }
+
+ @Override
+ protected void resetEditorFrom(KotlinStandaloneScriptRunConfiguration configuration) {
+ commonProgramParameters.reset(configuration);
+ String path = configuration.filePath;
+ chooseScriptFileTextField.setText(path != null ? path : "");
+ alternativeJREPanel.init(configuration.getAlternativeJrePath(), configuration.isAlternativeJrePathEnabled());
+ }
+
+ @Override
+ protected void applyEditorTo(KotlinStandaloneScriptRunConfiguration configuration) throws ConfigurationException {
+ commonProgramParameters.applyTo(configuration);
+ configuration.setAlternativeJrePath(alternativeJREPanel.getPath());
+ configuration.setAlternativeJrePathEnabled(alternativeJREPanel.isPathEnabled());
+ configuration.filePath = chooseScriptFileTextField.getText();
+ }
+
+ @NotNull
+ @Override
+ protected JComponent createEditor() {
+ return mainPanel;
+ }
+
+ @Override
+ public JComponent getAnchor() {
+ return anchor;
+ }
+
+ @Override
+ public void setAnchor(JComponent anchor) {
+ this.anchor = anchor;
+ commonProgramParameters.setAnchor(anchor);
+ alternativeJREPanel.setAnchor(anchor);
+ chooseScriptFileComponent.setAnchor(anchor);
+ }
+
+ private void createUIComponents() {
+ chooseScriptFileComponent = new LabeledComponent();
+ chooseScriptFileTextField = new TextFieldWithBrowseButton();
+ chooseScriptFileComponent.setComponent(chooseScriptFileTextField);
+ }
+}
diff --git a/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationProducer.kt b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationProducer.kt
new file mode 100644
index 00000000000..f30c2a7b2d2
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationProducer.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.run.script.standalone
+
+import com.intellij.execution.actions.ConfigurationContext
+import com.intellij.execution.actions.RunConfigurationProducer
+import com.intellij.openapi.util.Ref
+import com.intellij.psi.PsiElement
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
+
+public class KotlinStandaloneScriptRunConfigurationProducer :
+ RunConfigurationProducer(KotlinStandaloneScriptRunConfigurationType.instance) {
+ override fun setupConfigurationFromContext(
+ configuration: KotlinStandaloneScriptRunConfiguration,
+ context: ConfigurationContext?,
+ sourceElement: Ref?
+ ): Boolean {
+ configuration.filePath = pathFromContext(context) ?: return false
+ configuration.setGeneratedName()
+ return true
+ }
+
+ fun pathFromContext(context: ConfigurationContext?): String? {
+ val location = context?.location ?: return null
+ return pathFromPsiElement(location.psiElement)
+ }
+
+ override fun isConfigurationFromContext(configuration: KotlinStandaloneScriptRunConfiguration?, context: ConfigurationContext?): Boolean {
+ val filePath = configuration?.filePath
+ return filePath != null && filePath == pathFromContext(context)
+ }
+
+ companion object {
+ fun pathFromPsiElement(element: PsiElement): String? {
+ val file = element.getParentOfType(false) ?: return null
+ val script = file.script ?: return null
+ return script.getContainingKtFile().virtualFile.canonicalPath
+ }
+ }
+}
diff --git a/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationType.kt b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationType.kt
new file mode 100644
index 00000000000..194b9aff302
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/run/script/standalone/KotlinStandaloneScriptRunConfigurationType.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010-2015 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.run.script.standalone
+
+import com.intellij.execution.configurations.*
+import com.intellij.openapi.project.Project
+import org.jetbrains.kotlin.idea.KotlinIcons
+
+class KotlinStandaloneScriptRunConfigurationType : ConfigurationTypeBase(
+ "KotlinStandaloneScriptRunConfigurationType",
+ "Kotlin script",
+ "Run Kotlin script",
+ KotlinIcons.LAUNCH
+) {
+ init {
+ addFactory(Factory(this))
+ }
+
+ private class Factory(type: ConfigurationType) : ConfigurationFactory(type) {
+ override fun createTemplateConfiguration(project: Project): RunConfiguration {
+ return KotlinStandaloneScriptRunConfiguration(project, this, "")
+ }
+ }
+
+ companion object {
+ val instance: KotlinStandaloneScriptRunConfigurationType
+ get() = ConfigurationTypeUtil.findConfigurationType(KotlinStandaloneScriptRunConfigurationType::class.java)
+ }
+}