com.ansorgit.plugins.bash.runner.repl.AbstractConsoleRunnerWithHistory.java Source code

Java tutorial

Introduction

Here is the source code for com.ansorgit.plugins.bash.runner.repl.AbstractConsoleRunnerWithHistory.java

Source

/*
 * Copyright 2010 Joachim Ansorg, mail@ansorg-it.com
 * File: AbstractConsoleRunnerWithHistory.java, Class: AbstractConsoleRunnerWithHistory
 * Last modified: 2010-05-29
 *
 * 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 com.ansorgit.plugins.bash.runner.repl;

import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.Executor;
import com.intellij.execution.ExecutorRegistry;
import com.intellij.execution.console.LanguageConsoleImpl;
import com.intellij.execution.console.LanguageConsoleViewImpl;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.*;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.execution.ui.actions.CloseAction;
import com.intellij.ide.CommonActionsManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.PairProcessor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;

/**
 * This file comes from the IntelliJ IDEA sources.
 * <p/>
 * Some parts have been patched by Joachim Ansorg, mail@joachim-ansorg.de .
 *
 * @author oleg
 *         This class provides basic functionality for running consoles.
 *         It launches extrnal process and handles line input with history
 */
abstract class AbstractConsoleRunnerWithHistory {
    protected final Project myProject;
    protected final String myConsoleTitle;

    protected OSProcessHandler myProcessHandler;
    protected final CommandLineArgumentsProvider myProvider;
    protected final String myWorkingDir;

    protected LanguageConsoleViewImpl myConsoleView;
    private final ConsoleHistoryModel myHistory = new ConsoleHistoryModel();
    private AnAction myRunAction;

    public AbstractConsoleRunnerWithHistory(@NotNull final Project project, @NotNull final String consoleTitle,
            @NotNull final CommandLineArgumentsProvider provider, @Nullable final String workingDir) {
        myProject = project;
        myConsoleTitle = consoleTitle;
        myProvider = provider;
        myWorkingDir = workingDir;
    }

    /**
     * Launch process, setup history, actions etc.
     *
     * @throws ExecutionException
     */
    public void initAndRun() throws ExecutionException {
        // Create Server process
        final Process process = createProcess();

        // Init console view
        myConsoleView = createConsoleView();

        myProcessHandler = createProcessHandler(process);

        ProcessTerminatedListener.attach(myProcessHandler);

        myProcessHandler.addProcessListener(new ProcessAdapter() {
            @Override
            public void processTerminated(ProcessEvent event) {
                myRunAction.getTemplatePresentation().setEnabled(false);
                myConsoleView.getConsole().setPrompt("");
                myConsoleView.getConsole().getConsoleEditor().setRendererMode(true);
                ApplicationManager.getApplication().invokeLater(new Runnable() {
                    public void run() {
                        myConsoleView.getConsole().getConsoleEditor().getComponent().updateUI();
                    }
                });
            }
        });

        // Attach to process
        myConsoleView.attachToProcess(myProcessHandler);

        // Runner creating
        final Executor defaultExecutor = ExecutorRegistry.getInstance()
                .getExecutorById(DefaultRunExecutor.EXECUTOR_ID);
        final DefaultActionGroup toolbarActions = new DefaultActionGroup();
        final ActionToolbar actionToolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN,
                toolbarActions, false);

        // Runner creating
        final JPanel panel = new JPanel(new BorderLayout());
        panel.add(actionToolbar.getComponent(), BorderLayout.WEST);
        panel.add(myConsoleView.getComponent(), BorderLayout.CENTER);

        final RunContentDescriptor myDescriptor = new RunContentDescriptor(myConsoleView, myProcessHandler, panel,
                myConsoleTitle);

        // tool bar actions
        final AnAction[] actions = fillToolBarActions(toolbarActions, defaultExecutor, myDescriptor);
        registerActionShortcuts(actions, getLanguageConsole().getConsoleEditor().getComponent());
        registerActionShortcuts(actions, panel);
        panel.updateUI();

        // Show in run toolwindow
        ExecutionManager.getInstance(myProject).getContentManager().showRunContent(defaultExecutor, myDescriptor);

        // Request focus
        final ToolWindow window = ToolWindowManager.getInstance(myProject).getToolWindow(defaultExecutor.getId());
        window.activate(new Runnable() {
            public void run() {
                IdeFocusManager.getInstance(myProject)
                        .requestFocus(getLanguageConsole().getCurrentEditor().getContentComponent(), true);
            }
        });

        // Run
        myProcessHandler.startNotify();
    }

    protected abstract LanguageConsoleViewImpl createConsoleView();

    @Nullable
    protected abstract Process createProcess() throws ExecutionException;

    protected abstract OSProcessHandler createProcessHandler(final Process process);

    private void registerActionShortcuts(final AnAction[] actions, final JComponent component) {
        for (AnAction action : actions) {
            if (action.getShortcutSet() != null) {
                action.registerCustomShortcutSet(action.getShortcutSet(), component);
            }
        }
    }

    protected AnAction[] fillToolBarActions(final DefaultActionGroup toolbarActions, final Executor defaultExecutor,
            final RunContentDescriptor myDescriptor) {
        //stop
        final AnAction stopAction = createStopAction();
        toolbarActions.add(stopAction);

        //close
        final AnAction closeAction = createCloseAction(defaultExecutor, myDescriptor);
        toolbarActions.add(closeAction);

        // run action
        myRunAction = new DumbAwareAction("Execute current input",
                "Executes the current input of the editor with the Bash executable",
                IconLoader.getIcon("/actions/execute.png")) {
            public void actionPerformed(final AnActionEvent e) {
                runExecuteActionInner();
            }

            public void update(final AnActionEvent e) {
                final EditorEx editor = getLanguageConsole().getConsoleEditor();
                final Lookup lookup = LookupManager.getActiveLookup(editor);
                e.getPresentation().setEnabled(
                        !myProcessHandler.isProcessTerminated() && (lookup == null || !lookup.isCompletion()));
            }
        };
        myRunAction.registerCustomShortcutSet(KeyEvent.VK_ENTER, KeyEvent.CTRL_DOWN_MASK, null);

        //EmptyAction.setupAction(myRunAction, "Console.Execute", null);
        toolbarActions.add(myRunAction);

        // Help
        toolbarActions.add(CommonActionsManager.getInstance().createHelpAction("interactive_console"));

        // history actions
        final PairProcessor<AnActionEvent, String> historyProcessor = new PairProcessor<AnActionEvent, String>() {
            public boolean process(final AnActionEvent e, final String s) {
                new WriteCommandAction(myProject, getLanguageConsole().getFile()) {
                    protected void run(final Result result) throws Throwable {
                        getLanguageConsole().getEditorDocument().setText(s == null ? "" : s);
                    }
                }.execute();
                return true;
            }
        };

        final AnAction historyNextAction = ConsoleHistoryModel.createHistoryAction(myHistory, true,
                historyProcessor);
        final AnAction historyPrevAction = ConsoleHistoryModel.createHistoryAction(myHistory, false,
                historyProcessor);
        historyNextAction.getTemplatePresentation().setVisible(false);
        historyPrevAction.getTemplatePresentation().setVisible(false);
        toolbarActions.add(historyNextAction);
        toolbarActions.add(historyPrevAction);

        return new AnAction[] { stopAction, closeAction, myRunAction, historyNextAction, historyPrevAction };
    }

    protected AnAction createCloseAction(final Executor defaultExecutor, final RunContentDescriptor myDescriptor) {
        return new CloseAction(defaultExecutor, myDescriptor, myProject);
    }

    protected AnAction createStopAction() {
        return ActionManager.getInstance().getAction(IdeActions.ACTION_STOP_PROGRAM);
    }

    public void sendInput(final String input) {
        final Charset charset = myProcessHandler.getCharset();
        final OutputStream outputStream = myProcessHandler.getProcessInput();
        try {
            byte[] bytes = input.getBytes(charset.name());
            outputStream.write(bytes);
            outputStream.flush();
        } catch (IOException e) {
            // ignore
        }
    }

    public LanguageConsoleImpl getLanguageConsole() {
        return myConsoleView.getConsole();
    }

    protected void runExecuteActionInner() {
        // Process input and add to history
        final Document document = getLanguageConsole().getCurrentEditor().getDocument();
        final String documentText = document.getText();
        final TextRange range = new TextRange(0, document.getTextLength());

        getLanguageConsole().getCurrentEditor().getSelectionModel().setSelection(range.getStartOffset(),
                range.getEndOffset());
        getLanguageConsole().addCurrentToHistory(range, false);
        getLanguageConsole().setInputText("");

        if (!StringUtil.isEmptyOrSpaces(documentText)) {
            myHistory.addToHistory(documentText);
        }

        // Send to interpreter / server
        //final String text2send = line.length() == 0 ? "\n\n" : line + "\n";
        final String text2send = documentText + "\n";
        sendInput(text2send);
    }

    protected static String getProviderCommandLine(final CommandLineArgumentsProvider provider) {
        final StringBuilder builder = new StringBuilder();
        for (String s : provider.getArguments()) {
            if (builder.length() > 0) {
                builder.append(' ');
            }
            builder.append(s);
        }
        return builder.toString();
    }

    public Project getProject() {
        return myProject;
    }
}