Allow arbitrary actions for menu items

Description

original runwar issue #140

It would be cool to provide a command line to execute for a menu item. Either a box command option (I'd likely need to provide the full path to the binary to runwar) or any OS command that a user wanted to configure. This could be anything ranging from a git pull on the web root to a grunt build or a cmd box server log --follow (open a console) or calc.exe (why not, right? ).

I think the main question would be how to handle the output of that process, Do we

Ignore any output and simply tell the user when it completes
Find a method of showing the user the output which could be tricky given the underlying Java UI libs in use
Open the command in a terminal window native to that machine. Obviously, the command may not be a terminal command like if you wanted a button that opened calc.exe
Even if we just do a simple implementation of this at the moment, we could tie it up to a process builder and let people get funky with custom menu items to see what they build. I asked for feedback in CFML Slack and I got a lot of interesting ideas people wanted to be able to do such as starting a server with another CF engine and importing CFConfig files. Most of the ideas would require some arbitrary command execution.

Activity

Show:
Brad Wood
November 6, 2019, 7:10 PM

Note the proof of concept code Denny wrote for this is in the Tray.java class but commented out. Specifically, the RunShellCommandAction nested class and corresponding if statement in the addMenuItems() method.

Miguel Mathus
November 6, 2019, 7:49 PM

understood

Miguel Mathus
April 21, 2020, 12:23 AM

updating the work done in this ticket after observations:

  • Instead of reading all of the bytearray stream when the process is done, open the Swing window BEFORE running the process with an empty text area

  • Start a gobbler thread to pipe the out stream of the process into the text area as it appears. The thread exits when the process's out stream has been closed

  • Add a "cancel" button to the Swing window that calls process.destroy() AND stops the output gobber thread

  • A pass through method in the shell executor will be necessary to access the process destroy

  • For run async actions, no gobbler thread is needed since we don't care about the output
    Instead of reading all of the bytearray stream when the process is done, open the Swing window BEFORE running the process with an empty text area

  • Start a gobbler thread to pipe the out stream of the process into the text area as it appears. The thread exits when the process's out stream has been closed

  • Add a "cancel" button to the Swing window that calls process.destroy() AND stops the output gobber thread

  • A pass through method in the shell executor will be necessary to access the process destroy

  • For run async actions, no gobbler thread is needed since we don't care about the output

  • Stop command shouldn't close swing window

  • sync commands should still close toaster popup after a few seconds

  • See if you can get the PID of the command and if you can show it (java 9 has a method for this, Java 8 may have a workaround you can find. Would be great if you can detect if the user is on Java 9 or higher and use the built in method in those cases)

  • Disable the stop button after the process is dead

  • Output exit code if we can get it after process ends or is killed . Something like "Process completed with exit code: 0"

  • Test special characters in the runTerminal to make sure they're escaped inside the quotes

  • Remove "output" variable OR rename it so it at least makes sense. (It seems to disable the toaster popup)

  • test wether killing processes is actually working

  • Convert System.out.println calls to use proper logger

  • Stop logging console out of synchronous processes to the server console

  • Document all of the JSON options and what they do

This items are already done,

 

Miguel Mathus
April 21, 2020, 12:38 AM

Miguel Mathus
April 28, 2020, 4:13 AM

Future Docs for this feature

New actions available to create tray icon options

New action value available
run: Use this to execute a command from your tray menu if you are expecting to get some feedback from the result, a small window will pop to show the output for the executed command.

"label":"Open VScode",
"action":"runAsync",
"command":"code .",
"disabled":false,
"image":"/path/to/image.png"

runAsync:Use this to execute a command from your tray menu if you are NOT expecting to get any output, this will execute the command in silent mode.

"label":"Open VScode",
"action":"runAsync",
"command":"code .",
"disabled":false,
"image":"/path/to/image.png"

runTerminal: Use this to execute a command in a separated terminal window, the window will not close when the actions is done.

"label":"Say Hello",
"action":"runTerminal",
"command":"echo " hello "",
"disabled":false,
"image":"/path/to/image.png"

Also the new property workingDirectory has been added to the trayOption definition, this property allows to set the current working directory for all the executed commands i.e.

"label":"Start an awesome app",
"action":"run",
"command":"box server start",
"workingDirectory":"/path/to/my/app/folder"
"disabled":false,
"image":"/path/to/image.png"

 

Assignee

Miguel Mathus

Reporter

Miguel Mathus

Labels

None

Affects versions

None

Fix versions

Priority

Major

Components

Configure