Skip to content

Commit

Permalink
Added support for registering keyboard actions to bld commands.
Browse files Browse the repository at this point in the history
Cleanups.
  • Loading branch information
gbevin committed Jul 29, 2024
1 parent 348af9a commit f3d85ab
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/main/java/rife/bld/idea/config/BldBuildCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
*/
package rife.bld.idea.config;

public record BldBuildCommand(String name, String displayName, String description) {
public record BldBuildCommand(String name, String description, String actionId) {
}
38 changes: 35 additions & 3 deletions src/main/java/rife/bld/idea/config/BldConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
*/
package rife.bld.idea.config;

import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ReadAction;
Expand Down Expand Up @@ -34,6 +36,7 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import rife.bld.idea.console.BldConsoleManager;
import rife.bld.idea.console.BldConsoleWindowFactory;
import rife.bld.idea.events.ExecuteAfterCompilationEvent;
import rife.bld.idea.events.ExecuteBeforeCompilationEvent;
Expand All @@ -43,6 +46,7 @@
import rife.bld.idea.execution.BldExecution;
import rife.bld.idea.execution.BldExecutionFlags;
import rife.bld.idea.project.BldProjectWindowFactory;
import rife.bld.idea.project.BldProjectActionExecuteCommand;
import rife.bld.idea.utils.BldBundle;
import rife.bld.idea.utils.BldConstants;

Expand All @@ -53,6 +57,8 @@
@State(name = "BldConfiguration", storages = @Storage("bld.xml"), useLoadedStateAsExisting = false)
public final class BldConfiguration implements PersistentStateComponent<Element>, Disposable {
private static final Logger LOG = Logger.getInstance(BldConfiguration.class);
@NonNls public static final String ACTION_ID_PREFIX = "Bld_";

@NonNls private static final String ELEMENT_EVENTS = "events";
@NonNls private static final String ELEMENT_EXECUTE_ON = "executeOn";
@NonNls private static final String ELEMENT_EVENT = "event";
Expand All @@ -67,9 +73,9 @@ public final class BldConfiguration implements PersistentStateComponent<Element>
private final BldDependencyTree dependencyTree_ = new BldDependencyTree();

private static final Comparator<BldBuildCommand> commandComparator = (command1, command2) -> {
final String name1 = command1.displayName();
final String name1 = command1.name();
if (name1 == null) return -1;
final String name2 = command2.displayName();
final String name2 = command2.name();
if (name2 == null) return 1;
return name1.compareToIgnoreCase(name2);
};
Expand All @@ -84,6 +90,10 @@ public static BldConfiguration instance(final @NotNull Project project) {
return project.getService(BldConfiguration.class);
}

public static String getActionIdPrefix(final @NotNull Project project) {
return ACTION_ID_PREFIX + project.getLocationHash();
}

@Override
public void dispose() {
// no-op
Expand Down Expand Up @@ -248,6 +258,27 @@ public void setCommands(List<BldBuildCommand> commands) {
commandsMap_.clear();
sorted.forEach(cmd -> commandsMap_.put(cmd.name(), cmd));

ReadAction.run(() -> {
synchronized (this) {
if (!project_.isDisposed()) {
// unregister bld actions
var actionManager = ActionManagerEx.getInstanceEx();
for (var oldId : actionManager.getActionIdList(getActionIdPrefix(project_))) {
actionManager.unregisterAction(oldId);
}

// register project actions
for (var command : sorted) {
final var action_id = command.actionId();
if (action_id != null) {
final var action = new BldProjectActionExecuteCommand(project_, command.name(), command.description());
actionManager.registerAction(action_id, action);
}
}
}
}
});

ApplicationManager.getApplication().invokeLater(
() -> eventDispatcher_.getMulticaster().configurationChanged(),
ModalityState.any()
Expand Down Expand Up @@ -320,7 +351,7 @@ private boolean runCommandSynchronously(CompileContext compileContext, final Dat

if (ExecuteAfterCompilationEvent.TYPE_ID.equals(event.getTypeId()) && compileContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
compileContext.addMessage(
CompilerMessageCategory.INFORMATION, BldBundle.message("bld.message.skip.command.after.compilation.errors", command.displayName()), null, -1, -1
CompilerMessageCategory.INFORMATION, BldBundle.message("bld.message.skip.command.after.compilation.errors", command.name()), null, -1, -1
);
return true;
}
Expand All @@ -347,6 +378,7 @@ private static boolean executeCommandSynchronously(final DataContext dataContext
else {
var task = new Task.Backgroundable(null, BldBundle.message("bld.build.progress.dialog.title"), true) {
public void run(@NotNull ProgressIndicator indicator) {
BldConsoleManager.showTaskMessage(BldBundle.message("bld.project.console.commands", command.name()), ConsoleViewContentType.USER_INPUT, project);
BldExecution.instance(project).executeCommands(new BldExecutionFlags(), command, state -> {
result.set((state == BldBuildListener.FINISHED_SUCCESSFULLY));
command_done.up();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
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.ui.SimpleTextAttributes;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import rife.bld.idea.config.BldBuildCommand;
Expand Down Expand Up @@ -52,23 +54,32 @@ public boolean update() {

final var color = UIUtil.getLabelForeground();
var nameAttributes = new TextAttributes(color, null, null, EffectType.BOXED, Font.PLAIN);
highlightedText_.getEnding().addText(command_.displayName(), nameAttributes);
highlightedText_.getEnding().addText(command_.name(), nameAttributes);

myName = highlightedText_.getText();

addShortcutText(getCommand().actionId());

var configuration = BldConfiguration.instance(myProject);
final var added_names = new ArrayList<String>(4);
for (final var event : configuration.getEventsForCommand(command_)) {
final String presentableName = event.getPresentableName();
if (!added_names.contains(presentableName)) {
added_names.add(presentableName);
highlightedText_.getEnding().addText(" (" + presentableName + ')', POSTFIX_ATTRIBUTES);
final String presentable_name = event.getPresentableName();
if (!added_names.contains(presentable_name)) {
added_names.add(presentable_name);
highlightedText_.getEnding().addText(" (" + presentable_name + ')', POSTFIX_ATTRIBUTES);
}
}

myName = highlightedText_.getText();

return !Comparing.equal(highlightedText_, oldText);
}

private void addShortcutText(String actionId) {
var shortcut = KeymapUtil.getPrimaryShortcut(actionId);
if (shortcut != null) {
highlightedText_.getEnding().addText(" (" + KeymapUtil.getShortcutText(shortcut) + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
}
}

public CellAppearanceEx getHighlightedText() {
return highlightedText_;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ private Tree initTree() {
TreeSpeedSearch.installOn(tree, false, path -> {
final var userObject = ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
if (userObject instanceof BldBuildCommand command) {
return command.displayName();
return command.name();
}
return null;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package rife.bld.idea.execution;

import com.intellij.execution.ui.ConsoleViewContentType;
import org.jetbrains.annotations.NonNls;
import org.json.JSONException;
import org.json.JSONObject;
import rife.bld.idea.config.BldBuildCommand;
Expand All @@ -19,25 +20,28 @@
public abstract class BldExecuteListCommands {
public static void run(BldExecution execution) {
var output = String.join("", execution.executeCommands(new BldExecutionFlags().commands(true), List.of("help", WRAPPER_JSON_ARGUMENT)));
var project = execution.project();
if (output.isEmpty()) {
BldConsoleManager.showTaskMessage("Failed to detect the bld commands.\n", ConsoleViewContentType.ERROR_OUTPUT, execution.project());
BldConsoleManager.showTaskMessage("Failed to detect the bld commands.\n", ConsoleViewContentType.ERROR_OUTPUT, project);
return;
}

BldConsoleManager.showTaskMessage("Detected the bld commands\n", ConsoleViewContentType.SYSTEM_OUTPUT, execution.project());
BldConsoleManager.showTaskMessage("Detected the bld commands\n", ConsoleViewContentType.SYSTEM_OUTPUT, project);

var commands = new ArrayList<BldBuildCommand>();

try {
var json = new JSONObject(output);
var json_commands = json.getJSONObject("commands");
for (var json_command_key : json_commands.keySet()) {
commands.add(new BldBuildCommand(json_command_key, json_command_key, json_commands.getString(json_command_key)));
commands.add(new BldBuildCommand(json_command_key,
json_commands.getString(json_command_key),
BldConfiguration.getActionIdPrefix(project) + '_' + json_command_key));
}
} catch (JSONException e) {
BldConsoleManager.showTaskMessage(output + "\n", ConsoleViewContentType.ERROR_OUTPUT, execution.project());
BldConsoleManager.showTaskMessage(output + "\n", ConsoleViewContentType.ERROR_OUTPUT, project);
}

BldConfiguration.instance(execution.project()).setCommands(commands);
BldConfiguration.instance(project).setCommands(commands);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public void checkConfiguration()
@Override
public String suggestedName() {
var command = getCommand();
return command == null ? null : command.displayName();
return command == null ? null : command.name();
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* 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;

import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionUpdateThread;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.keymap.impl.ui.EditKeymapsDialog;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import rife.bld.idea.utils.BldBundle;

final class BldProjectActionAssignShortcut extends AnAction {
private final Project project_;
private final String actionId_;

BldProjectActionAssignShortcut(Project project, String actionId) {
super(BldBundle.message("bld.project.assign.shortcut.action.name"));
project_ = project;
actionId_ = actionId;
}

@Override
public void actionPerformed(@NotNull AnActionEvent e) {
new EditKeymapsDialog(project_, actionId_).show();
}

@Override
public void update(@NotNull AnActionEvent e) {
e.getPresentation().setEnabled(actionId_ != null && ActionManager.getInstance().getAction(actionId_) != null);
}

@Override
public @NotNull ActionUpdateThread getActionUpdateThread() {
return ActionUpdateThread.BGT;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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;

import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsActions;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import rife.bld.idea.console.BldConsoleManager;
import rife.bld.idea.execution.BldExecution;
import rife.bld.idea.execution.BldExecutionFlags;
import rife.bld.idea.utils.BldBundle;

import java.util.List;

public final class BldProjectActionExecuteCommand extends DumbAwareAction {
private final Project project_;
private final String command_;
private final String debugString_;

public BldProjectActionExecuteCommand(final @NotNull Project project,
final String command,
final @NlsActions.ActionDescription String description) {
project_ = project;

var template_presentation = getTemplatePresentation();
template_presentation.setText("Bld Command: " + command, false);
template_presentation.setDescription(description);
command_ = command;
debugString_ = "Command action: " + command +
"; Project: " + project.getPresentableUrl();
}

public @NonNls String toString() {
return debugString_;
}

@Override
public void actionPerformed(@NotNull AnActionEvent e) {
Project project = e.getProject();
if (project == null) return;

new Task.Backgroundable(project_, BldBundle.message("bld.project.progress.commands", command_), true) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
BldConsoleManager.showTaskMessage(BldBundle.message("bld.project.console.commands", command_), ConsoleViewContentType.USER_INPUT, project_);
BldExecution.instance(project_).executeCommands(new BldExecutionFlags(), List.of(command_));
}
}.queue();
}
}
Loading

0 comments on commit f3d85ab

Please sign in to comment.