For some time, I have been wishing that I could have some kind of command-line oriented functionality to LiveCode, beyond writing scripts with LiveCode Server. What if I could pipe things directly to it, or run it as an interactive shell? Being able to very quickly make use of the text handling in LiveCode would be extremely handy for certain command line oriented types of tasks. Alas, this is not possible with LiveCode or LiveCode Server as it currently stands. However, after some thought, I concluded that it should be possible to put together a script to provide this functionality.
Click to Zoom
After some time, I had produced a script which operates as a simple shell type interface. But how does it work? It’s actually fairly simple. The script is a LiveCode Server script, designed to be invoked via command line. When it starts up, it reads in the options passed to it on the command line to determine how it should behave. The options passed to it are in the $x variables, starting at $0. $# tells us how many were passed.
#!/usr/local/bin/livecode-server
## substitute this with the path to your livecode server executable
## array for storing the options passed to this program
local sOpts
## load options
repeat with x = 0 to ($# – 1)
do “put $” & x && “into tReadOpt”
if char 1 of tReadOpt is “-” then
repeat with y = 2 to the number of chars in tReadOpt
put char y of tReadOpt into sOpts[(the number of lines in the keys of sOpts + 1)]
end repeat
else
put tReadOpt into sOpts[(the number of lines in the keys of sOpts + 1)]
end if
end repeat
There are currently two modes: interactive and execute. We can also pass the -p option to tell it to expect data to be piped to it, and read it into a variable called ‘input’. If we pass it the -e option it starts up in execute mode, and expects you to have specified a command for it to run. It then exits after running the command. Usage for this would be like “lcsh -e ‘put hello world’”. Otherwise, it starts up in interactive mode.
## read from pipe
if optEnabled(“p”) then
read from stdin until EOF
put it into input
end if
## get command from last command line option and execute it, then quit
if optEnabled(“e”) then
do sOpts[(the number of lines in the keys of sOpts)]
put return
quit
end if
## interactive mode
repeat
put “lcsh[” & the folder & “]# “
read from stdin for 1 line
put it into tCommand
if isCommand(tCommand) then
put shell(tCommand)
else
try
do tCommand
catch pError
put “Error:” & return
put pError
end try
end if
put return
end repeat
Execute mode simply takes the last command line option and uses do on it, then quits. Interactive mode reads 1 line from stdin at a time (i.e. it reads 1 typed line by the user at a time) and then determines what should be done with it. It uses the isCommand function to check the $PATH environment variable (which contains all of the directories which should be looked in for executable programs) to see if what was entered was a utility that is already installed, such as the standard Linux utilities. If it was, it uses shell() to execute the entered command. Otherwise, it uses the do command to execute it as normal LiveCode code, catching any generated errors so that they can be displayed without causing the program to exit:
## checks to see if the first word is a command in $PATH
function isCommand pCommand
set the itemDel to “:”
put the folder into tFolder
put false into tIsCommand
repeat for each item tDir in $PATH
set the folder to tDir
if word 1 of pCommand is among the lines of the files then put true into tIsCommand
end repeat
set the folder to tFolder
return tIsCommand
end isCommand
There is also the optEnabled function that was referenced above. This checks to see if the program was loaded with a specific option enabled:
function optEnabled pOpt
repeat for each key tKey in sOpts
if sOpts[tKey] is pOpt then return true
end repeat
return false
end optEnabled
This is quite clunky and has many, many problems – for example, there’s no ability to pipe the output of some LiveCode to another program in interactive mode, and you can’t open another program that requires interaction. However, I think that with a lot more work, this could become quite a robust and useful tool. It already provides some very handy functionality in it’s current state, namely that I can pipe to it for text parsing:
Click to Zoom
I will probably keep chipping away at this until I can use it as my primary command line interface. You can get the full code here: http://jasminedavid.on-rev.com/lcsh.txt
read more
Recent Comments