Skip to content

Instantly share code, notes, and snippets.

@micoli
Created January 31, 2024 22:55
Show Gist options
  • Select an option

  • Save micoli/8a2d775fa18067dd76402e57ff240e3b to your computer and use it in GitHub Desktop.

Select an option

Save micoli/8a2d775fa18067dd76402e57ff240e3b to your computer and use it in GitHub Desktop.
/**
* Need the existence of a .dx-companion.json file at the project root
*
* .dx-companion.json format:
* {
* "actions": [{
* "label": "action label",
* "command": "sleep 3;exit"
* }],
* "observedFiles": [{
* "label": "button label",
* "filePath": "src/JavaMagazineJavaFxOnRaspberryPi/src/main/java/module-info2.env",
* "variableName": "BB"
* }]
* }
*
*
* Documentation:
* https://jetbrains.design/intellij/resources/icons_list/
* https://dmitrykandalov.com/liveplugin
* https://www.javaadvent.com/2021/12/liveplugin.html
*/
// KEEP NEXT LINE
// depends-on-plugin org.jetbrains.plugins.terminal
import org.jetbrains.plugins.terminal.TerminalView
import java.util.regex.Pattern
import javax.swing.Icon;
import javax.swing.*
import groovy.json.JsonSlurper;
import com.intellij.util.Alarm
import com.intellij.openapi.actionSystem.*
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.*;
import liveplugin.PluginUtil;
import static liveplugin.PluginUtil.show;
import static liveplugin.PluginUtil.*
import static liveplugin.implementation.Misc.scheduleTask
import static liveplugin.PluginUtil.registerToolWindow
class Configuration {
ObservedFile[] observedFiles
ShellAction[] actions
}
class ObservedFile {
String label
String filePath
String variableName
String activeIcon = "actions/inlayRenameInComments.svg"
String inactiveIcon = "actions/inlayRenameInCommentsActive.svg"
String unknownIcon = "expui/fileTypes/unknown.svg"
}
class ShellAction {
String label = 'ShellAction'
String command
String cwd
String icon = "debugger/threadRunning.svg"
}
static Configuration getConfiguration(project) {
VirtualFile projectBaseDir = project.getBaseDir()
VirtualFile configFile = projectBaseDir.findChild('.dx-companion.json')
if (configFile === null) {
show("DXCompanion, no .dx-companion.json found")
return
}
JsonSlurper jsonSlurper = new JsonSlurper()
return jsonSlurper.parseText(new String(configFile.contentsToByteArray()))
}
static JPanel initPlugin(project, Configuration configuration) {
if (configuration === null) {
return;
}
JPanel panel = new JPanel()
List<FileObserverToggle> actions = new ArrayList<>();
for (def observedFile : configuration.observedFiles) {
panel.add(new FileObserverToggle(observedFile))
}
if (configuration.actions.length > 0) {
for (def action : configuration.actions) {
panel.add(new ActionButton(project, action))
}
}
scheduleTask(new Alarm(Alarm.ThreadToUse.SWING_THREAD), 2000) {
for (def component : panel.getComponents()) {
if (component instanceof FileObserverToggle) {
component.check()
}
}
}
panel.revalidate()
return panel
}
class FileObserverToggle extends JButton {
ObservedFile observedFile
Pattern activeRegularExpression;
Pattern disabledRegularExpression;
private enum Status {
Active, Inactive, Unknown;
}
FileObserverToggle(ObservedFile _observedFile) {
super(_observedFile.label);
observedFile = _observedFile
activeRegularExpression = Pattern.compile("^" + observedFile.variableName + "=");
disabledRegularExpression = Pattern.compile("^#" + observedFile.variableName + "=");
addActionListener({ toggle() } as AbstractAction)
}
public void check() {
switch (getStatus()) {
case Status.Active:
setText(observedFile.label)
setIcon(IconLoader.getIcon(observedFile.activeIcon));
break
case Status.Inactive:
setText("# " + observedFile.label)
setIcon(IconLoader.getIcon(observedFile.inactiveIcon));
break
case Status.Unknown:
setText(observedFile.label + " not present")
setIcon(IconLoader.getIcon(observedFile.unknownIcon));
break
}
updateUI()
}
void toggle() {
switch (getStatus()) {
case Status.Active:
replaceInFile(false)
break
case Status.Inactive:
replaceInFile(true)
break
}
check()
}
private Status getStatus() {
File file = new File(observedFile.filePath)
def line = 0;
def result = Status.Unknown;
file.withReader { reader ->
while ((line = reader.readLine()) != null) {
if ((line =~ activeRegularExpression).size() > 0) {
result = Status.Active;
}
if ((line =~ disabledRegularExpression).size() > 0) {
result = Status.Inactive;
}
}
}
return result;
}
private void replaceInFile(boolean toActive) {
def file = new File(observedFile.filePath)
def result = "";
def line = 0;
file.withReader { reader ->
while ((line = reader.readLine()) != null) {
if (toActive) {
result = result + line.replaceFirst(disabledRegularExpression, "" + observedFile.variableName + "=") + System.getProperty("line.separator")
} else {
result = result + line.replaceFirst(activeRegularExpression, "#" + observedFile.variableName + "=") + System.getProperty("line.separator")
}
}
}
file.text = result
liveplugin.PluginUtil.show(observedFile.variableName + " " + (toActive ? "activated" : "deactivated"))
}
}
class ActionButton extends JButton {
Project project
ShellAction shellAction
String cmd
String actionIcon
ActionButton(Project _project, ShellAction _shellAction) {
super(_shellAction.label, IconLoader.getIcon(_shellAction.icon))
project = _project
shellAction = _shellAction
addActionListener({ click() } as AbstractAction)
}
void click() {
String cwd = shellAction.cwd ? shellAction.cwd : project.getBaseDir().getPath()
TerminalView.getInstance(project)
.createLocalShellWidget(cwd, shellAction.label)
.executeCommand(shellAction.command)
}
}
Configuration configuration = getConfiguration(project)
if(!configuration){
return;
}
registerToolWindow("DXCompanion", pluginDisposable) {
initPlugin(project, configuration)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment