Tải bản đầy đủ (.pdf) (4 trang)

Instant Keyboard Response

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (47.65 KB, 4 trang )

121
■ ■ ■
CHAPTER 19
Instant Keyboard Response
T
here are times you may want to enter some input or perform an action without having
to use the Enter key. A while back, I encountered this problem when I needed to view the
numerical output of ballistic equations. I wanted to be able to increment or decrement an
input value and recalculate the results by pressing just one key. I came up with a script
that would do this, and display both the changed input value and the new results calcu-
lated from it. The example script here, while interesting, is just a simple demonstration of
how to process instant response.
My script accomplished its task quite well. The following script is a simplified version
that calculates and displays the values for a projectile’s trajectory. The user can set the
launch angle and the firing velocity in the manner described. The script will then display
the projectile’s distance, maximum height, and duration of flight.
First we initialize some variables and, because we will alter the terminal settings, we
save the current settings so that we can restore them later.
#!/bin/sh
old_stty_settings=$(stty -g) # Save original settings.
stty -icanon
theta=0
velocity=0
distance=
height=
time=
To do the keystroke processing, we have to first set up the terminal using stty. We then
obtain keystrokes using the head (or dd) command, as described later in this chapter.
Here, setting stty with the -icanon switch disables canonical mode for terminal manipu-
lation. This changes input data from being read as a whole line to a more fine-grained
byte-based input. The first two attributes of the –icanon switch (erase and kill) enable


the special characters that will erase the last character typed and erase the current line,
respectively. The last two attributes (werase and rprnt) aren’t very common. The werase
attribute enables the special character that will erase the last word typed, whereas rprnt
enables the special character that redraws the current line on the screen. For more infor-
mation, review the stty man page.
122
CHAPTER 19

INSTANT KEYBOARD RESPONSE
The script consists of a loop that repeatedly computes trajectory values based on
the current inputs and then updates the input values based on the user’s keystrokes.
The following code section is where the calculations are performed for the values we
seek. Every iteration of the loop recalculates the projectile’s distance, height, and
duration.
1
while :
do
# convert the angle from degrees to radians
angle=`echo "scale=5;$theta/57.29578" | bc -l`
# gravity is 9.8m/s^2
distance=`echo "scale=5;(($velocity^2)*2*(s($angle))*(c($angle)))/9.8" | bc -l`
height=`echo "scale=5;(($velocity*s($angle))^2/(2*9.8))" | bc -l`
time=`echo "scale=5;(2*($velocity*s($angle))/(9.8))" | bc -l`
The value of the angle variable is the radian equivalent of the theta value, which is
expressed in degrees. The bc utility performs trigonometric functions in radians, so this
conversion must be performed before angles can be used. The -l switch used with bc
is required to load the standard math library that allows bc to evaluate trigonometric
functions, such as the cosine of the angle. The scale value that is passed to bc sets the
number of decimal places that follow the decimal point. More information on shell
math functions can be found in Chapter 11.

Next the script outputs usage instructions that inform the user how to vary the launch
angle and velocity and how to quit the program, plus displays the values just calculated
from the current values of launch angle and velocity.
clear
echo "j to decrease launch angle --- k to increase launch angle"
echo "h to decrease launch velocity --- l to increase launch velocity"
echo
echo "x or q to exit."
echo
echo "Launch angle deg.=$theta Velocity M/s=$velocity"
echo
echo "Distance: $distance meters"
echo "Maximum height: $height meters"
echo "Flight Time: $time seconds"
The next command is the central one for handling the input of the script.
2
Here each
character the user enters is assigned to the Keypress variable.
Keypress=$(head -c1)
# Keypress=$(dd bs=1 count=1 2> /dev/null)
1. Trajectory calculations can be found at />2. Thanks to Stephane Chazelas, who supplied the keypress-detection code found on />LDP/abs/html/system.html.
CHAPTER 19

INSTANT KEYBOARD RESPONSE
123
Note that two commands could be used. The head command on many UNIX systems
normally displays only the first few lines of a file. The GNU version of the head command,
however, has a -c option, as shown here. The -c switch specifies how many bytes or char-
acters of data to display. The line of code that has been commented out uses the dd
command to do the same thing; this command, with the bs (block size) set to 1 byte and a

count of 1, is functionally the same as the head -c1 command. You will need only one of
these lines. I’ve shown both here because not all UNIX systems have the GNU version of
head that has the -c switch, and I wanted to include an alternative command that can be
used on both GNU and non-GNU systems.
Once the Keypress variable has been assigned, you have to decide how to process it.
case $Keypress in
j|J)
if [ $theta -ne 0 ]
then
theta=$(($theta-1))
else
theta=90
fi
;;
k|K)
if [ $theta -ne 90 ]
then
theta=$(($theta+1))
else
theta=0
fi
;;
For each of the valid value-updating keystrokes, the new values are validated. In the
case of the launch angle, the valid values lie between 0 and 90 degrees. If the angle is going
to become greater than 90 or less than 0, we roll the variable to the opposite end of the
valid range. If the current angle theta were 90 degrees and you wanted to add another
degree, the value of theta would be reset to zero. The converse happens when decrement-
ing an angle of 0 degrees.
The launch velocity should, of course, have only a positive value. If the value for some
reason goes below 0, we reset it to 0. There is no upper bound on this value, so you can

increase the initial velocity as much as you like.
h|H)
if [ $velocity -ne 0 ]
then
velocity=$(($velocity-1))
else
velocity=0
fi
124
CHAPTER 19

INSTANT KEYBOARD RESPONSE
;;
l|L)
velocity=$(($velocity+1))
;;
Note that the keys used to increment and decrement the input values were chosen to
match the keys used for cursor movement within vi, where J is down, K is up, H is left, and
L is right.
If one of the keys to quit is pressed, we break out of the loop. Otherwise the next itera-
tion of the loop displays the recalculated trajectory values and waits for more input.
q|Q|x|X)
break
;;
esac
done
Finally, the script resets the terminal settings to the original values and exits cleanly.
stty "$old_stty_settings"
exit 0

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×