Page 1 of 1

Script to emulate a "shell" for a command-line program.

Posted: Tue 28 Oct 2008, 04:05
by disciple
EDIT - see my later post for the latest version.

I would find very useful a shell script or program to emulate a "shell" for a program by repeatedly taking input arguments and running the program with them.

e.g. I would run `shellemulator some-non-interactive-console-calculator-or-something`
and it would send each line of subsequent input to some-non-interactive-console-calculator-or-something, until I exit it somehow.
So for the calculator example above, I could just type an equation and press enter, instead of typing the full command to run the calculator each time.

Here's an example that doesn't demonstrate how useful it would really be :)
Instead of running:

Code: Select all

/lmp-0.2.99.10/src# ./lmp --vartable="pi=3.14159" 6+4*pi
18.56636

/lmp-0.2.99.10/src# ./lmp 6+4*3*sin45
16.210842

/lmp-0.2.99.10/src# ./lmp --vartable="pi=3.14159" 6+4*pi*3*sin45
38.07828
I would run:

Code: Select all

/lmp-0.2.99.10/src# shellemulator ./lmp --vartable="pi=3.14159"
6+4*pi
18.56636
6+4*3*sin45
16.210842
6+4*pi*3*sin45
38.07828
I'm guessing it would be fairly easy to write even a shell script to do this, but I can't figure out how :?
I could write an infinite loop to repeatedly run `rxvt -e something`, but I want to repeatedly use the same terminal so the user can see the argument and output history, and (hopefully) scroll through arguments with the arrow keys, just as they can scroll through the command history in rxvt.

BTW I did look for an existing program or script to do this, and I didn't find anything - but it's the sort of thing I don't have a good track record of finding :oops:

--------------
EDIT - wait a minute, I found this http://www.soyo123.com/shell-en/20080308/307.html
I'm just making it more generic...
It is just what I want, except it doesn't have a scrollable argument history :(

-------------
EDIT - here's a preliminary version

Code: Select all

#!/bin/sh

# shellemulator - emulates a "shell" for a program by repeatedly taking input arguments and running the program with them.
# e.g. allows sort-of "interactive" use of a non-interactive calculator.

# By disciple 28/10/08
# http://murga-linux.com/puppy/viewtopic.php?p=243877#243877
# Based on code from http://www.soyo123.com/shell-en/20080308/307.html
# Would be nice to be able to scroll through the argument history.
# Would be nice to add support for setting "environment variables".
# Would be nice to automatically store the output of the last command in an "answer" or "output" variable (e.g. for a calculator to use the results of the previous command).
# Could add ability to edit $command (or at least add extra arguments), but there is little point as it is just as easy to simply quit and edit the command we ran this script with.

helptext="shellemulator - emulates a 'shell' for a program by repeatedly taking input arguments and running the program with them. Enter 'help' for this text, 'quit' to quit."



command="$@"

echo "
$helptext
"

echo -n "$command> "

while read arguments
do
  case $arguments
  in
    quit|exit)    exit 0                         ;;
    help|\?)      echo "$helptext"               ;;
    *)            $command "$arguments"          ;;
  esac

  echo -n "
$command> "
done

echo ""

exit 0


Posted: Tue 28 Oct 2008, 04:43
by Pizzasgood

Code: Select all

while [ 1 ]; do read INPUT_STUFF; echo "${INPUT_STUFF} is 1337ness."; done
expanded:

Code: Select all

while [ 1 ]; do
read INPUT_STUFF
echo "${INPUT_STUFF} is 1337ness."
done

Posted: Tue 28 Oct 2008, 09:44
by disciple
Thanks. Nice new avatar BTW.

I was having the normal problems with unwittingly trying to use bash code in sh :), but here's a version with working argument history.
Now if I could only figure out how to implement "environment variables"...

Code: Select all

#!/bin/bash
# shellemulator - emulates a "shell" for a program by repeatedly taking input arguments and running the program with them.
# e.g. allows sort-of "interactive" use of a non-interactive calculator.

# By disciple 28/10/08
# http://murga-linux.com/puppy/viewtopic.php?p=243877#243877
# Would be nice to add support for setting "environment variables".
# Would be nice to automatically store the output of the last command in an "answer" or "output" variable (e.g. for a calculator to use the results of the previous command).
# Could add ability to edit $command (or at least add extra arguments), but there is little point as it is about as easy to simply quit and edit the command we ran this script with.

helptext="shellemulator - emulates a 'shell' for a program by repeatedly taking input arguments and running the program with them. Enter 'help' for this text, 'quit' to quit."

historyfile=$HOME/.shellemulator

command="$@"

echo "
$helptext"

while true
 do
 history -r "$historyfile"
 read -ep "
$command> " arguments
 echo "$arguments">>"$historyfile"
 history -c
  case $arguments
  in
   quit|exit)    exit 0                         ;;
   help|\?)      echo "$helptext"               ;;
   *)            $command "$arguments"          ;;
  esac
done

echo "

"
exit 0
Hmmm... I guess I should also add some sort of control on the number of lines in the history. I wonder if I can actually control it when I use the >>?

Posted: Tue 28 Oct 2008, 11:19
by disciple
I guess it doesn't make a whole lot of sense to use the same argument history regardless of what program we run with the script either...

Posted: Tue 28 Oct 2008, 16:15
by Pizzasgood
Cool. I didn't know about 'read -e' before.
Now if I could only figure out how to implement "environment variables"...
Maybe you can use eval to do that.

Code: Select all

SOMEVAR="Oscar"
#<snip>
read INPUT
PROCESSED="$(eval "echo $INPUT")"
When it takes in the input, you can give it something like this:

Code: Select all

$SOMEVAR is a grouch.
Then it should store this in $PROCESSED:

Code: Select all

Oscar is a grouch.

You should be able to set variables in a similar way, but you'll probably need some kind of way to signal that you're setting a variable, not providing input. Like a special "comment" character, that would be parsed out of the string before being passed to eval.

Posted: Sat 01 Nov 2008, 03:22
by disciple
Great!
Like a special "comment" character, that would be parsed out of the string before being passed to eval.
That's exactly what I was trying, but for some reason the way I was doing it the variable wasn't being recognised by the program when I subsequently tried to use it. Anyway, after following your eval example, it does work :)

The output of the previous command is now stored in the '$ANS' and '$ans' variables.
You can now execute a command outside of the fake 'shell' by prefixing it with '#' - e.g. to set a variable pi do '#pi=3.14'."

Code: Select all

#!/bin/bash
# shellemulator - emulates a "shell" for a program by repeatedly taking input arguments and running the program with them.
# e.g. allows sort-of "interactive" use of a non-interactive calculator.
# By disciple 01/11/08
# http://murga-linux.com/puppy/viewtopic.php?p=243877#243877

# Could add ability to edit $command on the fly (or at least add extra arguments), but there is little point as it is about as easy to simply quit and edit the command we ran this script with.

helptext="Usage: shellemulator command [command options]

Emulate a 'shell' for a program by repeatedly reading input arguments
and running the program with them. Enter 'help' or '?' for this text,
'quit' or 'exit' to quit.
The output of the previous command is stored in the '\$ANS' and '\$ans'
variables.
Prefix a command with '#' to execute it outside of the fake 'shell'
e.g. to set a variable pi do '#pi=3.14'."

historyfile=$HOME/.shellemulator

command="$@"

echo "
$helptext"

while true
do
 history -r "$historyfile"
 read -ep "
$command> " arguments
 echo "$arguments">>"$historyfile"
 history -c
 case $arguments
 in
  \#*)        eval `echo "$arguments" | cut -c 2-`            ;;
  quit|exit)  exit 0                                          ;;
  help|\?)    echo "$helptext"                                ;;
  *)          ANS="$(eval $command $arguments)" && echo $ANS  ;;
 esac
 ans=$ANS
done

echo "

"
exit 0
I guess the main thing missing now is probably the ability to set variables in the command you run the script with, which should be easy too... it would only be of real benefit if you were launching this from a variety of other scripts.
I'd better go study now :)

Posted: Sat 14 Jul 2012, 01:08
by disciple
There's also this:

Code: Select all

#!/bin/sh
cat | xargs -L1 "$@"
or this for readline support, but Puppy wouldn't include ledit:

Code: Select all

#!/bin/sh
ledit | xargs -L1 "$@"

Posted: Sat 14 Jul 2012, 17:39
by tallboy
I have not read the code supplied in detail, and I may misunderstand totally what this is about, so this may be a very stupid question, but why not simply run 'screen'?

http://www.rackaid.com/resources/linux- ... nd-how-to/

tallboy

Posted: Sun 15 Jul 2012, 02:25
by disciple
Yes, I think you totally misunderstand it :)
Unless screen has a feature I'm not aware of.

Posted: Mon 16 Jul 2012, 00:56
by disciple
disciple wrote:There's also this:

Code: Select all

#!/bin/sh
cat | xargs -L1 "$@"
I was just testing in msys on Windows, and interestingly this is incredibly slow compared to my shellemulator script.
They both seemed quick on my much slower linux machine at home... what is it with Windows?

Posted: Wed 26 Jun 2013, 01:47
by disciple
WARNING
disciple wrote:
disciple wrote:There's also this:

Code: Select all

#!/bin/sh
cat | xargs -L1 "$@"
I was just testing in msys on Windows, and interestingly this is incredibly slow compared to my shellemulator script.
They both seemed quick on my much slower linux machine at home... what is it with Windows?
My typical use case is pasting in a big list of files. At least in my current (Arch) install the shellemulator script can only accept a certain amount of input (typically about a hundred or so filenames) in one go, then it goes a little haywire and starts trying to work with parts of lines.
I believe this is a limitation of stdin, but it may be possible to improve the script so it doesn't cause a problem.
The xargs one-liner also looks confused, but it actually acts on everything correctly.