\input bkmacs \pagetag{\typing} \photo{}{\pspicture{4in}{io}{io}{}\vfill} \chapter{Input and Output} \chaptag{\io} In the tic-tac-toe project in Chapter \ttt, we didn't write a complete game program. We wrote a {\it function\/} that took a board position and {\tt x} or {\tt o} as arguments, returning the next move. We noted at the time that a complete game program would also need to carry on a {\it conversation\/} with the user. Instead of computing and returning one single value, a \bkidx{conversational}{program} must carry out a sequence of events in time, reading information from the \idx{keyboard} and displaying other information on the \idx{screen}. Before we complete the tic-tac-toe project, we'll start by exploring Scheme's mechanisms for \bkidx{interactive}{programming}. \backskipsubhd{Printing}{5} \justidx{printing} Up until now, we've never told Scheme to print anything. The programs we've written have computed values and returned them; we've relied on the \idx{read-eval-print loop} to print these values.\footnt{The only exception is that we've used {\tt trace}, which prints messages about the progress of a computation.} But let's say we want to write a program to print out all of the words to ``99 Bottles of Beer on the Wall.'' We could implement a function to produce a humongous {\it list\/} of the lines of the song, like this: {\prgex% (define (bottles n) (if (= n 0) '() (append (verse n) (bottles (- n 1))))) } {\medskipamount=4pt\prgexskipamount=9pt\prgexbaselineamount=10pt {\prgex% (define (verse n) (list (cons n '(bottles of beer on the wall)) (cons n '(bottles of beer)) '(if one of those bottles should happen to fall) (cons (- n 1) '(bottles of beer on the wall)) '())) > (bottles 3) ((3 BOTTLES OF BEER ON THE WALL) (3 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (2 BOTTLES OF BEER ON THE WALL) () (2 BOTTLES OF BEER ON THE WALL) (2 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (1 BOTTLES OF BEER ON THE WALL) () (1 BOTTLES OF BEER ON THE WALL) (1 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (0 BOTTLES OF BEER ON THE WALL) ()) } \noindent The problem is that we don't want a list. All we want is to print out the lines of the song; storing them in a data structure is unnecessary and inefficient. Also, some versions of Scheme would print the above list like this: {\prgex% ((3 BOTTLES OF BEER ON THE WALL) (3 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (2 BOTTLES OF BEER ON THE WALL) () (2 BOTTLES OF BEER ON THE WALL) (2 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (1 BOTTLES OF BEER ON THE WALL) () (1 BOTTLES OF BEER ON THE WALL) (1 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (0 BOTTLES OF BEER ON THE WALL) ()) } \noindent or even all on one line. We can't rely on Scheme's mechanism for printing lists if we want to be sure of a particular arrangement on the screen. Instead we'll write a program to {\it print\/} a verse, rather than return it in a list: \justtt{show} {\prgex% (define (\ufun{bottles} n) (if (= n 0) 'burp (begin (verse n) (bottles (- n 1))))) (define (\ufun{verse} n) (show (cons n '(bottles of beer on the wall))) (show (cons n '(bottles of beer))) (show '(if one of those bottles should happen to fall)) (show (cons (- n 1) '(bottles of beer on the wall))) (show '())) > (bottles 3) (3 BOTTLES OF BEER ON THE WALL) (3 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (2 BOTTLES OF BEER ON THE WALL) () (2 BOTTLES OF BEER ON THE WALL) (2 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (1 BOTTLES OF BEER ON THE WALL) () (1 BOTTLES OF BEER ON THE WALL) (1 BOTTLES OF BEER) (IF ONE OF THOSE BOTTLES SHOULD HAPPEN TO FALL) (0 BOTTLES OF BEER ON THE WALL) () BURP } } % skip kludges \noindent Notice that Scheme doesn't print an outer set of parentheses. Each line was printed separately; there isn't one big list containing all of them.\footnt{We know that it's still not as beautiful as can be, because of the capital letters and parentheses, but we'll get to that later.} Why was ``burp''\ printed at the end? Just because we're printing things explicitly doesn't mean that the read-eval-print loop stops functioning. We typed the expression {\tt (bottles~3)}. In the course of evaluating that expression, Scheme printed several lines for us. But the {\it value\/} of the expression was the word {\tt burp}, because that's what {\tt bottles} returned. \subhd{Side Effects and Sequencing} How does our program work? There are two new ideas here:\ {\it \bkidx{side}{effect}s\/} and {\it sequencing.} Until now, whenever we've invoked a procedure, our only goal has been to get a return value. The procedures we've used compute and return a value, and do nothing else. {\tt Show} is different. Although every Scheme procedure returns a value, the Scheme language standard doesn't specify what value the printing procedures should return.\footnt{Suppose {\tt show} returns {\tt \#f} in your version of Scheme. Then you might see {\prgex% > (show 7) 7 #F } \noindent But since the return value is unspecified, we try to write programs in such a way that we never use {\tt show}'s return value as the return value from our procedures. That's why we return values like {\tt burp}.} Instead, we are interested in their side effects. In other words, we invoke {\tt show} because we want it to {\it do\/} something, namely, print its argument on the screen. What exactly do we mean by ``side effect''? The kinds of procedures that we've used before this chapter can compute values, invoke helper procedures, provide arguments to the helper procedures, and return a value. There may be a lot of activity going on within the procedure, but the procedure affects the world outside of itself only by returning a value that some other procedure might use. {\tt Show} affects the world outside of itself by putting something on the screen. After {\tt show} has finished its work, someone who looks at the screen can tell that {\tt show} was used.\footnt{The term {\it side\/} effect is based on the idea that a procedure may have a useful return value as its main purpose and may also have an effect ``on the side.'' It's a misnomer to talk about the side effect of {\tt show}, since the effect is its main purpose. But nobody ever says ``side return value''!} {\medskipamount=4pt\prgexskipamount=9pt\prgexbaselineamount=10pt \def\psate{\prgexskipamount=8pt} Here's an example to illustrate the difference between values and effects: {\prgex% (define (\ufun{effect} x) (show x) 'done) (define (\ufun{value} x) x) > (effect '(oh! darling)) (OH! DARLING) DONE > (value '(oh! darling)) (OH! DARLING) > (bf (effect '(oh! darling))) (OH! DARLING) ONE\psate > (bf (value '(oh! darling))) (DARLING) > (define (\ufun{lots-of-effect} x) (effect x) (effect x) (effect x)) > (define (\ufun{lots-of-value} x) (value x) (value x) (value x)) > (lots-of-effect '(oh! darling)) (OH! DARLING) (OH! DARLING) (OH! DARLING) DONE > (lots-of-value '(oh! darling)) (OH! DARLING) } } % skip kludge This example also demonstrates the second new idea, \idx{sequencing}: Each of {\tt effect}, {\tt lots-of-effect}, and {\tt lots-of-value} contains more than one expression in its body. When you invoke such a procedure, Scheme evaluates all the expressions in the body, in order, and returns the value of the last one.\footnt{In Chapter \defining, we said that the body of a procedure was always one single expression. We lied. But as long as you don't use any procedures with side effects, it doesn't do you any good to evaluate more than one expression in a body.} This also works in the body of a {\tt let}, which is really the body of a procedure, and in each clause of a {\ttidx cond}.\footnt{For example: {\zfprgex% > (cond ((< 4 0) (show '(how interesting)) (show '(4 is less than zero?)) #f) ((> 4 0) (show '(more reasonable)) (show '(4 really is more than zero)) 'value) (else (show '(you mean 4=0?)) #f)) (MORE REASONABLE) (4 REALLY IS MORE THAN ZERO) VALUE}} When we invoked {\tt lots-of-value}, Scheme invoked {\tt value} three times; it discarded the values returned by the first two invocations, and returned the value from the third invocation. Similarly, when we invoked {\tt lots-of-effect}, Scheme invoked {\tt effect} three times and returned the value from the third invocation. But each invocation of {\tt effect} caused its argument to be printed by invoking {\tt show}. \subhd{The \ttpmb{Begin} Special Form} \pagetag{\beg} The {\tt lots-of-effect} procedure accomplished sequencing by having more than one expression in its body. This works fine if the sequence of events that you want to perform is the entire body of a procedure. But in {\tt bottles} we wanted to include a sequence as one of the alternatives in an {\tt if} construction. We couldn't just say {\prgex% (define (bottles n) ;; wrong (if (= n 0) '() (verse n) (bottles (- n 1)))) } \noindent because {\tt if} must have exactly three arguments. Otherwise, how would {\tt if} know whether we meant {\tt (verse~n)} to be the second expression in the true case, or the first expression in the false case? Instead, to turn the sequence of expressions into a single expression, we use the \bkidx{special}{form} \ttidx{begin}. It takes any number of arguments, evaluates them from left to right, and returns the value of the last one. {\prgex% (define bottles n) (if (= n 0) 'burp (begin (verse n) (bottles (- n 1))))) } \noindent (One way to think about sequences in procedure bodies is that every procedure body has an invisible {\tt begin} surrounding it.) \subhd{This Isn't Functional Programming} Sequencing and side effects are radical departures from the idea of \bkidx{functional}{programming}. In fact, we'd like to reserve the name {\it function\/} for something that computes and returns one value, with no side effects. ``Procedure'' is the general term for the thing that {\tt lambda} returns---an embodiment of an algorithm. If the algorithm is the kind that computes and returns a single value without side effects, then we say that the procedure implements a function.\footnt{Sometimes people sloppily say that the procedure {\it is\/} a function. In fact, you may hear people be {\it really\/} sloppy and call a non-functional procedure a function!} There is a certain kind of sequencing even in functional programming. If you say {\prgex% (* (+ 3 4) (- 92 15)) } \noindent it's clear that the addition has to happen before the multiplication, because the result of the addition provides one of the arguments to the multiplication. What's new in the sequential programming style is the {\it emphasis\/} on sequence, and the fact that the expressions in the sequence are {\it independent\/} instead of contributing values to each other. In this multiplication problem, for example, we don't care whether the addition happens before or after the subtraction. If the addition and subtraction were in a sequence, we'd be using them for independent purposes: {\prgex% (begin (show (+ 3 4)) (show (- 92 15))) } \noindent This is what we mean by being independent. Neither expression helps in computing the other. And the order matters because we can see the order in which the results are printed. \subhd{Not Moving to the Next Line} Each invocation of {\tt show} prints a separate line. What if we want a program that prints several things on the same line, like this: {\prgex% > (begin (show-addition 3 4) (show-addition 6 8) 'done) 3+4=7 6+8=14 DONE } \noindent We use \ttidx{display}, which doesn't move to the next line after printing its argument: {\prgex% (define (\ufun{show-addition} x y) (display x) (display '+) (display y) (display '=) (show (+ x y))) } \noindent (The last one is a {\tt show} because we {\it do\/} want to start a new line after it.) What if you just want to print a blank line? You use \ttidx{newline}: {\prgex% (define (verse n) (show (cons n '(bottles of beer on the wall))) (show (cons n '(bottles of beer))) (show '(if one of those bottles should happen to fall)) (show (cons (- n 1) '(bottles of beer on the wall))) (newline)) ; replaces (show '()) } In fact, {\tt show} isn't an official Scheme primitive; we wrote it in terms of {\tt display} and {\tt newline}. \subhd{Strings} Throughout the book we've occasionally used strings, that is, words enclosed in double-quote marks so that Scheme will permit the use of punctuation or other unusual characters. Strings also preserve the case of letters, so they can be used to beautify our song even more. Since {\it any\/} character can be in a \idx{string}, including spaces, the easiest thing to do in this case is to treat all the letters, spaces, and punctuation characters of each line of the song as one long word. (If we wanted to be able to compute functions of the individual words in each line, that wouldn't be such a good idea.) {\prgex% (define (\ufun{verse} n) (display n) (show " bottles of beer on the wall,") (display n) (show " bottles of beer.") (show "If one of those bottles should happen to fall,") (display (- n 1)) (show " bottles of beer on the wall.") (newline)) } {\medskipamount=4pt\prgexskipamount=8pt\prgexbaselineamount=10pt {\prgex% > (verse 6) 6 bottles of beer on the wall, 6 bottles of beer. If one of those bottles should happen to fall, 5 bottles of beer on the wall. #F ; or whatever is returned by (newline) } % \def\vb{\vispc\penalty 0{}} % \def\vb{\_} \def\vb{\ } \noindent It's strange to think of ``{\tt\vb bottles\vb of\vb beer\vb on\vb the\vb wall,}'' as a single word. But the rule is that anything inside double quotes counts as a single word. It doesn't have to be an English word. \backskipsubhd{A Higher-Order Procedure for Sequencing}{8} Sometimes we want to print each element of a list separately: {\prgex% (define (\ufun{show-list} lst) (if (null? lst) 'done (begin (show (car lst)) (show-list (cdr lst))))) > (show-list '((dig a pony) (doctor robert) (for you blue))) (DIG A PONY) (DOCTOR ROBERT) (FOR YOU BLUE) DONE } Like other patterns of computation involving lists, this one can be abstracted into a higher-order procedure. (We can't call it a ``higher-order function'' because this one is for computations with side effects.) The procedure {\tt \ttidx{for-each}} is part of standard Scheme: {\prgex% > (for-each show '((mean mr mustard) (no reply) (tell me why))) (MEAN MR MUSTARD) (NO REPLY) (TELL ME WHY) } \noindent The value returned by {\tt for-each} is unspecified. Why couldn't we just use {\tt map} for this purpose? There are two reasons. One is just an efficiency issue: {\tt Map} constructs a list containing the values returned by each of its sub-computations; in this example, it would be a list of three instances of the unspecified value returned by {\tt show}. But we aren't going to use that list for anything, so there's no point in constructing it. The second reason is more serious. In functional programming, the order of evaluation of subexpressions is unspecified. For example, when we evaluate the expression {\prgex% (- (+ 4 5) (* 6 7)) } \noindent we don't know whether the addition or the multiplication happens first. Similarly, the order in which {\tt map} computes the results for each element is unspecified. That's okay as long as the ultimately returned list of results is in the right order. But when we are using side effects, we {\it do\/} care about the order of evaluation. In this case, we want to make sure that the elements of the argument list are printed from left to right. {\tt For-each} guarantees this ordering. \backskipsubhd{Tic-Tac-Toe Revisited}{8} We're working up toward playing a game of tic-tac-toe against the computer. But as a first step, let's have the computer play against itself. What we already have is {\tt ttt}, a {\it strategy\/} function:\ one that takes a board position as argument (and also a letter {\tt x} or {\tt o}) and returns the chosen next move. In order to play a game of tic-tac-toe, we need two players; to make it more interesting, each should have its own strategy. So we'll write another one, quickly, that just moves in the first empty square it sees: {\prgex% (define (\ufun{stupid-ttt} position letter) (location '_ position)) (define (\ufun{location} letter word) (if (equal? letter (first word)) 1 (+ 1 (location letter (bf word))))) } Now we can write a program that takes two strategies as arguments and actually plays a game between them. {\prgex% (define (\ufun{play-ttt} x-strat o-strat) (play-ttt-helper x-strat o-strat '_________ 'x)) (define (\ufun{play-ttt-helper} x-strat o-strat position whose-turn) (cond ((already-won? position (opponent whose-turn)) (list (opponent whose-turn) 'wins!)) ((tie-game? position) '(tie game)) (else (let ((square (if (equal? whose-turn 'x) (x-strat position 'x) (o-strat position 'o)))) (play-ttt-helper x-strat o-strat (add-move square whose-turn position) (opponent whose-turn)))))) } } % skip kludge \noindent We use a helper procedure because we need to keep track of two pieces of information besides the strategy procedures:\ the current board position and whose turn it is ({\tt x} or {\tt o}). The helper procedure is invoked recursively for each move. First it checks whether the game is already over (won or tied).\footnt{You wrote the procedures {\tt already-won?}\ and {\tt tie-game?}\ in Exercises \tttwon\ and \ttttied: {\prgex% (define (\ufun{already-won?} position who) (member? (word who who who) (find-triples position))) (define (\ufun{tie-game?} position) (not (member? '_ position))) }} If not, the helper procedure invokes the current player's strategy procedure, which returns the square number for the next move. For the recursive call, the arguments are the same two strategies, the new position after the move, and the letter for the other player. We still need {\tt add-move}, the procedure that takes a square and an old position as arguments and returns the new position. {\prgex% (define (\ufun{add-move} square letter position) (if (= square 1) (word letter (bf position)) (word (first position) (add-move (- square 1) letter (bf position))))) > (play-ttt ttt stupid-ttt) (X WINS!) > (play-ttt stupid-ttt ttt) (O WINS!) } \subhd{Accepting User Input} The work we did in the last section was purely functional. We didn't print anything (except the ultimate return value, as always) and we didn't have to read information from a human player, because there wasn't one. You might expect that the structure of an {\it interactive\/} game program would be very different, with a top-level procedure full of sequential operations. But the fact is that we hardly have to change anything to turn this into an interactive game. All we need is a new ``strategy'' procedure that asks the user where to move, instead of computing a move based on built-in rules. {\prgex% (define (\ufun{ask-user} position letter) (print-position position) (display letter) (display "'s move: ") (read)) (define (print-position position) ;; first version (show position)) } \noindent (Ultimately we're going to want a beautiful two-dimensional display of the current position, but we don't want to get distracted by that just now. That's why we've written a trivial temporary version.) {\prgex% > (play-ttt ttt ask-user) ____X____ O'S MOVE: \pmb{1} O___XX___ O'S MOVE: \pmb{4} O__OXXX__ O'S MOVE: \pmb{3} OXOOXXX__ O'S MOVE: \pmb{8} (TIE GAME) } \noindent What the user typed is just the single digits shown in boldface at the ends of the lines. What's new here is that we invoke the procedure \ttidx{read}. It waits for you to type a Scheme expression, and returns that expression. Don't be confused: {\tt Read} does {\it not\/} evaluate what you type. It returns exactly the same expression that you type: {\prgex% (define (\ufun{echo}) (display "What? ") (let ((expr (read))) (if (equal? expr 'stop) 'okay (begin (show expr) (echo))))) } {\medskipamount=2pt\prgexskipamount=7.5pt\prgexbaselineamount=10pt {\prgex% > (echo) What? \pmb{hello} HELLO What? \pmb{(+ 2 3)} (+ 2 3) What? \pmb{(first (glass onion))} (FIRST (GLASS ONION)) What? \pmb{stop} OKAY } \backskipsubhd{Aesthetic Board Display}{9} Here's our beautiful position printer: {%\setbox2=\hbox{{\ninett +}}\catcode`+=\active\def+{\lower1pt\copy2} {\prgex% (define (\ufun{print-position} position) (print-row (subword position 1 3)) (show "-+-+-") (print-row (subword position 4 6)) (show "-+-+-") (print-row (subword position 7 9)) (newline)) (define (\ufun{print-row} row) (maybe-display (first row)) (display "|") (maybe-display (first (bf row))) (display "|") (maybe-display (last row)) (newline)) (define (\ufun{maybe-display} letter) (if (not (equal? letter '_)) (display letter) (display " "))) (define (\ufun{subword} wd start end) ((repeated bf (- start 1)) ((repeated bl (- (count wd) end)) wd)))\pgfoot \nobreak} \nobreak\vfootnt{Alternate version: \def\fpskip{\vskip 5pt\relax} {\prgex\fprgexbaselineamount=9.5pt% (define (subword wd start end) (cond ((> start 1) (subword (bf wd) (- start 1) (- end 1))) ((< end (count wd)) (subword (bl wd) start end)) (else wd))) } \noindent You can take your choice, depending on which you think is easier, recursion or higher-order functions. } } % skip kludge Here's how it works: {\prgex% > (print-position '_x_oo__xx) |X| -+-+- O|O| -+-+- |X|X } } %%%%%%%%% active + kludge %%%%%%%%%%%%% \subhd{Reading and Writing Normal Text} The {\tt read} procedure works fine as long as what you type looks like a Lisp program. That is, it reads one expression at a time. In the tic-tac-toe program the user types a single number, which is a Scheme expression, so {\tt read} works fine. But what if we want to read more than one word? {\prgex% (define (music-critic) ;; first version (show "What's your favorite Beatles song?") (let ((song (read))) (show (se "I like" song "too.")))) > (music-critic) What's your favorite Beatles song? \pmb{She Loves You} (I like SHE too.) } \noindent If the user had typed the song title in parentheses, then it would have been a single Scheme expression and {\tt read} would have accepted it. But we don't want the users of our program to have to be typing parentheses all the time. Scheme also lets you read one character at a time. This allows you to read any text, with no constraints on its format. The disadvantage is that you find yourself putting a lot of effort into minor details. We've provided a procedure {\tt \ttidx{read-line}} that reads one line of input and returns a sentence. The words in that sentence will contain any punctuation characters that appear on the line, including parentheses, which are not interpreted as sublist delimiters by {\tt read-line}. {\tt Read-line} also preserves the case of letters. {\prgex% (define (music-critic) ;; second version (read-line) ; See explanation on next page. (show "What's your favorite Beatles song?") (let ((song (read-line))) (show (se "I like" song "too.")))) > (music-critic) What's your favorite Beatles song? \pmb{She Loves You} (I like She Loves You too.) } \noindent Why do we call {\tt read-line} and ignore its result at the beginning of {\tt music-critic}? It has to do with the interaction between {\tt read-line} and {\tt read}. {\tt Read} treats what you type as a sequence of Scheme expressions; each invocation of {\tt read} reads one of them. {\tt Read} pays no attention to formatting details, such as several consecutive spaces or line breaks. If, for example, you type several expressions on the same line, it will take several invocations of {\tt read} to read them all. By contrast, {\tt read-line} treats what you type as a sequence of lines, reading one line per invocation, so it does pay attention to line breaks. Either of these ways to read input is sensible in itself, but if you mix the two, by invoking {\tt read} sometimes and {\tt read-line} sometimes in the same program, the results can be confusing. Suppose you type a line containing an expression and your program invokes {\tt read} to read it. Since there might have been another expression on the line, {\tt read} doesn't advance to the next line until you ask for the next expression. So if you now invoke {\tt read-line}, thinking that it will read another line from the keyboard, it will instead return an empty list, because what it sees is an empty line---what's left after {\tt read} uses up the expression you typed. You may be thinking, ``But {\tt music-critic} doesn't call {\tt read}!'' That's true, but Scheme itself used {\tt read} to read the expression that you used to invoke {\tt music-critic}. So the first invocation of {\tt read-line} is needed to skip over the spurious empty line. Our solution works only if {\tt music-critic} is invoked directly at a Scheme prompt. If {\tt music-critic} were a subprocedure of some larger program that has already called {\tt read-line} before calling {\tt music-critic}, the extra {\tt read-line} in {\tt music-critic} would really read and ignore a useful line of text. If you write a procedure using {\tt read-line} that will sometimes be called directly and sometimes be used as a subprocedure, you can't include an extra {\tt read-line} call in it. Instead, when you call your procedure directly from the Scheme prompt, you must say {\prgex% > (begin (read-line) (my-procedure)) } Another technical detail about {\tt read-line} is that since it preserves the capitalization of words, its result may include strings, which will be shown in quotation marks if you return the value rather than {\tt show}ing it: {\prgex% (define (music-critic-return) (read-line) (show "What's your favorite Beatles song?") (let ((song (read-line))) (se "I like" song "too."))) > (music-critic-return) What's your favorite Beatles song? \pmb{She Loves You} ("I like" "She" "Loves" "You" "too.") } We have also provided {\tt \ttidx{show-line},} which takes a sentence as argument. It prints the sentence without surrounding parentheses, followed by a newline
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><title>Python: module ranger.container.keybuffer</title>
</head><body bgcolor="#f0f0f8">
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
<tr bgcolor="#7799ee">
<td valign=bottom> <br>
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="ranger.html"><font color="#ffffff">ranger</font></a>.<a href="ranger.container.html"><font color="#ffffff">container</font></a>.keybuffer</strong></big></big></font></td
><td align=right valign=bottom
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/ranger/container/keybuffer.py">/home/hut/ranger/ranger/container/keybuffer.py</a></font></td></tr></table>
<p><tt># Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com><br>
#<br>
# This program is free software: you can redistribute it and/or modify<br>
# it under the terms of the GNU General Public License as published by<br>
# the Free Software Foundation, either version 3 of the License, or<br>
# (at your option) any later version.<br>
#<br>
# This program is distributed in the hope that it will be useful,<br>
# but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br>
# GNU General Public License for more details.<br>
#<br>
# You should have received a copy of the GNU General Public License<br>
# along with this program. If not, see <<a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>>.</tt></p>
<p>
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
<tr bgcolor="#aa55cc">
<td colspan=3 valign=bottom> <br>
<font color