Send result to stdout

How do I send output from a KM macro to stdout? (I'm on a Mac).

I'm asking because I'm using some KM macros to add functionality to scripts in another scripting language (JSL from SAS). The JSL scripting language has a function to call scripts in other languages. This JSL function is designed to look for the results produced by the foreign scripts on stdout.

Right now, I'm getting by by having KM push its results to the system clipboard; then reading off the clipboard in JSL. But it would be cleaner to get the results from stdout.

I apologize if this has already been asked -- I found a number of discussions about stdin, but if it's there, I missed discussions of stdout.

This is an interesting question. The only way that I've found that works sort of is to have a shell command with either "paste result" or "type result".

But are two problems.

  1. The output appears twice

  2. The output does not appear to actually be on stdout

To test #2 I tried to save the output to a variable like so:

FOO=$(osascript -e 'tell application "Keyboard Maestro Engine" to do script "11015FD9-D868-4B4B-B1D8-37D66537E3D8"' )

and the output still appeared in Terminal twice, but when I tried to do echo "$FOO" it did not have any content.

I was thinking maybe one could use the KM action "Write text to File" and specify the file as /dev/stdout. However, that doesn't seem to work. The following is in the log:

Write File failed to write file to /dev/stdout with error Error Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “stdout” in the folder “dev”." UserInfo={NSURL=file:///dev/stdout, NSUnderlyingError=0x600002e52ee0 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}} In macro “Untitled Macro 2” (while executing Write Text to File).

That's a good idea. I tried having it do date >>/dev/stdout but that didn't work either.

I think at this point I would recommend writing to a file such as /tmp/km-output.txt and then have your meta-process run the equivalent of cat /tmp/km-output.txt which I would prefer over using the pasteboard.

tj, thanks. I agree writing to a temporary file is a clean solution, and definitely better than messing with the system clipboard (even if a bit slower, but it's not like I'm invoking my KM macro inside a loop or anything).

Since my meta-environment's native function for invoking a shell script expects the results on stdout, it's unfortunate I can't use that method -- but it's not a major tragedy. If Peter chimes in, I'd be interested in knowing his thoughts. Meantime, thanks for thinking this through with me!

I figured out a different (?better) way to get back the result by browsing https://wiki.keyboardmaestro.com/action/Execute_a_Shell_Script

I invoke the KM macro from my metaemnvironment as before. I let the KM macro run, then at the end I have KM put the result string I am looking for into a KM variable named e.g. "my_result". The KM macro exits.

Now I have my metaenvironment do a second shell script invocation as follows:

/usr/bin/osascript -e tell application "Keyboard Maestro Engine" to get value of variable "my_result"

In this case, my metaenvironment actually does get back what it needs, as if it had been pushed onto stdout.

For what it's worth, here's the JSL/SAS program that defines a JSL function to invoke a KM script and then return the result:

New Custom Function(
	"ex",
	"Run KMScript alt",
	Function( {scriptID, paramlist = {}},
		{paramstring, macroResult = ""},
		paramstring = Concat Items( paramlist );
		Run Program(
			Executable( "/usr/bin/osascript" ),
			Options(
				"-e tell application \!"Keyboard Maestro Engine\!" to do script \!"" || scriptID || "\!" with parameter \!"" || paramstring ||
				"\!""
			),
			Read Function( "text" )
		);
		macroResult = Run Program(
			Executable( "/usr/bin/osascript" ),
			Options(
				"-e tell application \!"Keyboard Maestro Engine\!" to get value of variable \!"jmp_result\!""
			),
			Read Function( "text" )
		);
		Return( macroResult );
	)
)