6
\$\begingroup\$

I have taught myself some bash and already knew some AppleScript, so I have come up with this SSH chatting tool for OS X users. It allows you to chat from a terminal to another OS X computer.

One problem is that this code has to be located in an executable shell file on the computer of the person receiving the messages in order for it to work. For example if the sshChat.sh is located in ~, you have to go ssh username@adress, then cd ~ and then ./sshChat.sh and I would like it to work without the file being on the computer of the person receiving the messages.

VER="1.6 BETA"
echo "#############################"
echo " SSH CHAT TOOL BY PI.SASHA "
echo "#############################"
echo -ne "V. $VER\n\n"
printf '> '
read -n4 COMMND
while true;
do
case $COMMND in
msgs) #Standard message
echo -ne "\n***************\nMESSAGE:\n"
read MSG
osascript -e 'tell application "System Events" to display dialog "'"$MSG"'" buttons "OK" default button 1'
echo -ne "***************\n\n"
printf '> '
read -n4 COMMND
;;
msga) #Advanced message
echo -ne "\n***************\nMESSAGE:\n"
printf 'TITLE > '
read TITLE
printf 'BUTTON > '
read BUTTON
echo "TEXT:"
read MSG
osascript -e 'tell application "System Events" to display dialog "'"$MSG"'" buttons "'"$BUTTON"'" default button 1 with title "'"$TITLE"'"'
echo -ne "***************\n\n"
printf '> '
read -n4 COMMND
;;
chts) #Standart chat
echo -ne "\n***************\nMESSAGE:\n"
read MSG
RSPNS=$(osascript -e 'Tell application "System Events" to display dialog "'"$MSG"'" default answer "Message" buttons "Respond" default button 1' -e 'text returned of result')
if [ -z "$RSPNS" ]; then
echo "USER CANCELLED"
else
echo -ne "---------------\nREACTION:\n$RSPNS\n***************\n\n"
fi
printf '> '
read -n4 COMMND
;;
chta) #Advanced chat
echo -ne "\n***************\nMESSAGE:\n"
printf 'TITLE > '
read TITLE
printf 'BUTTON > '
read BUTTON
printf 'DEF.ANSW > '
read DEFANSW
echo "TEXT:"
read MSG
RSPNS=$(osascript -e 'tell application "System Events" to display dialog "'"$MSG"'" default answer "'"$DEFANSW"'" buttons "'"$BUTTON"'" default button 1 with title "'"$TITLE"'"' -e 'text returned of result')
if [ -z "$RSPNS" ]; then
echo "USER CANCELLED"
else
echo -ne "---------------\nREACTION:\n$RSPNS\n***************\n\n"
fi
printf '> '
read -n4 COMMND
;;
spks) #Speak standard
echo -ne "\n***************\nMESSAGE:\n"
printf 'VOL.(0-7) > '
read -n1 VOL
echo -ne "\nTEXT:\n"
read MSG
osascript -e 'say "'"$MSG"'"'
osascript -e 'set volume "'"$VOL"'"'
echo -ne "***************\n\n"
printf '> '
read -n4 COMMND
;;
quit) #Quit
echo
exit 0
;;
help) #Help
echo -ne "\nCOMMANDS\n"
echo "***************"
echo "> msgs : Standard Message"
echo -ne "Allows you to send a message to the user.\n\n"
echo "> msga : Advanced Message"
echo -ne "Allows you to send a message to the user with a few extra options.\n\n"
echo "> chts : Standard Chat"
echo -ne "Allows you to send a message to the user which they can respond to.\n\n"
echo "> chta : Advanced Chat"
echo -ne "Allows you to send a message to the user which the can respond to with a few extra options.\n\n"
echo "> spks : Standart Speak"
echo -ne "Allows you to send a message to the user which will be read to him, it allows you to controll the volume of the computer aswell.\n\n"
sleep 1
printf '> '
read -n4 COMMND
;;
*) #Error
echo -ne "\nINVALID COMMAND\nTYPE "help" FOR HELP"
sleep 1
echo ""
printf '> '
read -n4 COMMND
;;
esac
done

Any suggestions on how I can improve the code?

Snowbody
8,66225 silver badges50 bronze badges
asked Apr 29, 2015 at 16:52
\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

Avoid echo -ne

Although you intend to use this script specifically on Mac OS X, as a general rule of thumb, it's good to avoid the various flags of echo, because they are not portable.

In some of your use cases the flags are completely unnecessary, for example instead of this:

echo -ne "V. $VER\n\n"

You could write like this to get the same effect:

echo "V. $VER"
echo

In other cases, it's better to use printf, for example here:

echo -ne "\n***************\nMESSAGE:\n"

Just replace with printf, the end result will be the same.

Use indentation

It's customary to indent code blocks that belong to a specific logical unit, for example the body of a loop, if conditions, longer case statements, like this:

while true; do
 case $COMMAND in
 msgs)
 read MSG
 osascript -e 'tell application "System Events" to display dialog "'"$MSG"'" buttons "OK" default button 1'
 printf "***************\n\n"
 printf '> '
 read -n4 COMMAND
 ;;

It makes the code more readable when you see its structure.

Decompose to functions

The case statements are fairly long. The script will become easier to read if you extract those statements to functions.

Naming

I don't enjoy nitpicking on names, but COMMND looks like a typo and it's annoying. I don't think it's worth saving one character.

answered Apr 29, 2015 at 18:47
\$\endgroup\$
3
  • \$\begingroup\$ Thank you for the feedback, this will be very helpful in future projects. I hadn't even thought about using functions instead of placing it all inside of case statements. And also, about the name, I think you are correct, it's made sense in my head, but it is more logical to just use COMMAND rather than COMMND. About the identation, I've written this using the vim - function in terminal, should I just use spaces or tabs? Or is there a program which will do this automatically for me? Thank you again. \$\endgroup\$ Commented Apr 30, 2015 at 11:49
  • \$\begingroup\$ I use vim too ;-) You can setup vim to do the indentation for you automatically. For example when I press Enter after starting an if statement, it breaks the line and moves the cursor to the correct position. Google for it, or look around on vi.stackexchange.com. \$\endgroup\$ Commented Apr 30, 2015 at 13:23
  • 1
    \$\begingroup\$ As for using spaces or tabs, it's debatable and there is no standard for this. I borrow standards from Python, using spaces instead of tabs. This has the benefit that the scripts will look exactly the same wherever you display them. By contrast, the width of tab characters depends on the viewing tool. One thing is clear though: you should use either spaces everywhere or tabs everywhere, and never a mix of both. \$\endgroup\$ Commented Apr 30, 2015 at 13:26
3
\$\begingroup\$

First of all, why do you repeat read -n4 COMMND in every block? Just put it at the top of the loop.

Typically, chat applications are implemented either as "client-server" -- one machine is the "server" and listens for requests from clients then distributes them out, or as "peer-to-peer" -- each chatter sends messages to the other chatter(s), who are listening for it.

Your current architecture has you logging in to the server and executing commands (a bash script). The thing is, many of these commands could be executed on the current machine. The only things that need to be executed on the remote host are the commands to osascript / "System Events" (and the voice ones too).

And the neat thing is that ssh lets you do that.

The usual use of ssh is interactively: it gives you a shell on the remote host. But a batch file can also use ssh as a batch command: it connects to the remote host, runs a command, and returns the result.

So, with a little use of ssh, you could change this script so it runs on the local machine.

e.g. instead of

osascript -e 'tell application "System Events" to display dialog "'"$MSG"'" buttons "'"$BUTTON"'" default button 1 with title "'"$TITLE"'"'

you could write

ssh $USER@$HOST 'osascript -e "'"tell application "System Events" to display dialog ""'""$MSG""'"" buttons ""'""$BUTTON""'"" default button 1 with title ""'""$TITLE""'"""'"'

you'd just need to set those variables.

answered Apr 29, 2015 at 19:08
\$\endgroup\$
6
  • \$\begingroup\$ Thank you for the feedback, I hadn't thought about putting 'read -n4 COMMND' at the top of the loop, very sharp. And also thank you for explaining how to execute the code on a not-local machine. I will use this for the final product. Thanks again! \$\endgroup\$ Commented Apr 30, 2015 at 11:46
  • \$\begingroup\$ Also, I forgot to mention, if the command produces output, it gets sent back across the network to become the output of the ssh. \$\endgroup\$ Commented Apr 30, 2015 at 13:18
  • \$\begingroup\$ Thank you! Just another question, when I try to use your method ' ssh $USER@$HOST 'osascript -e "'"tell application "System Events" to display dialog ""'""$MSG""'"" buttons ""'""$BUTTON""'"" default button 1 with title ""'""$TITLE""'"""'"' ' then I get an error ' 24:30: syntax error: Expected end of line but found plural class name. (-2741) ' and I have no idea what goes wrong, but that probably is just due to my lack of experience with coding. \$\endgroup\$ Commented Apr 30, 2015 at 13:58
  • \$\begingroup\$ It's probably the quotes. I'm not familiar with the quoting convention being used here and I just guessed at it. The "plural class name" is probably the word "buttons"; that's not being parsed properly. \$\endgroup\$ Commented Apr 30, 2015 at 14:46
  • \$\begingroup\$ for some reason AppleScript simply doesn't seem to work in combination with SSH. Maybe this is on purpose, maybe I am still doing something wrong. \$\endgroup\$ Commented Apr 30, 2015 at 17:27

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.