]> git.lizzy.rs Git - plan9front.git/blob - sys/doc/sam/sam.ms
nusb/serial: implement flushes
[plan9front.git] / sys / doc / sam / sam.ms
1 .HTML "The Text Editor sam
2 .Vx 17 11 November 87 1 32 "ROB PIKE" "THE TEXT EDITOR SAM"
3 .ds DY "31 May 1987
4 .ds DR "Revised 1 July 1987
5 .de CW          \" puts first arg in CW font, same as UL; maintains font
6 \%\&\\$3\f(CW\\$1\fP\&\\$2
7 ..
8 .de Cs
9 .br
10 .fi
11 .ft 2
12 .ps -2
13 .vs -2
14 ..
15 .de Ce
16 .br
17 .nf
18 .ft 1
19 .ps
20 .vs
21 .sp
22 ..
23 .de XP
24 .ie h .html - <center><img src="\\$1.gif" /></center>
25 .el .BP \\$1.ps \\$2
26 ..
27 .TL
28 The Text Editor \&\f(CWsam\fP
29 .AU
30 Rob Pike
31 rob@plan9.bell-labs.com
32 .AB
33 .LP
34 .CW Sam
35 is an interactive multi-file text editor intended for
36 bitmap displays.
37 A textual command language
38 supplements the mouse-driven, cut-and-paste interface
39 to make complex or
40 repetitive editing tasks easy to specify.
41 The language is characterized by the composition of regular expressions
42 to describe the structure of the text being modified.
43 The treatment of files as a database, with changes logged
44 as atomic transactions, guides the implementation and
45 makes a general `undo' mechanism straightforward.
46 .PP
47 .CW Sam
48 is implemented as two processes connected by a low-bandwidth stream,
49 one process handling the display and the other the editing
50 algorithms.  Therefore it can run with the display process
51 in a bitmap terminal and the editor on a local host,
52 with both processes on a bitmap-equipped host, or with
53 the display process in the terminal and the editor in a
54 remote host.
55 By suppressing the display process,
56 it can even run without a bitmap terminal.
57 .PP
58 This paper is reprinted from Software\(emPractice and Experience,
59 Vol 17, number 11, pp. 813-845, November 1987.
60 The paper has not been updated for the Plan 9 manuals.  Although
61 .CW Sam
62 has not changed much since the paper was written, the system around it certainly has.
63 Nonetheless, the description here still stands as the best introduction to the editor.
64 .AE
65 .SH
66 Introduction
67 .LP
68 .CW Sam
69 is an interactive text editor that combines cut-and-paste interactive editing with
70 an unusual command language based on the composition of regular expressions.
71 It is written as two programs: one, the `host part,' runs on a UNIX system
72 and implements the command language and provides file access; the other, the
73 `terminal part,' runs asynchronously
74 on a machine with a mouse and bitmap display
75 and supports the display and interactive editing.
76 The host part may be even run in isolation on an ordinary terminal
77 to edit text using the command
78 language, much like a traditional line editor,
79 without assistance from a mouse or display.
80 Most often,
81 the terminal part runs on a Blit\u\s-4\&1\s+4\d terminal
82 (actually on a Teletype DMD 5620, the production version of the Blit), whose
83 host connection is an ordinary 9600 bps RS232 link;
84 on the SUN computer the host and display processes run on a single machine,
85 connected by a pipe.
86 .PP
87 .CW Sam
88 edits uninterpreted
89 ASCII text.
90 It has no facilities for multiple fonts, graphics or tables,
91 unlike MacWrite,\u\s-4\&2\s+4\d Bravo,\u\s-4\&3\s+4\d Tioga\u\s-4\&4\s+4\d
92 or Lara.\u\s-4\&5\s+4\d
93 Also unlike them, it has a rich command language.
94 (Throughout this paper, the phrase
95 .I
96 command language
97 .R
98 refers to
99 textual commands; commands activated from the mouse form the
100 .I mouse
101 .I language. )
102 .CW Sam
103 developed as an editor for use by programmers, and tries to join
104 the styles of the UNIX text editor
105 .CW ed \u\s-4\&6,7\s+4\d
106 with that of interactive cut-and-paste editors by
107 providing a comfortable mouse-driven interface
108 to a program with a solid command language driven by regular expressions.
109 The command language developed more than the mouse language, and
110 acquired a notation for describing the structure of files
111 more richly than as a sequence of lines,
112 using a dataflow-like syntax for specifying changes.
113 .PP
114 The interactive style was influenced by
115 .CW jim ,\u\s-4\&1\s+4\d
116 an early cut-and-paste editor for the Blit, and by
117 .CW mux ,\u\s-4\&8\s+4\d
118 the Blit window system.
119 .CW Mux
120 merges the original Blit window system,
121 .CW mpx ,\u\s-4\&1\s+4\d
122 with cut-and-paste editing, forming something like a
123 multiplexed version of
124 .CW jim
125 that edits the output of (and input to) command sessions rather than files.
126 .PP
127 The first part of this paper describes the command language, then the mouse
128 language, and explains how they interact.
129 That is followed by a description of the implementation,
130 first of the host part, then of the terminal part.
131 A principle that influenced the design of
132 .CW sam
133 is that it should have no explicit limits, such as upper limits on
134 file size or line length.
135 A secondary consideration is that it be efficient.
136 To honor these two goals together requires a method for efficiently
137 manipulating
138 huge strings (files) without breaking them into lines,
139 perhaps while making thousands of changes
140 under control of the command language.
141 .CW Sam 's
142 method is to
143 treat the file as a transaction database, implementing changes as atomic
144 updates.  These updates may be unwound easily to `undo' changes.
145 Efficiency is achieved through a collection of caches that minimizes
146 disc traffic and data motion, both within the two parts of the program
147 and between them.
148 .PP
149 The terminal part of
150 .CW sam
151 is fairly straightforward.
152 More interesting is how the two halves of the editor stay
153 synchronized when either half may initiate a change.
154 This is achieved through a data structure that organizes the
155 communications and is maintained in parallel by both halves.
156 .PP
157 The last part of the paper chronicles the writing of
158 .CW sam
159 and discusses the lessons that were learned through its development and use.
160 .PP
161 The paper is long, but is composed largely of two papers of reasonable length:
162 a description of the user interface of
163 .CW sam
164 and a discussion of its implementation.
165 They are combined because the implementation is strongly influenced by
166 the user interface, and vice versa.
167 .SH
168 The Interface
169 .LP
170 .CW Sam
171 is a text editor for multiple files.
172 File names may be provided when it is invoked:
173 .P1
174 sam file1 file2 ...
175 .P2
176 and there are commands
177 to add new files and discard unneeded ones.
178 Files are not read until necessary
179 to complete some command.
180 Editing operations apply to an internal copy
181 made when the file is read; the UNIX file associated with the copy
182 is changed only by an explicit command.
183 To simplify the discussion, the internal copy is here called a
184 .I file ,
185 while the disc-resident original is called a
186 .I
187 disc file.
188 .R
189 .PP
190 .CW Sam
191 is usually connected to a bitmap display that presents a cut-and-paste
192 editor driven by the mouse.
193 In this mode, the command language is still available:
194 text typed in a special window, called the
195 .CW sam
196 .I window,
197 is interpreted
198 as commands to be executed in the current file.
199 Cut-and-paste editing may be used in any window \(em even in the
200 .CW sam
201 window to construct commands.
202 The other mode of operation, invoked by starting
203 .CW sam
204 with the option
205 .CW -d
206 (for `no download'),
207 does not use the mouse or bitmap display, but still permits
208 editing using the textual command language, even on an ordinary terminal,
209 interactively or from a script.
210 .PP
211 The following sections describe first the command language (under
212 .CW sam\ -d
213 and in the
214 .CW sam
215 window), and then the mouse interface.
216 These two languages are nearly independent, but connect through the
217 .I current
218 .I text,
219 described below.
220 .SH 2
221 The Command Language
222 .LP
223 A file consists of its contents, which are an array of characters
224 (that is, a string); the
225 .I name
226 of the associated disc file; the
227 .I
228 modified bit
229 .R
230 that states whether the contents match those of
231 the disc file;
232 and a substring of the contents, called the
233 .I
234 current text
235 .R
236 or
237 .I dot
238 (see Figures 1 and 2).
239 If the current text is a null string, dot falls between characters.
240 The
241 .I value
242 of dot is the location of the current text; the
243 .I contents
244 of dot are the characters it contains.
245 .CW Sam
246 imparts to the text no two-dimensional interpretation such as columns
247 or fields; text is always one-dimensional.
248 Even the idea of a `line' of text as understood by most UNIX programs
249 \(em a sequence of characters terminated by a newline character \(em
250 is only weakly supported.
251 .PP
252 The
253 .I
254 current file
255 .R
256 is the file to which editing commands refer.
257 The current text is therefore dot in the current file.
258 If a command doesn't explicitly name a particular file or piece of text,
259 the command is assumed to apply to the current text.
260 For the moment, ignore the presence of multiple files and consider
261 editing a single file.
262 .KF L
263 .XP fig1 3.5i
264 .Cs
265 Figure 1. A typical
266 .CW sam
267 screen, with the editing menu presented.
268 The
269 .CW sam
270 (command language) window is in the middle, with file windows above and below.
271 (The user interface makes it easy to create these abutting windows.)
272 The partially obscured window is a third file window.
273 The uppermost window is that to which typing and mouse operations apply,
274 as indicated by its heavy border.
275 Each window has its current text highlighted in reverse video.
276 The
277 .CW sam
278 window's current text is the null string on the last visible line,
279 indicated by a vertical bar.
280 See also Figure 2.
281 .Ce
282 .KE
283 .PP
284 Commands have one-letter names.
285 Except for non-editing commands such as writing
286 the file to disc, most commands make some change
287 to the text in dot and leave dot set to the text resulting from the change.
288 For example, the delete command,
289 .CW d ,
290 deletes the text in dot, replacing it by the null string and setting dot
291 to the result.
292 The change command,
293 .CW c ,
294 replaces dot by text delimited by an arbitrary punctuation character,
295 conventionally
296 a slash.  Thus,
297 .P1
298 c/Peter/
299 .P2
300 replaces the text in dot by the string
301 .CW Peter .
302 Similarly,
303 .P1
304 a/Peter/
305 .P2
306 (append) adds the string after dot, and
307 .P1
308 i/Peter/
309 .P2
310 (insert) inserts before dot.
311 All three leave dot set to the new text,
312 .CW Peter .
313 .PP
314 Newlines are part of the syntax of commands:
315 the newline character lexically terminates a command.
316 Within the inserted text, however, newlines are never implicit.
317 But since it is often convenient to insert multiple lines of text,
318 .CW sam
319 has a special
320 syntax for that case:
321 .P1
322 a
323 some lines of text
324 to be inserted in the file,
325 terminated by a period
326 on a line by itself
327 \&.
328 .P2
329 In the one-line syntax, a newline character may be specified by a C-like
330 escape, so
331 .P1
332 c/\en/
333 .P2
334 replaces dot by a single newline character.
335 .PP
336 .CW Sam
337 also has a substitute command,
338 .CW s :
339 .P1
340 s/\f2expression\fP/\f2replacement\fP/
341 .P2
342 substitutes the replacement text for the first match, in dot,
343 of the regular expression.
344 Thus, if dot is the string
345 .CW Peter ,
346 the command
347 .P1
348 s/t/st/
349 .P2
350 changes it to
351 .CW Pester .
352 In general,
353 .CW s
354 is unnecessary, but it was inherited from
355 .CW ed
356 and it has some convenient variations.
357 For instance, the replacement text may include the matched text,
358 specified by
359 .CW & :
360 .P1
361 s/Peter/Oh, &, &, &, &!/
362 .P2
363 .PP
364 There are also three commands that apply programs
365 to text:
366 .P1
367 < \f2UNIX program\fP
368 .P2
369 replaces dot by the output of the UNIX program.
370 Similarly, the
371 .CW >
372 command
373 runs the program with dot as its standard input, and
374 .CW |
375 does both.  For example,
376 .P1
377 | sort
378 .P2
379 replaces dot by the result of applying the standard sorting utility to it.
380 Again, newlines have no special significance for these
381 .CW sam
382 commands.
383 The text acted upon and resulting from these commands is not necessarily
384 bounded by newlines, although for connection with UNIX programs,
385 newlines may be necessary to obey conventions.
386 .PP
387 One more command:
388 .CW p
389 prints the contents of dot.
390 Table I summarizes
391 .CW sam 's
392 commands.
393 .KF
394 .TS
395 center;
396 c s
397 lfCW l.
398 Table I. \f(CWSam\fP commands
399 .sp .4
400 .ft CW
401 _
402 .ft
403 .sp .4
404 \f1Text commands\fP     
405 .sp .4
406 _
407 .sp .4
408 a/\f2text\fP/   Append text after dot
409 c/\f2text\fP/   Change text in dot
410 i/\f2text\fP/   Insert text before dot
411 d       Delete text in dot
412 s/\f2regexp\fP/\f2text\fP/      Substitute text for match of regular expression in dot
413 m \f2address\fP Move text in dot after address
414 t \f2address\fP Copy text in dot after address
415 .sp .4
416 _
417 .sp .4
418 \f1Display commands\fP  
419 .sp .4
420 _
421 .sp .2
422 p       Print contents of dot
423 \&=     Print value (line numbers and character numbers) of dot
424 .sp .4
425 _
426 .sp .4
427 \f1File commands\fP
428 .sp .4
429 _
430 .sp .2
431 b \f2file-list\fP       Set current file to first file in list that \f(CWsam\fP has in menu
432 B \f2file-list\fP       Same as \f(CWb\fP, but load new files
433 n       Print menu lines of all files
434 D \f2file-list\fP       Delete named files from \f(CWsam\fP
435 .sp .4
436 _
437 .sp .4
438 \f1I/O commands\fP      
439 .sp .4
440 _
441 .sp .2
442 e \f2filename\fP        Replace file with named disc file
443 r \f2filename\fP        Replace dot by contents of named disc file
444 w \f2filename\fP        Write file to named disc file
445 f \f2filename\fP        Set file name and print new menu line
446 < \f2UNIX-command\fP    Replace dot by standard output of command
447 > \f2UNIX-command\fP    Send dot to standard input of command
448 | \f2UNIX-command\fP    Replace dot by result of command applied to dot
449 ! \f2UNIX-command\fP    Run the command
450 .sp .4
451 _
452 .sp .4
453 \f1Loops and conditionals\fP    
454 .sp .4
455 _
456 .sp .2
457 x/\f2regexp\fP/ \f2command\fP   For each match of regexp, set dot and run command
458 y/\f2regexp\fP/ \f2command\fP   Between adjacent matches of regexp, set dot and run command
459 X/\f2regexp\fP/ \f2command\fP   Run command in each file whose menu line matches regexp
460 Y/\f2regexp\fP/ \f2command\fP   Run command in each file whose menu line does not match
461 g/\f2regexp\fP/ \f2command\fP   If dot contains a match of regexp, run command
462 v/\f2regexp\fP/ \f2command\fP   If dot does not contain a match of regexp, run command
463 .sp .4
464 _
465 .sp .4
466 \f1Miscellany\fP        
467 .sp .4
468 _
469 .sp .2
470 k       Set address mark to value of dot
471 q       Quit
472 u \f2n\fP       Undo last \f2n\fP (default 1) changes
473 { }     Braces group commands
474 .sp .3
475 .ft CW
476 _
477 .ft
478 .TE
479 .sp
480 .KE
481 .PP
482 The value of dot may be changed by
483 specifying an
484 .I address
485 for the command.
486 The simplest address is a line number:
487 .P1
488 3
489 .P2
490 refers to the third line of the file, so
491 .P1
492 3d
493 .P2
494 deletes the third line of the file, and implicitly renumbers
495 the lines so the old line 4 is now numbered 3.
496 (This is one of the few places where
497 .CW sam
498 deals with lines directly.)
499 Line
500 .CW 0
501 is the null string at the beginning of the file.
502 If a command consists of only an address, a
503 .CW p
504 command is assumed, so typing an unadorned
505 .CW 3
506 prints line 3 on the terminal.
507 There are a couple of other basic addresses:
508 a period addresses dot itself; and
509 a dollar sign
510 .CW $ ) (
511 addresses the null string at the end of the file.
512 .PP
513 An address is always a single substring of the file.
514 Thus, the address
515 .CW 3
516 addresses the characters
517 after the second newline of
518 the file through the third newline of the file.
519 A
520 .I
521 compound address
522 .R
523 is constructed by the comma operator
524 .P1
525 \f2address1\fP,\f2address2\fP
526 .P2
527 and addresses the substring of the file from the beginning of
528 .I address1
529 to the end of
530 .I address2 .
531 For example, the command
532 .CW 3,5p
533 prints the third through fifth lines of the file and
534 .CW .,$d
535 deletes the text from the beginning of dot to the end of the file.
536 .PP
537 These addresses are all absolute positions in the file, but
538 .CW sam
539 also has relative addresses, indicated by
540 .CW +
541 or
542 .CW - .
543 For example,
544 .P1
545 $-3
546 .P2
547 is the third line before the end of the file and
548 .P1
549 \&.+1
550 .P2
551 is the line after dot.
552 If no address appears to the left of the
553 .CW +
554 or
555 .CW - ,
556 dot is assumed;
557 if nothing appears to the right,
558 .CW 1
559 is assumed.
560 Therefore,
561 .CW .+1
562 may be abbreviated to just a plus sign.
563 .PP
564 The
565 .CW +
566 operator acts relative to the end of its first argument, while the
567 .CW -
568 operator acts relative to the beginning.  Thus
569 .CW .+1
570 addresses the first line after dot,
571 .CW .-
572 addresses the first line before dot, and
573 .CW +-
574 refers to the line containing the end of dot.  (Dot may span multiple lines, and
575 .CW +
576 selects the line after the end of dot, then
577 .CW -
578 backs up one line.)
579 .PP
580 The final type of address is a regular expression, which addresses the
581 text matched by the expression.  The expression is enclosed in slashes, as in
582 .P1
583 /\f2expression\fP/
584 .P2
585 The expressions are the same as those in the UNIX program
586 .CW egrep ,\u\s-4\&6,7\s+4\d
587 and include closures, alternations, and so on.
588 They find the
589 .I
590 leftmost longest
591 .R
592 string that matches the expression, that is,
593 the first match after the point where the search is started,
594 and if more than one match begins at the same spot, the longest such match.
595 (I assume familiarity with the syntax for regular expressions in UNIX programs.\u\s-4\&9\s+4\d)
596 For example,
597 .P1
598 /x/
599 .P2
600 matches the next
601 .CW x
602 character in the file,
603 .P1
604 /xx*/
605 .P2
606 matches the next run of one or more
607 .CW x 's,
608 and
609 .P1
610 /x|Peter/
611 .P2
612 matches the next
613 .CW x
614 or
615 .CW Peter .
616 For compatibility with other UNIX programs, the `any character' operator,
617 a period,
618 does not match a newline, so
619 .P1
620 /.*/
621 .P2
622 matches the text from dot to the end of the line, but excludes the newline
623 and so will not match across
624 the line boundary.
625 .PP
626 Regular expressions are always relative addresses.
627 The direction is forwards by default,
628 so
629 .CW /Peter/
630 is really an abbreviation for
631 .CW +/Peter/ .
632 The search can be reversed with a minus sign, so
633 .P1
634 .CW -/Peter/
635 .P2
636 finds the first
637 .CW Peter
638 before dot.
639 Regular expressions may be used with other address forms, so
640 .CW 0+/Peter/
641 finds the first
642 .CW Peter
643 in the file and
644 .CW $-/Peter/
645 finds the last.
646 Table II summarizes
647 .CW sam 's
648 addresses.
649 .KF
650 .TS
651 center;
652 c s
653 lfCW l.
654 Table II. \f(CWSam\fP addresses
655 .sp .4
656 .ft CW
657 _
658 .ft
659 .sp .4
660 \f1Simple addresses\fP  
661 .sp .4
662 _
663 .sp .2
664 #\f2n\fP        The empty string after character \f2n\fP
665 \f2n\fP Line \f2n\fP.
666 /\f2regexp\fP/  The first following match of the regular expression
667 -/\f2regexp\fP/ The first previous match of the regular expression
668 $       The null string at the end of the file
669 \&.     Dot
670 \&'     The address mark, set by \f(CWk\fP command
671 "\f2regexp\fP"  Dot in the file whose menu line matches regexp
672 .sp .4
673 _
674 .sp .4
675 \f1Compound addresses\fP        
676 .sp .4
677 _
678 .sp .2
679 \f2a1\fP+\f2a2\fP       The address \f2a2\fP evaluated starting at right of \f2a1\fP
680 \f2a1\fP-\f2a2\fP       \f2a2\fP evaluated in the reverse direction starting at left of \f2a1\fP
681 \f2a1\fP,\f2a2\fP       From the left of \f2a1\fP to the right of \f2a2\fP (default \f(CW0,$\fP)
682 \f2a1\fP;\f2a2\fP       Like \f(CW,\fP but sets dot after evaluating \f2a1\fP
683 .sp .4
684 _
685 .sp .4
686 .T&
687 c s.
688 T{
689 The operators
690 .CW +
691 and
692 .CW -
693 are high precedence, while
694 .CW ,
695 and
696 .CW ;
697 are low precedence.
698 In both
699 .CW +
700 and
701 .CW -
702 forms,
703 .I a2
704 defaults to 1 and
705 .I a1
706 defaults to dot.
707 If both
708 .I a1
709 and
710 .I a2
711 are present,
712 .CW +
713 may be elided.
714 T}
715 .sp .5
716 .ft CW
717 _
718 .ft
719 .TE
720 .sp
721 .KE
722 .PP
723 The language discussed so far will not seem novel
724 to people who use UNIX text editors
725 such as
726 .CW ed
727 or
728 .CW vi .\u\s-4\&9\s+4\d
729 Moreover, the kinds of editing operations these commands allow, with the exception
730 of regular expressions and line numbers,
731 are clearly more conveniently handled by a mouse-based interface.
732 Indeed,
733 .CW sam 's
734 mouse language (discussed at length below) is the means by which
735 simple changes are usually made.
736 For large or repetitive changes, however, a textual language
737 outperforms a manual interface.
738 .PP
739 Imagine that, instead of deleting just one occurrence of the string
740 .CW Peter ,
741 we wanted to eliminate every
742 .CW Peter .
743 What's needed is an iterator that runs a command for each occurrence of some
744 text.
745 .CW Sam 's
746 iterator is called
747 .CW x ,
748 for extract:
749 .P1
750 x/\f2expression\fP/ \f2command\fP
751 .P2
752 finds all matches in dot of the specified expression, and for each
753 such match, sets dot to the text matched and runs the command.
754 So to delete all the
755 .CW Peters:
756 .P1
757 0,$ x/Peter/ d
758 .P2
759 (Blanks in these examples are to improve readability;
760 .CW sam
761 neither requires nor interprets them.)
762 This searches the entire file
763 .CW 0,$ ) (
764 for occurrences of the string
765 .CW Peter ,
766 and runs the
767 .CW d
768 command with dot set to each such occurrence.
769 (By contrast, the comparable
770 .CW ed
771 command would delete all
772 .I lines
773 containing
774 .CW Peter ;
775 .CW sam
776 deletes only the
777 .CW Peters .)
778 The address
779 .CW 0,$
780 is commonly used, and may be abbreviated to just a comma.
781 As another example,
782 .P1
783 , x/Peter/ p
784 .P2
785 prints a list of
786 .CW Peters,
787 one for each appearance in the file, with no intervening text (not even newlines
788 to separate the instances).
789 .PP
790 Of course, the text extracted by
791 .CW x
792 may be selected by a regular expression,
793 which complicates deciding what set of matches is chosen \(em
794 matches may overlap.  This is resolved by generating the matches
795 starting from the beginning of dot using the leftmost-longest rule,
796 and searching for each match starting from the end of the previous one.
797 Regular expressions may also match null strings, but a null match
798 adjacent to a non-null match is never selected; at least one character
799 must intervene.
800 For example,
801 .P1
802 , c/AAA/
803 x/B*/ c/-/
804 , p
805 .P2
806 produces as output
807 .P1
808 -A-A-A-
809 .P2
810 because the pattern
811 .CW B*
812 matches the null strings separating the
813 .CW A 's.
814 .PP
815 The
816 .CW x
817 command has a complement,
818 .CW y ,
819 with similar syntax, that executes the command with dot set to the text
820 .I between
821 the matches of the expression.
822 For example,
823 .P1
824 , c/AAA/
825 y/A/ c/-/
826 , p
827 .P2
828 produces the same result as the example above.
829 .PP
830 The
831 .CW x
832 and
833 .CW y
834 commands are looping constructs, and
835 .CW sam
836 has a pair of conditional commands to go with them.
837 They have similar syntax:
838 .P1
839 g/\f2expression\fP/ \f2command\fP
840 .P2
841 (guard)
842 runs the command exactly once if dot contains a match of the expression.
843 This is different from
844 .CW x ,
845 which runs the command for
846 .I each
847 match:
848 .CW x
849 loops;
850 .CW g
851 merely tests, without changing the value of dot.
852 Thus,
853 .P1
854 , x/Peter/ d
855 .P2
856 deletes all occurrences of
857 .CW Peter ,
858 but
859 .P1
860 , g/Peter/ d
861 .P2
862 deletes the whole file (reduces it to a null string) if
863 .CW Peter
864 occurs anywhere in the text.
865 The complementary conditional is
866 .CW v ,
867 which runs the command if there is
868 .I no
869 match of the expression.
870 .PP
871 These control-structure-like commands may be composed to construct more
872 involved operations.  For example, to print those lines of text that
873 contain the string
874 .CW Peter :
875 .P1
876 , x/.*\en/ g/Peter/ p
877 .P2
878 The
879 .CW x
880 breaks the file into lines, the
881 .CW g
882 selects those lines containing
883 .CW Peter ,
884 and the
885 .CW p
886 prints them.
887 This command gives an address for the
888 .CW x
889 command (the whole file), but because
890 .CW g
891 does not have an explicit address, it applies to the value of
892 dot produced by the
893 .CW x
894 command, that is, to each line.
895 All commands in
896 .CW sam
897 except for the command to write a file to disc use dot for the
898 default address.
899 .PP
900 Composition may be continued indefinitely.
901 .P1
902 , x/.*\en/ g/Peter/ v/SaltPeter/ p
903 .P2
904 prints those lines containing
905 .CW Peter
906 but
907 .I not
908 those containing
909 .CW SaltPeter .
910 .SH 2
911 Structural Regular Expressions
912 .LP
913 Unlike other UNIX text editors,
914 including the non-interactive ones such as
915 .CW sed
916 and
917 .CW awk ,\u\s-4\&7\s+4\d
918 .CW sam
919 is good for manipulating files with multi-line `records.'
920 An example is an on-line phone book composed of records,
921 separated by blank lines, of the form
922 .P1
923 Herbert Tic
924 44 Turnip Ave., Endive, NJ
925 201-5555642
926
927 Norbert Twinge
928 16 Potato St., Cabbagetown, NJ
929 201-5553145
930
931 \&...
932 .P2
933 The format may be encoded as a regular expression:
934 .P1
935 (.+\en)+
936 .P2
937 that is, a sequence of one or more non-blank lines.
938 The command to print Mr. Tic's entire record is then
939 .P1
940 , x/(.+\en)+/ g/^Herbert Tic$/ p
941 .P2
942 and that to extract just the phone number is
943 .P1
944 , x/(.+\en)+/ g/^Herbert Tic$/ x/^[0-9]*-[0-9]*\en/ p
945 .P2
946 The latter command breaks the file into records,
947 chooses Mr. Tic's record,
948 extracts the phone number from the record,
949 and finally prints the number.
950 .PP
951 A more involved problem is that of
952 renaming a particular variable, say
953 .CW n ,
954 to
955 .CW num
956 in a C program.
957 The obvious first attempt,
958 .P1
959 , x/n/ c/num/
960 .P2
961 is badly flawed: it changes not only the variable
962 .CW n
963 but any letter
964 .CW n
965 that appears.
966 We need to extract all the variables, and select those that match
967 .CW n
968 and only
969 .CW n :
970 .P1
971 , x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/
972 .P2
973 The pattern
974 .CW [A-Za-z_][A-Za-z_0-9]*
975 matches C identifiers.
976 Next
977 .CW g/n/
978 selects those containing an
979 .CW n .
980 Then
981 .CW v/../
982 rejects those containing two (or more) characters, and finally
983 .CW c/num/
984 changes the remainder (identifiers
985 .CW n )
986 to
987 .CW num .
988 This version clearly works much better, but there may still be problems.
989 For example, in C character and string constants, the sequence
990 .CW \en
991 is interpreted as a newline character, and we don't want to change it to
992 .CW \enum.
993 This problem can be forestalled with a
994 .CW y
995 command:
996 .P1
997 , y/\e\en/ x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/
998 .P2
999 (the second
1000 .CW \e
1001 is necessary because of lexical conventions in regular expressions),
1002 or we could even reject character constants and strings outright:
1003 .P1 0
1004 ,y/'[^']*'/ y/"[^"]*"/ x/[A-Za-z_][A-Za-z_0-9]*/ g/n/ v/../ c/num/
1005 .P2
1006 The
1007 .CW y
1008 commands in this version exclude from consideration all character constants
1009 and strings.
1010 The only remaining problem is to deal with the possible occurrence of
1011 .CW \e'
1012 or
1013 .CW \e"
1014 within these sequences, but it's easy to see how to resolve this difficulty.
1015 .PP
1016 The point of these composed commands is successive refinement.
1017 A simple version of the command is tried, and if it's not good enough,
1018 it can be honed by adding a clause or two.
1019 (Mistakes can be undone; see below.
1020 Also, the mouse language makes it unnecessary to retype the command each time.)
1021 The resulting chains of commands are somewhat reminiscent of
1022 shell pipelines.\u\s-4\&7\s+4\d
1023 Unlike pipelines, though, which pass along modified
1024 .I data ,
1025 .CW sam
1026 commands pass a
1027 .I view
1028 of the data.
1029 The text at each step of the command is the same, but which pieces
1030 are selected is refined step by step until the correct piece is
1031 available to the final step of the command line, which ultimately makes the change.
1032 .PP
1033 In other UNIX programs, regular expressions are used only for selection,
1034 as in the
1035 .CW sam
1036 .CW g
1037 command, never for extraction as in the
1038 .CW x
1039 or
1040 .CW y
1041 command.
1042 For example, patterns in
1043 .CW awk \u\s-4\&7\s+4\d
1044 are used to select lines to be operated on, but cannot be used
1045 to describe the format of the input text, or to handle newline-free text.
1046 The use of regular expressions to describe the structure of a piece
1047 of text rather than its contents, as in the
1048 .CW x
1049 command, 
1050 has been given a name:
1051 .I
1052 structural regular expressions.
1053 .R
1054 When they are composed, as in the above example,
1055 they are pleasantly expressive.
1056 Their use is discussed at greater length elsewhere.\u\s-4\&10\s+4\d
1057 .PP
1058 .SH 2
1059 Multiple files
1060 .LP
1061 .CW Sam
1062 has a few other commands, mostly relating to input and output.
1063 .P1
1064 e discfilename
1065 .P2
1066 replaces the contents and name of the current file with those of the named
1067 disc file;
1068 .P1
1069 w discfilename
1070 .P2
1071 writes the contents to the named disc file; and
1072 .P1
1073 r discfilename
1074 .P2
1075 replaces dot with the contents of the named disc file.
1076 All these commands use the current file's name if none is specified.
1077 Finally,
1078 .P1
1079 f discfilename
1080 .P2
1081 changes the name associated with the file and displays the result:
1082 .P1
1083 \&'-. discfilename
1084 .P2
1085 This output is called the file's
1086 .I
1087 menu line,
1088 .R
1089 because it is the contents of the file's line in the button 3 menu (described
1090 in the
1091 next section).
1092 The first three characters are a concise notation for the state of the file.
1093 The apostrophe signifies that the file is modified.
1094 The minus sign indicates the number of windows
1095 open on the file (see the next section):
1096 .CW -
1097 means none,
1098 .CW +
1099 means one, and
1100 .CW *
1101 means more than one.
1102 Finally, the period indicates that this is the current file.
1103 These characters are useful for controlling the
1104 .CW X
1105 command, described shortly.
1106 .PP
1107 .CW Sam
1108 may be started with a set of disc files (such as all the source for
1109 a program) by invoking it with a list of file names as arguments, and
1110 more may be added or deleted on demand.
1111 .P1
1112 B discfile1 discfile2 ...
1113 .P2
1114 adds the named files to
1115 .CW sam 's
1116 list, and
1117 .P1
1118 D discfile1 discfile2 ...
1119 .P2
1120 removes them from
1121 .CW sam 's
1122 memory (without effect on associated disc files).
1123 Both these commands have a syntax for using the shell\u\s-4\&7\s+4\d
1124 (the UNIX command interpreter) to generate the lists:
1125 .P1
1126 B <echo *.c
1127 .P2
1128 will add all C source files, and
1129 .P1
1130 B <grep -l variable *.c
1131 .P2
1132 will add all C source files referencing a particular variable
1133 (the UNIX command
1134 .CW grep\ -l
1135 lists all files in its arguments that contain matches of
1136 the specified regular expression).
1137 Finally,
1138 .CW D
1139 without arguments deletes the current file.
1140 .PP
1141 There are two ways to change which file is current:
1142 .P1
1143 b filename
1144 .P2
1145 makes the named file current.
1146 The
1147 .CW B
1148 command
1149 does the same, but also adds any new files to
1150 .CW sam 's
1151 list.
1152 (In practice, of course, the current file
1153 is usually chosen by mouse actions, not by textual commands.)
1154 The other way is to use a form of address that refers to files:
1155 .P1
1156 "\f2expression\fP" \f2address\fP
1157 .P2
1158 refers to the address evaluated in the file whose menu line
1159 matches the expression (there must be exactly one match).
1160 For example,
1161 .P1
1162 "peter.c" 3
1163 .P2
1164 refers to the third line of the file whose name matches
1165 .CW peter.c .
1166 This is most useful in the move
1167 .CW m ) (
1168 and copy
1169 .CW t ) (
1170 commands:
1171 .P1
1172 0,$ t "peter.c" 0
1173 .P2
1174 makes a copy of the current file at the beginning of
1175 .CW peter.c .
1176 .PP
1177 The
1178 .CW X
1179 command
1180 is a looping construct, like
1181 .CW x ,
1182 that refers to files instead of strings:
1183 .P1
1184 X/\f2expression\fP/ \f2command\fP
1185 .P2
1186 runs the command in all
1187 files whose menu lines match the expression.  The best example is
1188 .P1
1189 X/'/ w
1190 .P2
1191 which writes to disc all modified files.
1192 .CW Y
1193 is the complement of
1194 .CW X :
1195 it runs the command on all files whose menu lines don't match the expression:
1196 .P1
1197 Y/\e.c/ D
1198 .P2
1199 deletes all files that don't have
1200 .CW \&.c
1201 in their names, that is, it keeps all C source files and deletes the rest.
1202 .PP
1203 Braces allow commands to be grouped, so
1204 .P1
1205 {
1206         \f2command1\fP
1207         \f2command2\fP
1208 }
1209 .P2
1210 is syntactically a single command that runs two commands.
1211 Thus,
1212 .P1
1213 X/\e.c/ ,g/variable/ {
1214         f
1215         , x/.*\en/ g/variable/ p
1216 }
1217 .P2
1218 finds all occurrences of
1219 .CW variable
1220 in C source files, and prints
1221 out the file names and lines of each match.
1222 The precise semantics of compound operations is discussed in the implementation
1223 sections below.
1224 .PP
1225 Finally,
1226 the undo command,
1227 .CW u ,
1228 undoes the last command,
1229 no matter how many files were affected.
1230 Multiple undo operations move further back in time, so
1231 .P1
1232 u
1233 u
1234 .P2
1235 (which may be abbreviated
1236 .CW u2 )
1237 undoes the last two commands.  An undo may not be undone, however, nor
1238 may any command that adds or deletes files.
1239 Everything else is undoable, though, including for example
1240 .CW e
1241 commands:
1242 .P1
1243 e filename
1244 u
1245 .P2
1246 restores the state of the file completely, including its name, dot,
1247 and modified bit.  Because of the undo, potentially dangerous commands
1248 are not guarded by confirmations.  Only
1249 .CW D ,
1250 which destroys the information necessary to restore itself, is protected.
1251 It will not delete a modified file, but a second
1252 .CW D
1253 of the same file will succeed regardless.
1254 The
1255 .CW q
1256 command, which exits
1257 .CW sam ,
1258 is similarly guarded.
1259 .SH 2
1260 Mouse Interface
1261 .LP
1262 .CW Sam
1263 is most commonly run
1264 connected to a bitmap display and mouse for interactive editing.
1265 The only difference in the command language
1266 between regular, mouse-driven
1267 .CW sam
1268 and
1269 .CW sam\ -d
1270 is that if an address
1271 is provided without a command,
1272 .CW sam\ -d
1273 will print the text referenced by the address, but
1274 regular
1275 .CW sam
1276 will highlight it on the screen \(em in fact,
1277 dot is always highlighted (see Figure 2).
1278 .WS 1
1279 .KF
1280 .XP fig3 2.04i
1281 .Cs
1282 Figure 2. A
1283 .CW sam
1284 window.  The scroll bar down the left
1285 represents the file, with the bubble showing the fraction
1286 visible in the window.
1287 The scroll bar may be manipulated by the mouse for convenient browsing.
1288 The current text,
1289 which is highlighted, need not fit on a line.  Here it consists of one partial
1290 line, one complete line, and final partial line.
1291 .Ce
1292 .KE
1293 .PP
1294 Each file may have zero or more windows open on the display.
1295 At any time, only one window in all of
1296 .CW sam
1297 is the
1298 .I
1299 current window,
1300 .R
1301 that is, the window to which typing and mouse actions refer;
1302 this may be the
1303 .CW sam
1304 window (that in which commands may be typed)
1305 or one of the file windows.
1306 When a file has multiple windows, the image of the file in each window
1307 is always kept up to date.
1308 The current file is the last file affected by a command,
1309 so if the
1310 .CW sam
1311 window is current,
1312 the current window is not a window on the current file.
1313 However, each window on a file has its own value of dot,
1314 and when switching between windows on a single file,
1315 the file's value of dot is changed to that of the window.
1316 Thus, flipping between windows behaves in the obvious, convenient way.
1317 .PP
1318 The mouse on the Blit has three buttons, numbered left to right.
1319 Button 3 has a list of commands to manipulate windows,
1320 followed by a list of `menu lines' exactly as printed by the
1321 .CW f
1322 command, one per file (not one per window).
1323 These menu lines are sorted by file name.
1324 If the list is long, the Blit menu software will make it more manageable
1325 by generating a scrolling menu instead of an unwieldy long list.
1326 Using the menu to select a file from the list makes that file the current
1327 file, and the most recently current window in that file the current window.
1328 But if that file is already current, selecting it in the menu cycles through
1329 the windows on the file; this simple trick avoids a special menu to
1330 choose windows on a file.
1331 If there is no window open on the file,
1332 .CW sam
1333 changes the mouse cursor to prompt the user to create one.
1334 .PP
1335 The commands on the button 3 menu are straightforward (see Figure 3), and
1336 are like the commands to manipulate windows in
1337 .CW mux ,\u\s-4\&8\s+4\d
1338 the Blit's window system.
1339 .CW New
1340 makes a new file, and gives it one empty window, whose size is determined
1341 by a rectangle swept by the mouse.
1342 .CW Zerox
1343 prompts for a window to be selected, and
1344 makes a clone of that window; this is how multiple windows are created on one file.
1345 .CW Reshape
1346 changes the size of the indicated window, and
1347 .CW close
1348 deletes it.  If that is the last window open on the file,
1349 .CW close
1350 first does a
1351 .CW D
1352 command on the file.
1353 .CW Write
1354 is identical to a
1355 .CW w
1356 command on the file; it is in the menu purely for convenience.
1357 Finally,
1358 .CW ~~sam~~
1359 is a menu item that appears between the commands and the file names.
1360 Selecting it makes the
1361 .CW sam
1362 window the current window,
1363 causing subsequent typing to be interpreted as commands.
1364 .KF
1365 .XP fig2 2.74i
1366 .Cs
1367 Figure 3. The menu on button 3.
1368 The black rectangle on the left is a scroll bar; the menu is limited to
1369 the length shown to prevent its becoming unwieldy.
1370 Above the
1371 .CW ~~sam~~
1372 line is a list of commands;
1373 beneath it is a list of files, presented exactly as with the
1374 .CW f
1375 command.
1376 .Ce
1377 .KE
1378 .PP
1379 When
1380 .CW sam
1381 requests that a window be swept, in response to
1382 .CW new ,
1383 .CW zerox
1384 or
1385 .CW reshape ,
1386 it changes the mouse cursor from the usual arrow to a box with
1387 a small arrow.
1388 In this state, the mouse may be used to indicate an arbitrary rectangle by
1389 pressing button 3 at one corner and releasing it at the opposite corner.
1390 More conveniently,
1391 button 3 may simply be clicked,
1392 whereupon
1393 .CW sam
1394 creates the maximal rectangle that contains the cursor
1395 and abuts the
1396 .CW sam
1397 window.
1398 By placing the
1399 .CW sam
1400 window in the middle of the screen, the user can define two regions (one above,
1401 one below) in which stacked fully-overlapping
1402 windows can be created with minimal fuss (see Figure 1).
1403 This simple user interface trick makes window creation noticeably easier.
1404 .PP
1405 The cut-and-paste editor is essentially the same as that in Smalltalk-80.\u\s-4\&11\s+4\d
1406 The text in dot is always highlighted on the screen.
1407 When a character is typed it replaces dot, and sets dot to the null
1408 string after the character.  Thus, ordinary typing inserts text.
1409 Button 1 is used for selection:
1410 pressing the button, moving the mouse, and lifting the button
1411 selects (sets dot to) the text between the points where the
1412 button was pressed and released.
1413 Pressing and releasing at the same point selects a null string; this
1414 is called clicking.  Clicking twice quickly, or
1415 .I
1416 double clicking,
1417 .R
1418 selects larger objects;
1419 for example, double clicking in a word selects the word,
1420 double clicking just inside an opening bracket selects the text
1421 contained in the brackets (handling nested brackets correctly),
1422 and similarly for
1423 parentheses, quotes, and so on.
1424 The double-clicking rules reflect a bias toward
1425 programmers.
1426 If
1427 .CW sam
1428 were intended more for word processing, double-clicks would probably
1429 select linguistic structures such as sentences.
1430 .PP
1431 If button 1 is pressed outside the current window, it makes the indicated
1432 window current.
1433 This is the easiest way to switch between windows and files.
1434 .PP
1435 Pressing button 2 brings up a menu of editing functions (see Figure 4).
1436 These mostly apply to the selected text:
1437 .CW cut
1438 deletes the selected text, and remembers it in a hidden buffer called the
1439 .I
1440 snarf buffer,
1441 .R
1442 .CW paste
1443 replaces the selected text by the contents of the snarf buffer,
1444 .CW snarf
1445 just copies the selected text to the snarf buffer,
1446 .CW look
1447 searches forward for the next literal occurrence of the selected text, and
1448 .CW <mux>
1449 exchanges snarf buffers with the window system in which
1450 .CW sam
1451 is running.
1452 Finally, the last regular expression used appears as a menu entry
1453 to search
1454 forward for the next occurrence of a match for the expression.
1455 .WS 1
1456 .KF
1457 .XP fig4 1.20i
1458 .Cs
1459 Figure 4. The menu on button 2.
1460 The bottom entry tracks the most recently used regular expression, which may
1461 be literal text.
1462 .Ce
1463 .KE
1464 .PP
1465 The relationship between the command language and the mouse language is
1466 entirely due to the equality of dot and the selected text chosen
1467 with button 1 on the mouse.
1468 For example, to make a set of changes in a C subroutine, dot can be
1469 set by double clicking on the left brace that begins the subroutine,
1470 which sets dot for the command language.
1471 An address-free command then typed in the
1472 .CW sam
1473 window will apply only to the text between the opening and closing
1474 braces of the function.
1475 The idea is to select what you want, and then say what you want
1476 to do with it, whether invoked by a menu selection or by a typed command.
1477 And of course, the value of dot is highlighted on
1478 the display after the command completes.
1479 This relationship between mouse interface and command language
1480 is clumsy to explain, but comfortable, even natural, in practice.
1481 .SH
1482 The Implementation
1483 .LP
1484 The next few sections describe how
1485 .CW sam
1486 is put together, first the host part,
1487 then the inter-component communication,
1488 then the terminal part.
1489 After explaining how the command language is implemented,
1490 the discussion follows (roughly) the path of a character
1491 from the temporary file on disc to the screen.
1492 The presentation centers on the data structures,
1493 because that is how the program was designed and because
1494 the algorithms are easy to provide, given the right data
1495 structures.
1496 .SH 2
1497 Parsing and execution
1498 .LP
1499 The command language is interpreted by parsing each command with a
1500 table-driven recursive
1501 descent parser, and when a complete command is assembled, invoking a top-down
1502 executor.
1503 Most editors instead employ a simple character-at-a-time
1504 lexical scanner.
1505 Use of a parser makes it
1506 easy and unambiguous to detect when a command is complete,
1507 which has two advantages.
1508 First, escape conventions such as backslashes to quote
1509 multiple-line commands are unnecessary;  if the command isn't finished,
1510 the parser keeps reading.  For example, a multiple-line append driven by an
1511 .CW x
1512 command is straightforward:
1513 .P1
1514 x/.*\en/ g/Peter/ a
1515 one line about Peter
1516 another line about Peter
1517 \&.
1518 .P2
1519 Other UNIX editors would require a backslash after all but the last line.
1520 .PP
1521 The other advantage is specific to the two-process structure of
1522 .CW sam .
1523 The host process must decide when a command is completed so the
1524 command interpreter can be called.  This problem is easily resolved
1525 by having the lexical analyzer read the single stream of events from the
1526 terminal, directly executing all typing and mouse commands,
1527 but passing to the parser characters typed to the
1528 .CW sam
1529 command window.
1530 This scheme is slightly complicated by the availability of cut-and-paste
1531 editing in the
1532 .CW sam
1533 window, but that difficulty is resolved by applying the rules
1534 used in
1535 .CW mux :
1536 when a newline is typed to the
1537 .CW sam
1538 window, all text between the newline and the previously typed newline
1539 is made available to the parser.
1540 This permits arbitrary editing to be done to a command before
1541 typing newline and thereby requesting execution.
1542 .PP
1543 The parser is driven by a table because the syntax of addresses
1544 and commands is regular enough
1545 to be encoded compactly.  There are few special cases, such as the
1546 replacement text in a substitution, so the syntax of almost all commands
1547 can be encoded with a few flags.
1548 These include whether the command allows an address (for example,
1549 .CW e
1550 does not), whether it takes a regular expression (as in
1551 .CW x
1552 and
1553 .CW s ),
1554 whether it takes replacement text (as in
1555 .CW c
1556 or
1557 .CW i ),
1558 which may be multi-line, and so on.
1559 The internal syntax of regular expressions is handled by a separate
1560 parser; a regular expression is a leaf of the command parse tree.
1561 Regular expressions are discussed fully in the next section.
1562 .PP
1563 The parser table also has information about defaults, so the interpreter
1564 is always called with a complete tree.  For example, the parser fills in
1565 the implicit
1566 .CW 0
1567 and
1568 .CW $
1569 in the abbreviated address
1570 .CW ,
1571 (comma),
1572 inserts a
1573 .CW +
1574 to the left of an unadorned regular expression in an address,
1575 and provides the usual default address
1576 .CW .
1577 (dot) for commands that expect an address but are not given one.
1578 .PP
1579 Once a complete command is parsed, the evaluation is easy.
1580 The address is evaluated left-to-right starting from the value of dot,
1581 with a mostly ordinary expression evaluator.
1582 Addresses, like many of the data structures in
1583 .CW sam ,
1584 are held in a C structure and passed around by value:
1585 .P1
1586 typedef long Posn;    /* Position in a file */
1587 typedef struct Range{
1588         Posn    p1, p2;
1589 }Range;
1590 typedef struct Address{
1591         Range   r;
1592         File    *f;
1593 }Address;
1594 .P2
1595 An address is encoded as a substring (character positions
1596 .CW p1
1597 to
1598 .CW p2 )
1599 in a file
1600 .CW f .
1601 (The data type
1602 .CW File
1603 is described in detail below.)
1604 .PP
1605 The address interpreter is an
1606 .CW Address -valued
1607 function that traverses the parse tree describing an address (the
1608 parse tree for the address has type
1609 .CW Addrtree ):
1610 .P1
1611 Address
1612 address(ap, a, sign)
1613         Addrtree *ap;
1614         Address a;
1615         int sign;
1616 {
1617         Address a2;
1618         do
1619                 switch(ap->type){
1620                 case '.':
1621                         a=a.f->dot;
1622                         break;
1623                 case '$':
1624                         a.r.p1=a.r.p2=a.f->nbytes;
1625                         break;
1626                 case '"':       
1627                         a=matchfile(a, ap->aregexp)->dot; 
1628                         break;
1629                 case ',':
1630                         a2=address(ap->right, a, 0);
1631                         a=address(ap->left, a, 0);
1632                         if(a.f!=a2.f || a2.r.p2<a.r.p1)
1633                                 error(Eorder);
1634                         a.r.p2=a2.r.p2;
1635                         return a;
1636                 /* and so on */
1637                 }
1638         while((ap=ap->right)!=0);
1639         return a;
1640 }
1641 .P2
1642 .PP
1643 Throughout, errors are handled by a non-local
1644 .CW goto
1645 (a
1646 .CW setjmp/longjmp
1647 in C terminology)
1648 hidden in a routine called
1649 .CW error
1650 that immediately aborts the execution, retracts any
1651 partially made changes (see the section below on `undoing'), and
1652 returns to the top level of the parser.
1653 The argument to
1654 .CW error
1655 is an enumeration type that
1656 is translated to a terse but possibly helpful
1657 message such as `?addresses out of order.'
1658 Very common messages are kept short; for example the message for
1659 a failed regular expression search is `?search.'
1660 .PP
1661 Character addresses such as
1662 .CW #3
1663 are trivial to implement, as the
1664 .CW File
1665 data structure is accessible by character number.
1666 However,
1667 .CW sam
1668 keeps no information about the position of newlines \(em it is too
1669 expensive to track dynamically \(em so line addresses are computed by reading
1670 the file, counting newlines.  Except in very large files, this has proven
1671 acceptable: file access is fast enough to make the technique practical,
1672 and lines are not central to the structure of the command language.
1673 .PP
1674 The command interpreter, called
1675 .CW cmdexec ,
1676 is also straightforward.  The parse table includes a
1677 function to call to interpret a particular command.  That function
1678 receives as arguments
1679 the calculated address
1680 for the command
1681 and the command tree (of type
1682 .CW Cmdtree ),
1683 which may contain information such as the subtree for compound commands.
1684 Here, for example, is the function for the
1685 .CW g
1686 and
1687 .CW v
1688 commands:
1689 .P1
1690 int
1691 g_cmd(a, cp)
1692         Address a;
1693         Cmdtree *cp;
1694 {
1695         compile(cp->regexp);
1696         if(execute(a.f, a.r.p1, a.r.p2)!=(cp->cmdchar=='v')){
1697                 a.f->dot=a;
1698                 return cmdexec(a, cp->subcmd);
1699         }
1700         return TRUE;    /* cause execution to continue */
1701 }
1702 .P2
1703 .CW Compile "" (
1704 and
1705 .CW execute
1706 are part of the regular expression code, described in the next section.)
1707 Because the parser and the
1708 .CW File
1709 data structure do most of the work, most commands
1710 are similarly brief.
1711 .SH 2
1712 Regular expressions
1713 .LP
1714 The regular expression code in
1715 .CW sam
1716 is an interpreted, rather than compiled on-the-fly, implementation of Thompson's
1717 non-deterministic finite automaton algorithm.\u\s-4\&12\s+4\d
1718 The syntax and semantics of the expressions are as in the UNIX program
1719 .CW egrep ,
1720 including alternation, closures, character classes, and so on.
1721 The only changes in the notation are two additions:
1722 .CW \en
1723 is translated to, and matches, a newline character, and
1724 .CW @
1725 matches any character.  In
1726 .CW egrep ,
1727 the character
1728 .CW \&.
1729 matches any character except newline, and in
1730 .CW sam
1731 the same rule seemed safest, to prevent idioms like
1732 .CW \&.*
1733 from spanning newlines.
1734 .CW Egrep
1735 expressions are arguably too complicated for an interactive editor \(em
1736 certainly it would make sense if all the special characters were two-character
1737 sequences, so that most of the punctuation characters wouldn't have
1738 peculiar meanings \(em but for an interesting command language, full
1739 regular expressions are necessary, and
1740 .CW egrep
1741 defines the full regular expression syntax for UNIX programs.
1742 Also, it seemed superfluous to define a new syntax, since various UNIX programs
1743 .CW ed , (
1744 .CW egrep
1745 and
1746 .CW vi )
1747 define too many already.
1748 .PP
1749 The expressions are compiled by a routine,
1750 .CW compile ,
1751 that generates the description of the non-deterministic finite state machine.
1752 A second routine,
1753 .CW execute ,
1754 interprets the machine to generate the leftmost-longest match of the
1755 expression in a substring of the file.
1756 The algorithm is described elsewhere.\u\s-4\&12,13\s+4\d
1757 .CW Execute
1758 reports
1759 whether a match was found, and sets a global variable,
1760 of type
1761 .CW Range ,
1762 to the substring matched.
1763 .PP
1764 A trick is required to evaluate the expression in reverse, such as when
1765 searching backwards for an expression.
1766 For example,
1767 .P1
1768 -/P.*r/
1769 .P2
1770 looks backwards through the file for a match of the expression.
1771 The expression, however, is defined for a forward search.
1772 The solution is to construct a machine identical to the machine
1773 for a forward search except for a reversal of all the concatenation
1774 operators (the other operators are symmetric under direction reversal),
1775 to exchange the meaning of the operators
1776 .CW ^
1777 and
1778 .CW $ ,
1779 and then to read the file backwards, looking for the
1780 usual earliest longest match.
1781 .PP
1782 .CW Execute
1783 generates only one match each time it is called.
1784 To interpret looping constructs such as the
1785 .CW x
1786 command,
1787 .CW sam
1788 must therefore synchronize between
1789 calls of
1790 .CW execute
1791 to avoid
1792 problems with null matches.
1793 For example, even given the leftmost-longest rule,
1794 the expression
1795 .CW a*
1796 matches three times in the string
1797 .CW ab
1798 (the character
1799 .CW a ,
1800 the null string between the
1801 .CW a
1802 and
1803 .CW b ,
1804 and the final null string).
1805 After returning a match for the
1806 .CW a ,
1807 .CW sam
1808 must not match the null string before the
1809 .CW b .
1810 The algorithm starts
1811 .CW execute
1812 at the end of its previous match, and
1813 if the match it returns
1814 is null and abuts the previous match, rejects the match and advances
1815 the initial position one character.
1816 .SH 2
1817 Memory allocation
1818 .LP
1819 The C language has no memory allocation primitives, although a standard
1820 library routine,
1821 .CW malloc ,
1822 provides adequate service for simple programs.
1823 For specific uses, however,
1824 it can be better to write a custom allocator.
1825 The allocator (or rather, pair of allocators) described here
1826 work in both the terminal and host parts of
1827 .CW sam .
1828 They are designed for efficient manipulation of strings,
1829 which are allocated and freed frequently and vary in length from essentially
1830 zero to 32 Kbytes (very large strings are written to disc).
1831 More important, strings may be large and change size often,
1832 so to minimize memory usage it is helpful to reclaim and to coalesce the
1833 unused portions of strings when they are truncated.
1834 .PP
1835 Objects to be allocated in
1836 .CW sam
1837 are of two flavors:
1838 the first is C
1839 .CW structs ,
1840 which are small and often addressed by pointer variables;
1841 the second is variable-sized arrays of characters
1842 or integers whose
1843 base pointer is always used to access them.
1844 The memory allocator in
1845 .CW sam
1846 is therefore in two parts:
1847 first, a traditional first-fit allocator that provides fixed storage for
1848 .CW structs ;
1849 and second, a garbage-compacting allocator that reduces storage
1850 overhead for variable-sized objects, at the cost of some bookkeeping.
1851 The two types of objects are allocated from adjoining arenas, with
1852 the garbage-compacting allocator controlling the arena with higher addresses.
1853 Separating into two arenas simplifies compaction and prevents fragmentation due
1854 to immovable objects.
1855 The access rules for garbage-compactable objects
1856 (discussed in the next paragraph) allow them to be relocated, so when
1857 the first-fit arena needs space, it moves the garbage-compacted arena
1858 to higher addresses to make room.  Storage is therefore created only
1859 at successively higher addresses, either when more garbage-compacted
1860 space is needed or when the first-fit arena pushes up the other arena.
1861 .PP
1862 Objects that may be compacted declare to the
1863 allocator a cell that is guaranteed to be the sole repository of the
1864 address of the object whenever a compaction can occur.
1865 The compactor can then update the address when the object is moved.
1866 For example, the implementation of type
1867 .CW List
1868 (really a variable-length array)
1869 is:
1870 .P1
1871 typedef struct List{
1872         int     nused;
1873         long    *ptr;
1874 }List;
1875 .P2
1876 The
1877 .CW ptr
1878 cell must always be used directly, and never copied.  When a
1879 .CW List
1880 is to be created the
1881 .CW List
1882 structure is allocated in the ordinary first-fit arena
1883 and its
1884 .CW ptr
1885 is allocated in the garbage-compacted arena.
1886 A similar data type for strings, called
1887 .CW String ,
1888 stores variable-length character arrays of up to 32767 elements.
1889 .PP
1890 A related matter of programming style:
1891 .CW sam
1892 frequently passes structures by value, which
1893 simplifies the code.
1894 Traditionally, C programs have
1895 passed structures by reference, but implicit allocation on
1896 the stack is easier to use.
1897 Structure passing is a relatively new feature of C
1898 (it is not in the 
1899 standard reference manual for C\u\s-4\&14\s+4\d), and is poorly supported in most
1900 commercial C compilers.
1901 It's convenient and expressive, though,
1902 and simplifies memory management by
1903 avoiding the allocator altogether
1904 and eliminating pointer aliases.
1905 .SH 2
1906 Data structures for manipulating files
1907 .LP
1908 Experience with
1909 .CW jim
1910 showed that the requirements
1911 of the file data structure were few, but strict.
1912 First, files need to be read and written quickly;
1913 adding a fresh file must be painless.
1914 Second, the implementation must place no arbitrary upper limit on
1915 the number or sizes of files.  (It should be practical to edit many files,
1916 and files up to megabytes in length should be handled gracefully.)
1917 This implies that files be stored on disc, not in main memory.
1918 (Aficionados of virtual memory may argue otherwise, but the
1919 implementation of virtual
1920 memory in our system is not something to depend on
1921 for good performance.)
1922 Third, changes to files need be made by only two primitives:
1923 deletion and insertion.
1924 These are inverses of each other,
1925 which simplifies the implementation of the undo operation.
1926 Finally,
1927 it must be easy and efficient to access the file, either
1928 forwards or backwards, a byte at a time.
1929 .PP
1930 The
1931 .CW File
1932 data type is constructed from three simpler data structures that hold arrays
1933 of characters.
1934 Each of these types has an insertion and deletion operator, and the
1935 insertion and deletion operators of the
1936 .CW File
1937 type itself are constructed from them.
1938 .PP
1939 The simplest type is the
1940 .CW String ,
1941 which is used to hold strings in main memory.
1942 The code that manages
1943 .CW Strings
1944 guarantees that they will never be longer
1945 than some moderate size, and in practice they are rarely larger than 8 Kbytes.
1946 .CW Strings
1947 have two purposes: they hold short strings like file names with little overhead,
1948 and because they are deliberately small, they are efficient to modify.
1949 They are therefore used as the data structure for in-memory caches.
1950 .PP
1951 The disc copy of the file is managed by a data structure called a
1952 .CW Disc ,
1953 which corresponds to a temporary file.  A
1954 .CW Disc
1955 has no storage in main memory other than bookkeeping information;
1956 the actual data being held is all on the disc.
1957 To reduce the number of open files needed,
1958 .CW sam
1959 opens a dozen temporary UNIX files and multiplexes the
1960 .CW Discs
1961 upon them.
1962 This permits many files to
1963 be edited; the entire
1964 .CW sam
1965 source (48 files) may be edited comfortably with a single
1966 instance of
1967 .CW sam .
1968 Allocating one temporary file per
1969 .CW Disc
1970 would strain the operating system's limit on the number of open files.
1971 Also, spreading the traffic among temporary files keeps the files shorter,
1972 and shorter files are more efficiently implemented by the UNIX
1973 I/O subsystem.
1974 .PP
1975 A
1976 .CW Disc
1977 is an array of fixed-length blocks, each of which contains
1978 between 1 and 4096 characters of active data.
1979 (The block size of our UNIX file system is 4096 bytes.)
1980 The block addresses within the temporary file and the length of each
1981 block are stored in a
1982 .CW List .
1983 When changes are made the live part of blocks may change size.
1984 Blocks are created and coalesced when necessary to try to keep the sizes
1985 between 2048 and 4096 bytes.
1986 An actively changing part of the
1987 .CW Disc
1988 therefore typically has about a kilobyte of slop that can be
1989 inserted or deleted
1990 without changing more than one block or affecting the block order.
1991 When an insertion would overflow a block, the block is split, a new one
1992 is allocated to receive the overflow, and the memory-resident list of blocks
1993 is rearranged to reflect the insertion of the new block.
1994 .PP
1995 Obviously, going to the disc for every modification to the file is
1996 prohibitively expensive.
1997 The data type
1998 .CW Buffer
1999 consists of a
2000 .CW Disc
2001 to hold the data and a
2002 .CW String
2003 that acts as a cache.
2004 This is the first of a series of caches throughout the data structures in
2005 .CW sam.
2006 The caches not only improve performance, they provide a way to organize
2007 the flow of data, particularly in the communication between the host
2008 and terminal.
2009 This idea is developed below, in the section on communications.
2010 .PP
2011 To reduce disc traffic, changes to a
2012 .CW Buffer
2013 are mediated by a variable-length string, in memory, that acts as a cache.
2014 When an insertion or deletion is made to a
2015 .CW Buffer ,
2016 if the change can be accommodated by the cache, it is done there.
2017 If the cache becomes bigger than a block because of an insertion,
2018 some of it is written to the
2019 .CW Disc
2020 and deleted from the cache.
2021 If the change does not intersect the cache, the cache is flushed.
2022 The cache is only loaded at the new position if the change is smaller than a block;
2023 otherwise, it is sent directly to the
2024 .CW Disc .
2025 This is because
2026 large changes are typically sequential,
2027 whereupon the next change is unlikely to overlap the current one.
2028 .PP
2029 A
2030 .CW File
2031 comprises a
2032 .CW String
2033 to hold the file name and some ancillary data such as dot and the modified bit.
2034 The most important components, though, are a pair of
2035 .CW Buffers ,
2036 one called the transcript and the other the contents.
2037 Their use is described in the next section.
2038 .PP
2039 The overall structure is shown in Figure 5.
2040 Although it may seem that the data is touched many times on its
2041 way from the
2042 .CW Disc ,
2043 it is read (by one UNIX system call) directly into the cache of the
2044 associated
2045 .CW Buffer ;
2046 no extra copy is done.
2047 Similarly, when flushing the cache, the text is written
2048 directly from the cache to disc.
2049 Most operations act directly on the text in the cache.
2050 A principle applied throughout
2051 .CW sam
2052 is that the fewer times the data is copied, the faster the program will run
2053 (see also the paper by Waite\u\s-4\&15\s+4\d).
2054 .KF
2055 .PS
2056 copy "fig5.pic"
2057 .PE
2058 .Cs
2059 Figure 5. File data structures.
2060 The temporary files are stored in the standard repository for such files
2061 on the host system.
2062 .Ce
2063 .KE
2064 .PP
2065 The contents of a
2066 .CW File
2067 are accessed by a routine that
2068 copies to a buffer a substring of a file starting at a specified offset.
2069 To read a byte at a time, a
2070 .CW File "" per-
2071 array is loaded starting from a specified initial position,
2072 and bytes may then be read from the array.
2073 The implementation is done by a macro similar to the C standard I/O
2074 .CW getc
2075 macro.\u\s-4\&14\s+4\d
2076 Because the reading may be done at any address, a minor change to the
2077 macro allows the file to be read backwards.
2078 This array is read-only; there is no
2079 .CW putc .
2080 .SH 2
2081 Doing and undoing
2082 .LP
2083 .CW Sam
2084 has an unusual method for managing changes to files.
2085 The command language makes it easy to specify multiple variable-length changes
2086 to a file millions of bytes long, and such changes
2087 must be made efficiently if the editor is to be practical.
2088 The usual techniques for inserting and deleting strings
2089 are inadequate under these conditions.
2090 The
2091 .CW Buffer
2092 and
2093 .CW Disc
2094 data structures are designed for efficient random access to long strings,
2095 but care must be taken to avoid super-linear behavior when making
2096 many changes simultaneously.
2097 .PP
2098 .CW Sam
2099 uses a two-pass algorithm for making changes, and treats each file as a database
2100 against which transactions are registered.
2101 Changes are not made directly to the contents.
2102 Instead, when a command is started, a `mark' containing
2103 a sequence number is placed in the transcript
2104 .CW Buffer ,
2105 and each change made to the file, either an insertion or deletion
2106 or a change to the file name,
2107 is appended to the end of the transcript.
2108 When the command is complete, the transcript is rewound to the
2109 mark and applied to the contents.
2110 .PP
2111 One reason for separating evaluation from
2112 application in this way is to simplify tracking the addresses of changes
2113 made in the middle of a long sequence.
2114 The two-pass algorithm also allows all changes to apply to the
2115 .I original
2116 data: no change can affect another change made in the same command.
2117 This is particularly important when evaluating an
2118 .CW x
2119 command because it prevents regular expression matches
2120 from stumbling over changes made earlier in the execution.
2121 Also, the two-pass
2122 algorithm is cleaner than the way other UNIX editors allow changes to
2123 affect each other;
2124 for example,
2125 .CW ed 's
2126 idioms to do things like delete every other line
2127 depend critically on the implementation.
2128 Instead,
2129 .CW sam 's
2130 simple model, in which all changes in a command occur effectively
2131 simultaneously, is easy to explain and to understand.
2132 .PP
2133 The records in the transcript are of the form ``delete substring from
2134 locations
2135 123 to 456'' and ``insert 11 characters `hello there' at location 789.''
2136 (It is an error if the changes are not at monotonically greater
2137 positions through the file.)
2138 While the update is occurring, these numbers must be
2139 offset by earlier changes, but that is straightforward and
2140 local to the update routine;
2141 moreover, all the numbers have been computed
2142 before the first is examined.
2143 .PP
2144 Treating the file as a transaction system has another advantage:
2145 undo is trivial.
2146 All it takes is to invert the transcript after it has been
2147 implemented, converting insertions
2148 into deletions and vice versa, and saving them in a holding
2149 .CW Buffer .
2150 The `do' transcript can then be deleted from
2151 the transcript
2152 .CW Buffer
2153 and replaced by the `undo' transcript.
2154 If an undo is requested, the transcript is rewound and the undo transcript
2155 executed.
2156 Because the transcript
2157 .CW Buffer
2158 is not truncated after each command, it accumulates
2159 successive changes.
2160 A sequence of undo commands
2161 can therefore back up the file arbitrarily,
2162 which is more helpful than the more commonly implemented self-inverse form of undo.
2163 .CW Sam "" (
2164 provides no way to undo an undo, but if it were desired,
2165 it would be easy to provide by re-interpreting the `do' transcript.)
2166 Each mark in the transcript contains a sequence number and the offset into
2167 the transcript of the previous mark, to aid in unwinding the transcript.
2168 Marks also contain the value of dot and the modified bit so these can be
2169 restored easily.
2170 Undoing multiple files is easy; it merely demands undoing all files whose
2171 latest change has the same sequence number as the current file.
2172 .PP
2173 Another benefit of having a transcript is that errors encountered in the middle
2174 of a complicated command need not leave the files in an intermediate state.
2175 By rewinding the transcript to the mark beginning the command,
2176 the partial command can be trivially undone.
2177 .PP
2178 When the update algorithm was first implemented, it was unacceptably slow,
2179 so a cache was added to coalesce nearby changes,
2180 replacing multiple small changes by a single larger one.
2181 This reduced the number
2182 of insertions into the transaction
2183 .CW Buffer ,
2184 and made a dramatic improvement in performance,
2185 but made it impossible
2186 to handle changes in non-monotonic order in the file; the caching method
2187 only works if changes don't overlap.
2188 Before the cache was added, the transaction could in principle be sorted
2189 if the changes were out of order, although
2190 this was never done.
2191 The current status is therefore acceptable performance with a minor
2192 restriction on global changes, which is sometimes, but rarely, an annoyance.
2193 .PP
2194 The update algorithm obviously paws the data more than simpler
2195 algorithms, but it is not prohibitively expensive;
2196 the caches help.
2197 (The principle of avoiding copying the data is still honored here,
2198 although not as piously:
2199 the data is moved from contents' cache to
2200 the transcript's all at once and through only one internal buffer.)
2201 Performance figures confirm the efficiency.
2202 To read from a dead start a hundred kilobyte file on a VAX-11/750
2203 takes 1.4 seconds of user time, 2.5 seconds of system time,
2204 and 5 seconds of real time.
2205 Reading the same file in
2206 .CW ed
2207 takes 6.0 seconds of user time, 1.7 seconds of system time,
2208 and 8 seconds of real time.
2209 .CW Sam
2210 uses about half the CPU time.
2211 A more interesting example is the one stated above:
2212 inserting a character between every pair of characters in the file.
2213 The
2214 .CW sam
2215 command is
2216 .P1
2217 ,y/@/ a/x/
2218 .P2
2219 and takes 3 CPU seconds per kilobyte of input file, of which
2220 about a third is spent in the regular expression code.
2221 This translates to about 500 changes per second.
2222 .CW Ed
2223 takes 1.5 seconds per kilobyte to make a similar change (ignoring newlines),
2224 but cannot undo it.
2225 The same example in
2226 .CW ex ,\u\s-4\&9\s+4\d
2227 a variant of
2228 .CW ed
2229 done at the University of California at Berkeley,
2230 which allows one level of undoing, again takes 3 seconds.
2231 In summary,
2232 .CW sam 's
2233 performance is comparable to that of other UNIX editors, although it solves
2234 a harder problem.
2235 .SH 2
2236 Communications
2237 .LP
2238 The discussion so far has described the implementation of the host part of
2239 .CW sam ;
2240 the next few sections explain how a machine with mouse and bitmap display
2241 can be engaged to improve interaction.
2242 .CW Sam
2243 is not the first editor to be written as two processes,\u\s-4\&16\s+4\d
2244 but its implementation
2245 has some unusual aspects.
2246 .PP
2247 There are several ways
2248 .CW sam 's
2249 host and terminal parts may be connected.
2250 The first and simplest is to forgo the terminal part and use the host
2251 part's command language to edit text on an ordinary terminal.
2252 This mode is invoked by starting
2253 .CW sam
2254 with the
2255 .CW -d
2256 option.
2257 With no options,
2258 .CW sam
2259 runs separate host and terminal programs,
2260 communicating with a message protocol over the physical
2261 connection that joins them.
2262 Typically, the connection is an RS-232 link between a Blit
2263 (the prototypical display for
2264 .CW sam )
2265 and a host running
2266 the Ninth Edition of the UNIX operating system.\u\s-4\&8\s+4\d
2267 (This is the version of the system used in the Computing Sciences Research
2268 Center at AT&T Bell Laboratories [now Lucent Technologies, Bell Labs], where I work.  Its relevant
2269 aspects are discussed in the Blit paper.\u\s-4\&1\s+4\d)
2270 The implementation of
2271 .CW sam
2272 for the SUN computer runs both processes on the same machine and
2273 connects them by a pipe.
2274 .PP
2275 The low bandwidth of an RS-232 link
2276 necessitated the split between
2277 the two programs.
2278 The division is a mixed blessing:
2279 a program in two parts is much harder to write and to debug
2280 than a self-contained one,
2281 but the split makes several unusual configurations possible.
2282 The terminal may be physically separated from the host, allowing the conveniences
2283 of a mouse and bitmap display to be taken home while leaving the files at work.
2284 It is also possible to run the host part on a remote machine:
2285 .P1
2286 sam -r host
2287 .P2
2288 connects to the terminal in the usual way, and then makes a call
2289 across the network to establish the host part of
2290 .CW sam
2291 on the named machine.
2292 Finally, it cross-connects the I/O to join the two parts.
2293 This allows
2294 .CW sam
2295 to be run on machines that do not support bitmap displays;
2296 for example,
2297 .CW sam
2298 is the editor of choice on our Cray X-MP/24.
2299 .CW Sam
2300 .CW -r
2301 involves
2302 .I three
2303 machines: the remote host, the terminal, and the local host.
2304 The local host's job is simple but vital: it passes the data
2305 between the remote host and terminal.
2306 .PP
2307 The host and terminal exchange messages asynchronously
2308 (rather than, say, as remote procedure calls) but there is no
2309 error detection or correction
2310 because, whatever the configuration, the connection is reliable.
2311 Because the terminal handles mundane interaction tasks such as
2312 popping up menus and interpreting the responses, the messages are about
2313 data, not actions.
2314 For example, the host knows nothing about what is displayed on the screen,
2315 and when the user types a character, the message sent to the host says
2316 ``insert a one-byte string at location 123 in file 7,'' not ``a character
2317 was typed at the current position in the current file.''
2318 In other words, the messages look very much like the transaction records
2319 in the transcripts.
2320 .PP
2321 Either the host or terminal part of
2322 .CW sam
2323 may initiate a change to a file.
2324 The command language operates on the host, while typing and some
2325 mouse operations are executed directly in the terminal to optimize response.
2326 Changes initiated by the host program must be transmitted to the terminal,
2327 and
2328 vice versa.
2329 (A token is exchanged to determine which end is in control,
2330 which means that characters typed while a time-consuming command runs
2331 must be buffered and do not appear until the command is complete.)
2332 To maintain consistent information,
2333 the host and terminal track changes through a per-file
2334 data structure that records what portions of the file
2335 the terminal has received.
2336 The data structure, called a
2337 .CW Rasp
2338 (a weak pun: it's a file with holes)
2339 is held and updated by both the host and terminal.
2340 A
2341 .CW Rasp
2342 is a list of
2343 .CW Strings
2344 holding those parts of the file known to the terminal,
2345 separated by counts of the number of bytes in the interstices.
2346 Of course, the host doesn't keep a separate copy of the data (it only needs
2347 the lengths of the various pieces),
2348 but the structure is the same on both ends.
2349 .PP
2350 The
2351 .CW Rasp
2352 in the terminal doubles as a cache.
2353 Since the terminal keeps the text for portions of the file it has displayed,
2354 it need not request data from the host when revisiting old parts of the file
2355 or redrawing obscured windows, which speeds things up considerably
2356 over low-speed links.
2357 .PP
2358 It's trivial for the terminal to maintain its
2359 .CW Rasp ,
2360 because all changes made on the terminal apply to parts of the file
2361 already loaded there.
2362 Changes made by the host are compared against the
2363 .CW Rasp
2364 during the update sequence after each command.
2365 Small changes to pieces of the file loaded in the terminal
2366 are sent in their entirety.
2367 Larger changes, and changes that fall entirely in the holes,
2368 are transmitted as messages without literal data:
2369 only the lengths of the deleted and inserted strings are transmitted.
2370 When a command is completed, the terminal examines its visible
2371 windows to see if any holes in their
2372 .CW Rasps
2373 intersect the visible portion of the file.
2374 It then requests the missing data from the host,
2375 along with up to 512 bytes of surrounding data, to minimize
2376 the number of messages when visiting a new portion of the file.
2377 This technique provides a kind of two-level lazy evaluation for the terminal.
2378 The first level sends a minimum of information about
2379 parts of the file not being edited interactively;
2380 the second level waits until a change is displayed before
2381 transmitting the new data.
2382 Of course,
2383 performance is also helped by having the terminal respond immediately to typing
2384 and simple mouse requests.
2385 Except for small changes to active pieces of the file, which are
2386 transmitted to the terminal without negotiation,
2387 the terminal is wholly responsible for deciding what is displayed;
2388 the host uses the
2389 .CW Rasp
2390 only to tell the terminal what might be relevant.
2391 .PP
2392 When a change is initiated by the host,
2393 the messages to the terminal describing the change
2394 are generated by the routine that applies the transcript of the changes
2395 to the contents of the
2396 .CW File .
2397 Since changes are undone by the same update routine,
2398 undoing requires
2399 no extra code in the communications;
2400 the usual messages describing changes to the file are sufficient
2401 to back up the screen image.
2402 .PP
2403 The
2404 .CW Rasp
2405 is a particularly good example of the way caches are used in
2406 .CW sam .
2407 First, it facilitates access to the active portion of the text by placing
2408 the busy text in main memory.
2409 In so doing, it provides efficient access
2410 to a large data structure that does not fit in memory.
2411 Since the form of data is to be imposed by the user, not by the program,
2412 and because characters will frequently be scanned sequentially,
2413 files are stored as flat objects.
2414 Caches help keep performance good and linear when working with such
2415 data.
2416 .PP
2417 Second, the
2418 .CW Rasp
2419 and several of the other caches have some
2420 .I read-ahead;
2421 that is, the cache is loaded with more information than is needed for
2422 the job immediately at hand.
2423 When manipulating linear structures, the accesses are usually sequential,
2424 and read-ahead can significantly reduce the average time to access the
2425 next element of the object.
2426 Sequential access is a common mode for people as well as programs;
2427 consider scrolling through a document while looking for something.
2428 .PP
2429 Finally, like any good data structure,
2430 the cache guides the algorithm, or at least the implementation.
2431 The
2432 .CW Rasp
2433 was actually invented to control the communications between the host and
2434 terminal parts, but I realized very early that it was also a form of
2435 cache.  Other caches were more explicitly intended to serve a double
2436 purpose: for example, the caches in
2437 .CW Files
2438 that coalesce updates not only reduce traffic to the
2439 transcript and contents
2440 .CW Buffers ,
2441 they also clump screen updates so that complicated changes to the
2442 screen are achieved in
2443 just a few messages to the terminal.
2444 This saved me considerable work: I did not need to write special
2445 code to optimize the message traffic to the
2446 terminal.
2447 Caches pay off in surprising ways.
2448 Also, they tend to be independent, so their performance improvements
2449 are multiplicative.
2450 .SH 2
2451 Data structures in the terminal
2452 .LP
2453 The terminal's job is to display and to maintain a consistent image of
2454 pieces of the files being edited.
2455 Because the text is always in memory, the data structures are
2456 considerably simpler than those in the host part.
2457 .PP
2458 .CW Sam
2459 typically has far more windows than does
2460 .CW mux ,
2461 the window system within which its Blit implementation runs.
2462 .CW Mux
2463 has a fairly small number of asynchronously updated windows;
2464 .CW sam
2465 needs a large number of synchronously updated windows that are
2466 usually static and often fully obscured.
2467 The different tradeoffs guided
2468 .CW sam
2469 away from the memory-intensive implementation of windows, called
2470 .CW Layers ,\u\s-4\&17\s+4\d
2471 used in
2472 .CW mux.
2473 Rather than depending on a complete bitmap image of the display for each window,
2474 .CW sam
2475 regenerates the image from its in-memory text
2476 (stored in the
2477 .CW Rasp )
2478 when necessary, although it will use such an image if it is available.
2479 Like
2480 .CW Layers ,
2481 though,
2482 .CW sam
2483 uses the screen bitmap as active storage in which to update the image using
2484 .CW bitblt .\u\s-4\&18,19\s+4\d
2485 The resulting organization, pictured in Figure 6,
2486 has a global array of windows, called
2487 .CW Flayers ,
2488 each of which holds an image of a piece of text held in a data structure
2489 called a
2490 .CW Frame ,
2491 which in turn represents
2492 a rectangular window full of text displayed in some
2493 .CW Bitmap .
2494 Each
2495 .CW Flayer
2496 appears in a global list that orders them all front-to-back
2497 on the display, and simultaneously as an element of a per-file array
2498 that holds all the open windows for that file.
2499 The complement in the terminal of the
2500 .CW File
2501 on the host is called a
2502 .CW Text ;
2503 each connects its
2504 .CW Flayers
2505 to the associated
2506 .CW Rasp .
2507 .KF
2508 .PS
2509 copy "fig6.pic"
2510 .PE
2511 .Cs
2512 Figure 6. Data structures in the terminal.
2513 .CW Flayers
2514 are also linked together into a front-to-back list.
2515 .CW Boxes
2516 are discussed in the next section.
2517 .Ce
2518 .KE
2519 .PP
2520 The
2521 .CW Bitmap
2522 for a
2523 .CW Frame
2524 contains the image of the text.
2525 For a fully visible window, the
2526 .CW Bitmap
2527 will be the screen (or at least the
2528 .CW Layer
2529 in which
2530 .CW sam
2531 is being run),
2532 while for partially obscured windows the
2533 .CW Bitmap
2534 will be off-screen.
2535 If the window is fully obscured, the
2536 .CW Bitmap
2537 will be null.
2538 .PP
2539 The
2540 .CW Bitmap
2541 is a kind of cache.
2542 When making changes to the display, most of the original image will
2543 look the same in the final image, and the update algorithms exploit this.
2544 The
2545 .CW Frame
2546 software updates the image in the
2547 .CW Bitmap
2548 incrementally; the
2549 .CW Bitmap
2550 is not just an image, it is a data structure.\u\s-4\&18,19\s+4\d
2551 The job of the software that updates the display is therefore
2552 to use as much as possible of the existing image (converting the
2553 text from ASCII characters to pixels is expensive) in a sort of two-dimensional
2554 string insertion algorithm.
2555 The details of this process are described in the next section.
2556 .PP
2557 The
2558 .CW Frame
2559 software has no code to support overlapping windows;
2560 its job is to keep a single
2561 .CW Bitmap
2562 up to date.
2563 It falls to the
2564 .CW Flayer
2565 software to multiplex the various
2566 .CW Bitmaps
2567 onto the screen.
2568 The problem of maintaining overlapping
2569 .CW Flayers
2570 is easier than for
2571 .CW Layers \u\s-4\&17\s+4\d
2572 because changes are made synchronously and because the contents of the window
2573 can be reconstructed from the data stored in the
2574 .CW Frame ;
2575 the
2576 .CW Layers
2577 software
2578 makes no such assumptions.
2579 In
2580 .CW sam ,
2581 the window being changed is almost always fully visible, because the current
2582 window is always fully visible, by construction.
2583 However, when multi-file changes are being made, or when
2584 more than one window is open on a file,
2585 it may be necessary to update partially obscured windows.
2586 .PP
2587 There are three cases: the window is 
2588 fully visible, invisible (fully obscured), or partially visible.
2589 If fully visible, the
2590 .CW Bitmap
2591 is part of the screen, so when the
2592 .CW Flayer
2593 update routine calls the
2594 .CW Frame
2595 update routine, the screen will be updated directly.
2596 If the window is invisible,
2597 there is no associated
2598 .CW Bitmap ,
2599 and all that is necessary is to update the
2600 .CW Frame
2601 data structure, not the image.
2602 If the window is partially visible, the
2603 .CW Frame
2604 routine is called to update the image in the off-screen
2605 .CW Bitmap ,
2606 which may require regenerating it from the text of the window.
2607 The
2608 .CW Flayer
2609 code then clips this
2610 .CW Bitmap
2611 against the
2612 .CW Bitmaps
2613 of all
2614 .CW Frames
2615 in front of the
2616 .CW Frame
2617 being modified, and the remainder is copied to the display.
2618 .PP
2619 This is much faster than recreating the image off-screen
2620 for every change, or clipping all the changes made to the image
2621 during its update.
2622 Unfortunately, these caches can also consume prohibitive amounts of
2623 memory, so they are freed fairly liberally \(em after every change to the
2624 front-to-back order of the
2625 .CW Flayers .
2626 The result is that
2627 the off-screen
2628 .CW Bitmaps
2629 exist only while multi-window changes are occurring,
2630 which is the only time the performance improvement they provide is needed.
2631 Also, the user interface causes fully-obscured windows to be the
2632 easiest to make \(em
2633 creating a canonically sized and placed window requires only a button click
2634 \(em which reduces the need for caching still further.
2635 .PP
2636 .SH 2
2637 Screen update
2638 .LP
2639 Only two low-level primitives are needed for incremental update:
2640 .CW bitblt ,
2641 which copies rectangles of pixels, and
2642 .CW string
2643 (which in turn calls
2644 .CW bitblt ),
2645 which draws a null-terminated character string in a
2646 .CW Bitmap .
2647 A
2648 .CW Frame
2649 contains a list of
2650 .CW Boxes ,
2651 each of which defines a horizontal strip of text in the window
2652 (see Figure 7).
2653 A
2654 .CW Box
2655 has a character string
2656 .CW str ,
2657 and a
2658 .CW Rectangle
2659 .CW rect
2660 that defines the location of the strip in the window.
2661 (The text in
2662 .CW str
2663 is stored in the
2664 .CW Box
2665 separately from the
2666 .CW Rasp
2667 associated with the window's file, so
2668 .CW Boxes
2669 are self-contained.)
2670 The invariant is that
2671 the image of the
2672 .CW Box
2673 can be reproduced by calling
2674 .CW string
2675 with argument
2676 .CW str
2677 to draw the string in
2678 .CW rect ,
2679 and the resulting picture fits perfectly within
2680 .CW rect .
2681 In other words, the
2682 .CW Boxes
2683 define the tiling of the window.
2684 The tiling may be complicated by long lines of text, which
2685 are folded onto the next line.
2686 Some editors use horizontal scrolling to avoid this complication,
2687 but to be comfortable this technique requires that lines not be
2688 .I too
2689 long;
2690 .CW sam
2691 has no such restriction.
2692 Also, and perhaps more importantly, UNIX programs and terminals traditionally fold
2693 long lines to make their contents fully visible.
2694 .PP
2695 Two special kinds of
2696 .CW Boxes
2697 contain a single
2698 character: either a newline or a tab.
2699 Newlines and tabs are white space.
2700 A newline
2701 .CW Box
2702 always extends to the right edge of the window,
2703 forcing the following
2704 .CW Box
2705 to the next line.
2706 The width of a tab depends on where it is located:
2707 it forces the next
2708 .CW Box
2709 to begin at a tab location.
2710 Tabs also
2711 have a minimum width equivalent to a blank (blanks are
2712 drawn by
2713 .CW string
2714 and are not treated specially); newlines have a minimum width of zero.
2715 .KF
2716 .PS
2717 copy "fig7.pic"
2718 .PE
2719 .sp .5
2720 .Cs
2721 Figure 7. A line of text showing its
2722 .CW Boxes .
2723 The first two blank
2724 .CW Boxes
2725 contain tabs; the last contains a newline.
2726 Spaces are handled as ordinary characters.
2727 .Ce
2728 .KE
2729 .PP
2730 The update algorithms always use the
2731 .CW Bitmap
2732 image of the text (either the display or cache
2733 .CW Bitmap );
2734 they never examine the characters within a
2735 .CW Box
2736 except when the
2737 .CW Box
2738 needs to be split in two.
2739 Before a change, the window consists of a tiling of
2740 .CW Boxes ;
2741 after the change the window is tiled differently.
2742 The update algorithms rearrange the tiles in place, without
2743 backup storage.
2744 The algorithms are not strictly optimal \(em for example, they can
2745 clear a pixel that is later going to be written upon \(em
2746 but they never move a tile that doesn't need to be moved,
2747 and they move each tile at most once.
2748 .CW Frinsert
2749 on a Blit can absorb over a thousand characters a second if the strings
2750 being inserted are a few tens of characters long.
2751 .PP
2752 Consider
2753 .CW frdelete .
2754 Its job is to delete a substring from a
2755 .CW Frame
2756 and restore the image of the
2757 .CW Frame .
2758 The image of a substring has a peculiar shape (see Figure 2) comprising
2759 possibly a partial line,
2760 zero or more full lines,
2761 and possibly a final partial line.
2762 For reference, call this the
2763 .I
2764 Z-shape.
2765 .R
2766 .CW Frdelete
2767 begins by splitting, if necessary, the
2768 .CW Boxes
2769 containing the ends of
2770 the substring so the substring begins and ends on
2771 .CW Box
2772 boundaries.
2773 Because the substring is being deleted, its image is not needed,
2774 so the Z-shape is then cleared.
2775 Then, tiles (that is, the images of
2776 .CW Boxes )
2777 are copied, using
2778 .CW bitblt ,
2779 from immediately after the Z-shape to
2780 the beginning of the Z-shape,
2781 resulting in a new Z-shape.
2782 .CW Boxes "" (
2783 whose contents would span two lines in the new position must first be split.)
2784 .PP
2785 Copying the remainder of the
2786 .CW Frame
2787 tile by tile
2788 this way will clearly accomplish the deletion but eventually,
2789 typically when the copying algorithm encounters a tab or newline,
2790 the old and new
2791 .CW x
2792 coordinates of the tile
2793 to be copied are the same.
2794 This correspondence implies
2795 that the Z-shape has its beginning and ending edges aligned
2796 vertically, and a sequence of at most two
2797 .CW bitblts
2798 can be used to copy the remaining tiles.
2799 The last step is to clear out the resulting empty space at the bottom
2800 of the window;
2801 the number of lines to be cleared is the number of complete lines in the
2802 Z-shape closed by the final
2803 .CW bitblts.
2804 The final step is to merge horizontally adjacent
2805 .CW Boxes
2806 of plain text.
2807 The complete source to
2808 .CW frdelete
2809 is less than 100 lines of C.
2810 .PP
2811 .CW frinsert
2812 is more complicated because it must do four passes:
2813 one to construct the
2814 .CW Box
2815 list for the inserted string,
2816 one to reconnoitre,
2817 one to copy (in opposite order to
2818 .CW frdelete )
2819 the
2820 .CW Boxes
2821 to make the hole for the new text,
2822 and finally one to copy the new text into place.
2823 Overall, though,
2824 .CW frinsert
2825 has a similar flavor to
2826 .CW frdelete ,
2827 and needn't be described further.
2828 .CW Frinsert
2829 and its subsidiary routines comprise 211 lines of C.
2830 .PP
2831 The terminal source code is 3024 lines of C,
2832 and the host source is 5797 lines.
2833 .SH
2834 Discussion
2835 .SH 2
2836 History
2837 .LP
2838 The immediate ancestor of
2839 .CW sam
2840 was the original text editor for the Blit, called
2841 .CW jim .
2842 .CW Sam
2843 inherited
2844 .CW jim 's
2845 two-process structure and mouse language almost unchanged, but
2846 .CW jim
2847 suffered from several drawbacks that were addressed in the design of
2848 .CW sam .
2849 The most important of these was the lack of a command language.
2850 Although
2851 .CW jim
2852 was easy to use for simple editing, it provided no direct help with
2853 large or repetitive editing tasks.  Instead, it provided a command to pass
2854 selected text through a shell pipeline,
2855 but this was no more satisfactory than could be expected of a stopgap measure.
2856 .PP
2857 .CW Jim
2858 was written primarily as a vehicle for experimenting with a mouse-based
2859 interface to text, and the experiment was successful.
2860 .CW Jim
2861 had some spin-offs:
2862 .CW mux ,
2863 the second window system for the Blit, is essentially a multiplexed
2864 version of the terminal part of
2865 .CW jim ;
2866 and the debugger
2867 .CW pi 's
2868 user interface\u\s-4\&20\s+4\d was closely modeled on
2869 .CW jim 's.
2870 But after a couple of years,
2871 .CW jim
2872 had become difficult to maintain and limiting to use,
2873 and its replacement was overdue.
2874 .PP
2875 I began the design of
2876 .CW sam
2877 by asking
2878 .CW jim
2879 customers what they wanted.
2880 This was probably a mistake; the answers were essentially a list of features
2881 to be found in other editors, which did not provide any of the
2882 guiding principles I was seeking.
2883 For instance, one common request was for a ``global substitute,''
2884 but no one suggested how to provide it within a cut-and-paste editor.
2885 I was looking for a scheme that would
2886 support such specialized features comfortably in the context of some
2887 general command language.
2888 Ideas were not forthcoming, though, particularly given my insistence
2889 on removing all limits on file sizes, line lengths and so on.
2890 Even worse, I recognized that, since the mouse could easily
2891 indicate a region of the screen that was not an integral number of lines,
2892 the command language would best forget about newlines altogether,
2893 and that meant the command language had to treat the file as a single
2894 string, not an array of lines.
2895 .PP
2896 Eventually, I decided that thinking was not getting me very far and it was
2897 time to try building.
2898 I knew that the terminal part could be built easily \(em
2899 that part of
2900 .CW jim
2901 behaved acceptably well \(em and that most of the hard work was going
2902 to be in the host part: the file interface, command interpreter and so on.
2903 Moreover, I had some ideas about how the architecture of
2904 .CW jim
2905 could be improved without destroying its basic structure, which I liked
2906 in principle but which hadn't worked out as well as I had hoped.
2907 So I began by designing the file data structure,
2908 starting with the way
2909 .CW jim
2910 worked \(em comparable to a single structure merging
2911 .CW Disc
2912 and
2913 .CW Buffer ,
2914 which I split to make the cache more general
2915 \(em and thinking about how global substitute could be implemented.
2916 The answer was clearly that it had to be done in two passes,
2917 and the transcript-oriented implementation fell out naturally.
2918 .PP
2919 .CW Sam
2920 was written bottom-up,
2921 starting from the data structures and algorithms for manipulating text,
2922 through the command language and up to the code for maintaining
2923 the display.
2924 In retrospect, it turned out well, but this implementation method is
2925 not recommended in general.
2926 There were several times when I had a large body of interesting code
2927 assembled and no clue how to proceed with it.
2928 The command language, in particular, took almost a year to figure out,
2929 but can be implemented (given what was there at the beginning of that year)
2930 in a day or two.  Similarly, inventing the
2931 .CW Rasp
2932 data structure delayed the
2933 connection of the host and terminal pieces by another few months.
2934 .CW Sam
2935 took about two years to write, although only about four months were
2936 spent actually working on it.
2937 .PP
2938 Part of the design process was unusual:
2939 the subset of the protocol that maintains the
2940 .CW Rasp
2941 was simulated, debugged
2942 and verified by an automatic protocol analyzer,\u\s-4\&21\s+4\d and was bug-free
2943 from the start.
2944 The rest of the protocol, concerned mostly
2945 with keeping menus up to date,
2946 was unfortunately too unwieldy for such analysis,
2947 and was debugged by more traditional methods, primarily
2948 by logging in a file all messages in and out of the host.
2949 .SH 2
2950 Reflections
2951 .LP
2952 .CW Sam
2953 is essentially the only interactive editor used by the sixty or so members of
2954 the computing science research center in which I work.
2955 The same could not be said of
2956 .CW jim ;
2957 the lack of a command language kept some people from adopting it.
2958 The union of a user interface as comfortable as
2959 .CW jim 's
2960 with a command language as powerful as
2961 .CW ed 's†
2962 .FS
2963 .vs 9
2964 †The people who criticize
2965 .CW ed
2966 as an interactive program often forget that it and its close relative
2967 .CW sed \u\s-4\&7\s+4\d
2968 still thrive as programmable editors.  The strength of these programs is
2969 independent of their convenience for interactive editing.
2970 .br
2971 .vs
2972 .FE
2973 is essential to
2974 .CW sam 's
2975 success.
2976 When
2977 .CW sam
2978 was first made available to the
2979 .CW jim
2980 community,
2981 almost everyone switched to it within two or three days.
2982 In the months that followed, even people who had never adopted
2983 .CW jim
2984 started using
2985 .CW sam
2986 exclusively.
2987 .PP
2988 To be honest,
2989 .CW ed
2990 still gets occasional use, but usually when
2991 something quick needs to be done and the overhead of
2992 downloading the terminal part of
2993 .CW sam
2994 isn't worth the trouble.
2995 Also, as a `line' editor,
2996 .CW sam
2997 .CW -d
2998 is a bit odd;
2999 when using a good old ASCII terminal, it's comforting to have
3000 a true line editor.
3001 But it is fair to say that
3002 .CW sam 's
3003 command language has displaced
3004 .CW ed 's
3005 for most of the complicated editing that has kept line editors
3006 (that is, command-driven editors) with us.
3007 .PP
3008 .CW Sam 's
3009 command language is even fancier than
3010 .CW ed 's,
3011 and most
3012 .CW sam
3013 customers don't come near to using all its capabilities.
3014 Does it need to be so sophisticated?
3015 I think the answer is yes, for two reasons.
3016 .PP
3017 First, the
3018 .I model
3019 for
3020 .CW sam 's
3021 command language is really relatively simple, and certainly simpler than that of
3022 .CW ed .
3023 For instance, there is only one kind of textual loop in
3024 .CW sam
3025 \(em the
3026 .CW x
3027 command \(em
3028 while
3029 .CW ed
3030 has three (the
3031 .CW g
3032 command, the global flag on substitutions, and the implicit loop over
3033 lines in multi-line substitutions).
3034 Also,
3035 .CW ed 's
3036 substitute command is necessary to make changes within lines, but in
3037 .CW sam
3038 the
3039 .CW s
3040 command is more of a familiar convenience than a necessity;
3041 .CW c
3042 and
3043 .CW t
3044 can do all the work.
3045 .PP
3046 Second,
3047 given a community that expects an editor to be about as powerful as
3048 .CW ed ,
3049 it's hard to see how
3050 .CW sam
3051 could really be much simpler and still satisfy that expectation.
3052 People want to do ``global substitutes,'' and most are content
3053 to have the recipe for that and a few other fancy changes.
3054 The sophistication of the command language is really just a veneer
3055 over a design that makes it possible to do global substitutes
3056 in a screen editor.
3057 Some people will always want something more, however, and it's gratifying to
3058 be able to provide it.
3059 The real power of
3060 .CW sam 's
3061 command language comes from composability of the operators, which is by
3062 nature orthogonal to the underlying model.
3063 In other words,
3064 .CW sam
3065 is not itself complex, but it makes complex things possible.
3066 If you don't want to do anything complex, you can ignore the
3067 complexity altogether, and many people do so.
3068 .PP
3069 Sometimes I am asked the opposite question: why didn't I just make
3070 .CW sam
3071 a real programmable editor, with macros and variables and so on?
3072 The main reason is a matter of taste: I like the editor
3073 to be the same every time I use it.
3074 There is one technical reason, though:
3075 programmability in editors is largely a workaround for insufficient
3076 interactivity.
3077 Programmable editors are used to make particular, usually short-term,
3078 things easy to do, such as by providing shorthands for common actions.
3079 If things are generally easy to do in the first place,
3080 shorthands are not as helpful.
3081 .CW Sam
3082 makes common editing operations very easy, and the solutions to
3083 complex editing problems seem commensurate with the problems themselves.
3084 Also, the ability to edit the
3085 .CW sam
3086 window makes it easy to repeat commands \(em it only takes a mouse button click
3087 to execute a command again.
3088 .SH 2
3089 Pros and cons
3090 .LP
3091 .CW Sam
3092 has several other good points,
3093 and its share of problems.
3094 Among the good things is the idea of
3095 structural regular expressions,
3096 whose usefulness has only begun to be explored.
3097 They were arrived at serendipitously when I attempted to distill the essence of
3098 .CW ed 's
3099 way of doing global substitution and recognized that the looping command in
3100 .CW ed
3101 was implicitly imposing a structure (an array of lines) on the file.
3102 .PP
3103 Another of
3104 .CW sam 's
3105 good things is its undo capability.
3106 I had never before used an editor with a true undo,
3107 but I would never go back now.
3108 Undo
3109 .I must
3110 be done well, but if it is, it can be relied on.
3111 For example,
3112 it's safe to experiment if you're not sure how to write some intricate command,
3113 because if you make a mistake, it can be fixed simply and reliably.
3114 I learned two things about undo from writing
3115 .CW sam :
3116 first, it's easy to provide if you design it in from the beginning, and
3117 second, it's necessary, particularly if the system has some subtle
3118 properties that may be unfamiliar or error-prone for users.
3119 .PP
3120 .CW Sam 's
3121 lack of internal limits and sizes is a virtue.
3122 Because it avoids all fixed-size tables and data structures,
3123 .CW sam
3124 is able to make global changes to files that some of our other
3125 tools cannot even read.
3126 Moreover, the design keeps the performance linear when doing such
3127 operations, although I must admit
3128 .CW sam
3129 does get slow when editing a huge file.
3130 .PP
3131 Now, the problems.
3132 Externally, the most obvious is that it is poorly integrated into the
3133 surrounding window system.
3134 By design, the user interface in
3135 .CW sam
3136 feels almost identical to that of
3137 .CW mux ,
3138 but a thick wall separates text in
3139 .CW sam
3140 from the programs running in
3141 .CW mux .
3142 For instance, the `snarf buffer' in
3143 .CW sam
3144 must be maintained separately from that in
3145 .CW mux .
3146 This is regrettable, but probably necessary given the unusual configuration
3147 of the system, with a programmable terminal on the far end of an RS-232 link.
3148 .PP
3149 .CW Sam
3150 is reliable; otherwise, people wouldn't use it.
3151 But it was written over such a long time, and has so many new (to me)
3152 ideas in it, that I would like to see it done over again to clean
3153 up the code and remove many of the lingering problems in the implementation.
3154 The worst part is in the interconnection of the host and terminal parts,
3155 which might even be able to go away in a redesign for a more
3156 conventional window system.
3157 The program must be split in two to use the terminal effectively,
3158 but the low bandwidth of the connection forces the separation to
3159 occur in an inconvenient part of the design if performance is to be acceptable.
3160 A simple remote procedure call
3161 protocol driven by the host, emitting only graphics
3162 commands, would be easy to write but wouldn't have nearly the
3163 necessary responsiveness.  On the other hand, if the terminal were in control
3164 and requested much simpler file services from the host, regular expression
3165 searches would require that the terminal read the entire file over its RS-232
3166 link, which would be unreasonably slow.
3167 A compromise in which either end can take control is necessary.
3168 In retrospect, the communications protocol should have been
3169 designed and verified formally, although I do not know of any tool
3170 that can adequately relate the protocol to
3171 its implementation.
3172 .PP
3173 Not all of
3174 .CW sam 's
3175 users are comfortable with its command language, and few are adept.
3176 Some (venerable) people use a sort of
3177 .CW ed \& ``
3178 subset'' of
3179 .CW sam 's
3180 command language,
3181 and even ask why
3182 .CW sam 's
3183 command language is not exactly
3184 .CW ed 's.
3185 (The reason, of course, is that
3186 .CW sam 's
3187 model for text does not include newlines, which are central to
3188 .CW ed .
3189 Making the text an array of newlines to the command language would
3190 be too much of a break from the seamless model provided by the mouse.
3191 Some editors, such as
3192 .CW vi ,
3193 are willing to make this break, though.)
3194 The difficulty is that
3195 .CW sam 's
3196 syntax is so close to
3197 .CW ed 's
3198 that people believe it
3199 .I should
3200 be the same.
3201 I thought, with some justification in hindsight,
3202 that making
3203 .CW sam
3204 similar to
3205 .CW ed
3206 would make it easier to learn and to accept.
3207 But I may have overstepped and raised the users'
3208 expectations too much.
3209 It's hard to decide which way to resolve this problem.
3210 .PP
3211 Finally, there is a tradeoff in
3212 .CW sam
3213 that was decided by the environment in which it runs:
3214 .CW sam
3215 is a multi-file editor, although in a different system there might instead be
3216 multiple single-file editors.
3217 The decision was made primarily because starting a new program in a Blit is
3218 time-consuming.
3219 If the choice could be made freely, however, I would
3220 still choose the multi-file architecture, because it allows
3221 groups of files to be handled as a unit;
3222 the usefulness of the multi-file commands is incontrovertible.
3223 It is delightful to have the source to an entire program
3224 available at your fingertips.
3225 .SH
3226 Acknowledgements
3227 .LP
3228 Tom Cargill suggested the idea behind the
3229 .CW Rasp
3230 data structure.
3231 Norman Wilson and Ken Thompson influenced the command language.
3232 This paper was improved by comments from
3233 Al Aho,
3234 Jon Bentley,
3235 Chris Fraser,
3236 Gerard Holzmann,
3237 Brian Kernighan,
3238 Ted Kowalski,
3239 Doug McIlroy
3240 and
3241 Dennis Ritchie.