From 14d6b069f0ddc49ea3e145e884f5129a0407b97c Mon Sep 17 00:00:00 2001 From: Geert Bevin Date: Tue, 16 Jul 2024 19:25:42 -0400 Subject: [PATCH] Added command execution --- .../rife/bld/idea/config/BldBuildCommand.java | 21 +-- .../bld/idea/config/BldConfiguration.java | 1 - .../explorer/BldExplorerTreeStructure.java | 4 +- .../BldCommandNodeDescriptor.java | 5 +- .../rife/bld/idea/execution/BldExecution.java | 32 +---- .../bld/idea/project/BldProjectWindow.java | 136 +++++++++++++++++- .../idea/project/actions/RefreshAction.java | 36 ----- .../bld/idea/project/actions/RunAction.java | 38 ----- .../resources/messages/BldBundle.properties | 8 +- 9 files changed, 151 insertions(+), 130 deletions(-) delete mode 100644 src/main/java/rife/bld/idea/project/actions/RefreshAction.java delete mode 100644 src/main/java/rife/bld/idea/project/actions/RunAction.java diff --git a/src/main/java/rife/bld/idea/config/BldBuildCommand.java b/src/main/java/rife/bld/idea/config/BldBuildCommand.java index 9e73018..bb99d6a 100644 --- a/src/main/java/rife/bld/idea/config/BldBuildCommand.java +++ b/src/main/java/rife/bld/idea/config/BldBuildCommand.java @@ -4,24 +4,5 @@ */ package rife.bld.idea.config; -import com.intellij.openapi.actionSystem.DataContext; -import com.intellij.openapi.util.NlsSafe; -import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public interface BldBuildCommand { - @Nullable - @NlsSafe - String getName(); - - @Nullable - @NlsSafe - String getDisplayName(); - - @Nullable - @Nls(capitalization = Nls.Capitalization.Sentence) String getNotEmptyDescription(); - - void run(DataContext dataContext, List additionalProperties, BldBuildListener buildListener); +public record BldBuildCommand(String name, String displayName, String description) { } diff --git a/src/main/java/rife/bld/idea/config/BldConfiguration.java b/src/main/java/rife/bld/idea/config/BldConfiguration.java index 97d29ef..4e264c9 100644 --- a/src/main/java/rife/bld/idea/config/BldConfiguration.java +++ b/src/main/java/rife/bld/idea/config/BldConfiguration.java @@ -55,7 +55,6 @@ public void setupComplete() { } public void setBuildCommandList(ArrayList commands) { - buildCommands_.clear(); buildCommands_.addAll(commands); ApplicationManager.getApplication().invokeLater( diff --git a/src/main/java/rife/bld/idea/config/explorer/BldExplorerTreeStructure.java b/src/main/java/rife/bld/idea/config/explorer/BldExplorerTreeStructure.java index b8937e5..a504ed9 100644 --- a/src/main/java/rife/bld/idea/config/explorer/BldExplorerTreeStructure.java +++ b/src/main/java/rife/bld/idea/config/explorer/BldExplorerTreeStructure.java @@ -31,9 +31,9 @@ public final class BldExplorerTreeStructure extends AbstractTreeStructure { private final Object dependenciesFolder_ = new Object(); private static final Comparator commandComparator = (command1, command2) -> { - final String name1 = command1.getDisplayName(); + final String name1 = command1.displayName(); if (name1 == null) return -1; - final String name2 = command2.getDisplayName(); + final String name2 = command2.displayName(); if (name2 == null) return 1; return name1.compareToIgnoreCase(name2); }; diff --git a/src/main/java/rife/bld/idea/config/explorer/nodeDescriptors/BldCommandNodeDescriptor.java b/src/main/java/rife/bld/idea/config/explorer/nodeDescriptors/BldCommandNodeDescriptor.java index 2477aa5..09be44c 100644 --- a/src/main/java/rife/bld/idea/config/explorer/nodeDescriptors/BldCommandNodeDescriptor.java +++ b/src/main/java/rife/bld/idea/config/explorer/nodeDescriptors/BldCommandNodeDescriptor.java @@ -12,7 +12,6 @@ import com.intellij.openapi.roots.ui.CellAppearanceEx; import com.intellij.openapi.roots.ui.util.CompositeAppearance; import com.intellij.openapi.util.Comparing; -import com.intellij.ui.JBColor; import com.intellij.ui.SimpleColoredComponent; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; @@ -48,7 +47,7 @@ public boolean update() { final var color = UIUtil.getLabelForeground(); var nameAttributes = new TextAttributes(color, null, null, EffectType.BOXED, Font.PLAIN); - highlightedText_.getEnding().addText(command_.getDisplayName(), nameAttributes); + highlightedText_.getEnding().addText(command_.displayName(), nameAttributes); myName = highlightedText_.getText(); @@ -63,7 +62,7 @@ public CellAppearanceEx getHighlightedText() { public void customize(@NotNull SimpleColoredComponent component) { getHighlightedText().customize(component); component.setIcon(getIcon()); - var toolTipText = getCommand().getNotEmptyDescription(); + var toolTipText = getCommand().description(); component.setToolTipText(toolTipText); } } \ No newline at end of file diff --git a/src/main/java/rife/bld/idea/execution/BldExecution.java b/src/main/java/rife/bld/idea/execution/BldExecution.java index 03d35cf..d77dc39 100644 --- a/src/main/java/rife/bld/idea/execution/BldExecution.java +++ b/src/main/java/rife/bld/idea/execution/BldExecution.java @@ -11,17 +11,13 @@ import com.intellij.execution.process.ProcessEvent; import com.intellij.execution.process.ProcessOutputType; import com.intellij.execution.ui.ConsoleViewContentType; -import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.components.Service; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import rife.bld.idea.config.BldBuildCommand; -import rife.bld.idea.config.BldBuildListener; import rife.bld.idea.config.BldConfiguration; import rife.bld.idea.console.BldConsoleManager; import rife.bld.idea.utils.BldConstants; @@ -29,6 +25,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -95,34 +92,17 @@ public void listTasks() { var json = new JSONObject(output); var json_commands = json.getJSONObject("commands"); for (var json_command_key : json_commands.keySet()) { - commands.add(new BldBuildCommand() { - @Override - public @Nullable String getName() { - return json_command_key; - } - - @Override - public @Nullable String getDisplayName() { - return json_command_key; - } - - @Nls(capitalization = Nls.Capitalization.Sentence) - @Override - public @Nullable String getNotEmptyDescription() { - return json_commands.getString(json_command_key); - } - - @Override - public void run(DataContext dataContext, List additionalProperties, BldBuildListener buildListener) { - - } - }); + commands.add(new BldBuildCommand(json_command_key, json_command_key, json_commands.getString(json_command_key))); } BldConfiguration.getInstance(project_).setBuildCommandList(commands); } public List executeCommands(boolean silent, String... commands) { + return executeCommands(silent, Arrays.asList(commands)); + } + + public List executeCommands(boolean silent, List commands) { if (projectDir_ == null || bldMainClass_ == null) { return Collections.emptyList(); } diff --git a/src/main/java/rife/bld/idea/project/BldProjectWindow.java b/src/main/java/rife/bld/idea/project/BldProjectWindow.java index c03317d..78466f8 100644 --- a/src/main/java/rife/bld/idea/project/BldProjectWindow.java +++ b/src/main/java/rife/bld/idea/project/BldProjectWindow.java @@ -5,11 +5,19 @@ package rife.bld.idea.project; import com.intellij.execution.RunManagerListener; +import com.intellij.execution.ui.ConsoleViewContentType; +import com.intellij.icons.AllIcons; +import com.intellij.ide.DataManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.Task; +import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.NlsSafe; +import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.SimpleTextAttributes; @@ -17,12 +25,15 @@ import com.intellij.ui.tree.AsyncTreeModel; import com.intellij.ui.tree.StructureTreeModel; import com.intellij.ui.treeStructure.Tree; +import com.intellij.util.EditSourceOnDoubleClickHandler; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; +import rife.bld.idea.config.BldBuildCommand; import rife.bld.idea.config.BldConfigurationListener; -import rife.bld.idea.project.actions.RefreshAction; -import rife.bld.idea.project.actions.RunAction; +import rife.bld.idea.config.explorer.nodeDescriptors.BldCommandNodeDescriptor; +import rife.bld.idea.console.BldConsoleManager; +import rife.bld.idea.execution.BldExecution; import rife.bld.idea.config.BldConfiguration; import rife.bld.idea.config.explorer.BldExplorerTreeStructure; import rife.bld.idea.config.explorer.nodeDescriptors.BldNodeDescriptor; @@ -31,6 +42,11 @@ import javax.swing.*; import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; public final class BldProjectWindow extends SimpleToolWindowPanel implements DataProvider, Disposable { private Project project_; @@ -78,6 +94,13 @@ public void configurationChanged() { TreeUtil.installActions(tree_); TreeUIHelper.getInstance().installTreeSpeedSearch(tree_); + new EditSourceOnDoubleClickHandler.TreeMouseListener(tree_, null) { + @Override + protected void processDoubleClick(@NotNull MouseEvent e, @NotNull DataContext dataContext, @NotNull TreePath treePath) { + runSelection(DataManager.getInstance().getDataContext(tree_), true); + } + }.installOn(tree_); + project.getMessageBus().connect(this).subscribe(RunManagerListener.TOPIC, new RunManagerListener() { @Override public void beforeRunTasksChanged () { @@ -137,4 +160,113 @@ public void customizeCellRenderer(@NotNull JTree tree, } } + private void runSelection(final DataContext dataContext, final boolean moveFocusToEditor) { + if (!canRunSelection()) { + return; + } + + final var commands = getCommandNamesFromPaths(tree_.getSelectionPaths()); + + var commands_info = String.join(" ", commands); + new Task.Backgroundable(project_, BldBundle.message("bld.project.progress.commands", commands_info), true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + BldConsoleManager.showTaskMessage(BldBundle.message("bld.project.console.commands", commands_info), ConsoleViewContentType.USER_INPUT, project_); + BldExecution.getInstance(project_).executeCommands(false, commands); + } + }.queue(); + + if (moveFocusToEditor) { + ToolWindowManager.getInstance(project_).activateEditorComponent(); + } + } + + private boolean canRunSelection() { + if (tree_ == null) { + return false; + } + final TreePath[] paths = tree_.getSelectionPaths(); + if (paths == null) { + return false; + } + for (final TreePath path : paths) { + final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + final Object userObject = node.getUserObject(); + return userObject instanceof BldCommandNodeDescriptor; + } + return true; + } + + private static List<@NlsSafe String> getCommandNamesFromPaths(TreePath[] paths) { + if (paths == null || paths.length == 0) { + return Collections.emptyList(); + } + final List targets = new ArrayList<>(); + for (final TreePath path : paths) { + final Object userObject = ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject(); + if (!(userObject instanceof BldCommandNodeDescriptor)) { + continue; + } + final BldBuildCommand target = ((BldCommandNodeDescriptor)userObject).getCommand(); + targets.add(target.name()); + } + return targets; + } + + private final class RefreshAction extends AnAction implements DumbAware { + public RefreshAction() { + super(BldBundle.messagePointer("refresh.bld.command.action.name"), + BldBundle.messagePointer("refresh.bld.command.action.description"), AllIcons.Actions.Refresh); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + new Task.Backgroundable(project_, BldBundle.message("bld.project.progress.refresh"), true) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + BldConsoleManager.showTaskMessage(BldBundle.message("bld.project.console.refresh"), ConsoleViewContentType.USER_INPUT, project_); + + BldExecution.getInstance(project_).listTasks(); + } + }.queue(); + } + + @Override + public void update(@NotNull AnActionEvent event) { + final var presentation = event.getPresentation(); + presentation.setText(BldBundle.messagePointer("refresh.bld.command.action.name")); + presentation.setEnabled(true); + } + + @Override + public @NotNull ActionUpdateThread getActionUpdateThread() { + return ActionUpdateThread.EDT; + } + } + + private final class RunAction extends AnAction implements DumbAware { + public RunAction() { + super(BldBundle.messagePointer("run.bld.command.action.name"), + BldBundle.messagePointer("run.bld.command.action.description"), AllIcons.Actions.Execute); + } + + @Override + public void actionPerformed(@NotNull AnActionEvent e) { + runSelection(e.getDataContext(), true); + } + + @Override + public void update(@NotNull AnActionEvent event) { + final var presentation = event.getPresentation(); + presentation.setText(BldBundle.messagePointer("run.bld.command.action.name")); + presentation.setEnabled(true); + presentation.setEnabled(canRunSelection()); + } + + @Override + public @NotNull ActionUpdateThread getActionUpdateThread() { + return ActionUpdateThread.EDT; + } + } + } diff --git a/src/main/java/rife/bld/idea/project/actions/RefreshAction.java b/src/main/java/rife/bld/idea/project/actions/RefreshAction.java deleted file mode 100644 index f87fd6d..0000000 --- a/src/main/java/rife/bld/idea/project/actions/RefreshAction.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2024 Geert Bevin (gbevin[remove] at uwyn dot com) - * Licensed under the Apache License, Version 2.0 (the "License") - */ -package rife.bld.idea.project.actions; - -import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.ActionUpdateThread; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.DumbAware; -import org.jetbrains.annotations.NotNull; -import rife.bld.idea.utils.BldBundle; - -public final class RefreshAction extends AnAction implements DumbAware { - public RefreshAction() { - super(BldBundle.messagePointer("refresh.bld.command.action.name"), - BldBundle.messagePointer("refresh.bld.command.action.description"), AllIcons.Actions.Refresh); - } - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { - } - - @Override - public void update(@NotNull AnActionEvent event) { - final var presentation = event.getPresentation(); - presentation.setText(BldBundle.messagePointer("refresh.bld.command.action.name")); - presentation.setEnabled(true); - } - - @Override - public @NotNull ActionUpdateThread getActionUpdateThread() { - return ActionUpdateThread.EDT; - } -} diff --git a/src/main/java/rife/bld/idea/project/actions/RunAction.java b/src/main/java/rife/bld/idea/project/actions/RunAction.java deleted file mode 100644 index 0c7f730..0000000 --- a/src/main/java/rife/bld/idea/project/actions/RunAction.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2024 Geert Bevin (gbevin[remove] at uwyn dot com) - * Licensed under the Apache License, Version 2.0 (the "License") - */ -package rife.bld.idea.project.actions; - -import com.intellij.icons.AllIcons; -import com.intellij.openapi.actionSystem.ActionUpdateThread; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.project.DumbAware; -import org.jetbrains.annotations.NotNull; -import rife.bld.idea.utils.BldBundle; - -public final class RunAction extends AnAction implements DumbAware { - public RunAction() { - super(BldBundle.messagePointer("run.bld.command.action.name"), - BldBundle.messagePointer("run.bld.command.action.description"), AllIcons.Actions.Execute); - } - - @Override - public void actionPerformed(@NotNull AnActionEvent e) { -// runSelection(e.getDataContext(), true); - } - - @Override - public void update(@NotNull AnActionEvent event) { - final var presentation = event.getPresentation(); - presentation.setText(BldBundle.messagePointer("run.bld.command.action.name")); - presentation.setEnabled(true); -// presentation.setEnabled(canRunSelection()); - } - - @Override - public @NotNull ActionUpdateThread getActionUpdateThread() { - return ActionUpdateThread.EDT; - } -} diff --git a/src/main/resources/messages/BldBundle.properties b/src/main/resources/messages/BldBundle.properties index bdae71d..ff1cab3 100644 --- a/src/main/resources/messages/BldBundle.properties +++ b/src/main/resources/messages/BldBundle.properties @@ -1,5 +1,5 @@ name=bld -bld.command.terminated=\nbld command was terminated\! +bld.command.terminated=\nbld command was terminated\!\n refresh.bld.command.action.name=Refresh refresh.bld.command.action.description=Refresh the bld commands run.bld.command.action.name=Run @@ -7,4 +7,8 @@ run.bld.command.action.description=Run the selected command(s) with bld progress.text.loading.bld.config=Loading bld configuration... bld.empty.text=No bld commands found. bld.project.commands=Commands -bld.project.dependencies=Dependencies \ No newline at end of file +bld.project.dependencies=Dependencies +bld.project.progress.commands=bld {0} +bld.project.console.commands=> bld {0}\n +bld.project.progress.refresh=Refreshing bld +bld.project.console.refresh=> refresh\n \ No newline at end of file