Package org.intellij.erlang.actions

Source Code of org.intellij.erlang.actions.ErlangEmacsFormatAction

/*
* Copyright 2012-2014 Sergey Ignatov
*
* 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.intellij.erlang.actions;

import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.OSProcessHandler;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.ExceptionUtil;
import org.intellij.erlang.emacs.EmacsSettings;
import org.intellij.erlang.psi.ErlangFile;
import org.intellij.erlang.sdk.ErlangSystemUtil;
import org.intellij.erlang.settings.ErlangExternalToolsConfigurable;
import org.intellij.erlang.utils.ErlangExternalToolsNotificationListener;
import org.jetbrains.annotations.NotNull;

import java.io.File;

public class ErlangEmacsFormatAction extends AnAction implements DumbAware {
  private static final String NOTIFICATION_TITLE = "Reformat code with Emacs";
  private static final Logger LOG = Logger.getInstance(ErlangEmacsFormatAction.class);

  @Override
  public void update(AnActionEvent e) {
    PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
    boolean isErlang = psiFile instanceof ErlangFile;
    e.getPresentation().setEnabled(isErlang);
  }

  @Override
  public void actionPerformed(AnActionEvent e) {
    final PsiFile psiFile = e.getData(CommonDataKeys.PSI_FILE);
    final Project project = getEventProject(e);
    if (project == null) return;
    if (!(psiFile instanceof ErlangFile)) return;
    VirtualFile virtualFile = psiFile.getVirtualFile();
    if (virtualFile == null) return;

    final String groupId = e.getPresentation().getText();
    try {
      GeneralCommandLine commandLine = new GeneralCommandLine();
      String emacsPath = EmacsSettings.getInstance(project).getEmacsPath();
      if (emacsPath.isEmpty()) {
        Notifications.Bus.notify(
          new Notification(groupId, NOTIFICATION_TITLE,
            "Emacs executable path is empty"+
            "<br/><a href='configure'>Configure</a>",
          NotificationType.WARNING, new ErlangExternalToolsNotificationListener(project)), project);
        return;
      }
      commandLine.setExePath(emacsPath);
      commandLine.addParameters("--batch", "--eval");

      String sdkPath = getSdkPath(project);

      if (StringUtil.isEmpty(sdkPath)) {
        Notifications.Bus.notify(
          new Notification(groupId, NOTIFICATION_TITLE, "Erlang project SDK is not configured",
            NotificationType.WARNING), project);
        return;
      }

      final File tmpFile = FileUtil.createTempFile("emacs", ".erl", true);
      VirtualFile virtualTmpFile = LocalFileSystem.getInstance().findFileByIoFile(tmpFile);
      if (virtualTmpFile == null) {
        Notifications.Bus.notify(
          new Notification(groupId, NOTIFICATION_TITLE, "Failed to create a temporary file",
            NotificationType.WARNING), project);
        return;
      }

      boolean exists = new File(sdkPath, "lib/erlang/lib").exists();

      String emacsCommand = "\n" +
        "(progn (find-file \"" + virtualFile.getCanonicalPath() + "\")\n" +
        "    (setq erlang-root-dir \"" + sdkPath + "\")\n" +
        "    (setq load-path (cons (car (file-expand-wildcards (concat erlang-root-dir \"/lib/" + (exists ? "erlang/lib/" : "") + "tools-*/emacs\")))\n" +
        "                          load-path))\n" +
        "    (require 'erlang-start)\n" +
        "    (erlang-mode)\n" +
        "    (erlang-indent-current-buffer)\n" +
        "    (delete-trailing-whitespace)\n" +
        "    (untabify (point-min) (point-max))\n" +
        "    (write-region (point-min) (point-max) \"" + virtualTmpFile.getCanonicalPath() + "\")\n" +
        "    (kill-emacs))";

      commandLine.addParameter(emacsCommand);

      ApplicationManager.getApplication().saveAll();

      final String commandLineString = commandLine.getCommandLineString();
      OSProcessHandler handler = new OSProcessHandler(commandLine.createProcess(), commandLineString);
      handler.addProcessListener(new ProcessAdapter() {
        @Override
        public void processTerminated(ProcessEvent event) {
          ApplicationManager.getApplication().invokeLater(new Runnable() {
            @Override
            public void run() {
              try {
                final String emacsText = FileUtilRt.loadFile(tmpFile, true);
                if (StringUtil.isEmptyOrSpaces(emacsText)) {
                  Notifications.Bus.notify(new Notification(groupId, NOTIFICATION_TITLE,
                    "Emacs returned an empty file",
                    NotificationType.WARNING), project);
                  LOG.warn("Emacs returned an empty file:\n" + commandLineString);
                  return;
                }
                final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
                if (document == null) return;
                CommandProcessor.getInstance().executeCommand(project, new Runnable() {
                  @Override
                  public void run() {
                    ApplicationManager.getApplication().runWriteAction(new Runnable() {
                      @Override
                      public void run() {
                        document.setText(emacsText);
                      }
                    });
                  }
                }, NOTIFICATION_TITLE, "", document);

                Notifications.Bus.notify(new Notification(groupId, NOTIFICATION_TITLE,
                  psiFile.getName() + " formatted with Emacs",
                  NotificationType.INFORMATION), project);

              } catch (Exception ex) {
                Notifications.Bus.notify(new Notification(groupId,
                  psiFile.getName() + " formatting with Emacs failed", ExceptionUtil.getUserStackTrace(ex, LOG),
                  NotificationType.ERROR), project);
                LOG.error(ex);
              }
            }
          });
        }
      });
      handler.startNotify();
    } catch (Exception ex) {
      Notifications.Bus.notify(new Notification(groupId,
        psiFile.getName() + " formatting with Emacs failed", ExceptionUtil.getUserStackTrace(ex, LOG),
        NotificationType.ERROR), project);
      LOG.error(ex);
    }
  }

  @NotNull
  private static String getSdkPath(@NotNull Project project) {
    if (ErlangSystemUtil.isSmallIde()) {
      return ErlangExternalToolsConfigurable.getErlangSdkPath(project);
    }
    else {
      Sdk projectSdk = ProjectRootManager.getInstance(project).getProjectSdk();
      return projectSdk != null ? StringUtil.notNullize(projectSdk.getHomePath()) : "";
    }
  }
}
TOP

Related Classes of org.intellij.erlang.actions.ErlangEmacsFormatAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.