.MH "Tutorial" .SH "Starting an Editing Session" We assume that you have successfully logged in to your computer and are running the Software Tools Subsystem. If you need assistance, see the .ul Software Tools Subsystem Tutorial. We further assume that you know how to use the character erase and line delete characters, so that you will have no trouble correcting typographical errors, and that you have some idea of what a "file" is. .pp Since you are in the Subsystem, the command interpreter should have just printed the prompt "]". To enter the text editor, type .be ] [bf ed] (followed by a newline) .ee (Throughout this guide, boldface is used to indicate information that you should type in. Things typed by 'ed' are shown in the regular font.) You are now in the editor, ready to go. Note that 'ed' does not print any prompting information; this quiet behavior is preferred by experienced users. (If you would like a prompt, it can be provided; try the command "op/prompt/".) .pp At this point, 'ed' is waiting for instructions from you. You can instruct 'ed' by using "commands," which are single letters (occasionally accompanied by other information, which you will see shortly). .SH "Entering Text - the Append Command" The first thing that you need is text to edit. Working with 'ed' is like working with a blank sheet of paper; you write on the paper, alter or add to what you have written, and either file the paper away for further use or throw it away. In 'ed's terminology, the blank sheet of paper you start with is called a "buffer." The buffer is empty when you start editing. All editing operations take place in the buffer; nothing you do can affect any file unless you make an explicit request to transfer the contents of the buffer to a file. .pp So the first problem reduces to finding a way to put text into the buffer. The "append" command is used to do this: .be [bf a] .ee This command appends (adds) text lines to the buffer, as they are typed in. .pp To put text into the buffer, simply type it in, terminating each line with a newline: .be 4 .bf 1000 The quick brown fox jumps over the lazy dog. . .bf 0 .ee To stop entering text, you must enter a line containing only a period, immediately followed by a newline, as in the last line above. This tells 'ed' that you are finished writing on the buffer, and are ready to do some editing. .pp The buffer now contains: .be 3 The quick brown fox jumps over the lazy dog. .ee Neither the append command nor the final period are included in the buffer -- just the text you typed in between them. .SH "Writing text on a file - the Write command" Now that you have some text in the buffer, you need to know how to save it. The write command "w" is used for this purpose. It is used like this: .be [bf w file] .ee where "file" is the name of the file used to store what you just typed in. The write command copies the contents of the buffer to the named file, destroying whatever was previously in the file. The buffer, however, remains intact; whatever you typed in is still there. To indicate that the transfer of data was successful, 'ed' types out the number of lines written. In this example, 'ed' would type: .be 3 .ee It is advisable to write the contents of the buffer out to a file periodically, to insure that you have an up-to-date version in case of some terrible catastrophe (like a system crash). .SH "Finishing up - the Quit command" Now that you have saved your text in a file, you may wish to leave the editor. The "quit" command "q" is provided for this: .be [bf q] .ee The next thing you see should be the "]" prompt from the Subsystem command interpreter. If you did not write out the contents of the buffer, the editor would respond: .be ? (not saved) .ee This is to remind you to write out the buffer, so that the results of your editing session are not lost. If you intended that the buffer be discarded, just enter "q" again and 'ed' will throw away the buffer and terminate. .pp When you receive the "]" prompt from the Subsystem command interpreter, the buffer has been thrown away; there is absolutely no way to recover it. If you wrote the contents of the buffer to a file, then this is of no concern; if you did not, it may mean disaster. .pp To check if the text you typed in is really in the file you wrote it to, try the following command: .be ] [bf cat file] .ee where "file" is the name of the file given with the "w" command. ("Cat" is a Subsystem command that can be used to print files on the terminal. If, for example, you wished to print your file on the line printer, you could say: .be ] [bf pr file] .ee and the contents of "file" would be queued for printing.) .SH "Reading files - the Enter command" Of course, most of the time you will not be entering text into the buffer for the first time. You need a way to fill the buffer with the contents of some file that already exists, so that you can modify it. This is the purpose of the "enter" command "e"; it enters the contents of a file into the buffer. To try out "enter," you must first get back into the editor: .be ] [bf ed] .ee "Enter" is used like this: .be [bf e file] .ee "File" is the name of a file to be read into the buffer. .pp Note that you are not restricted to editing files in the current directory; you may also edit files belonging to other users (provided they have given you permission). Files belonging to other users must be identified by their full "pathname" (discussed fully in [ul User's Guide to the Primos File System]). For example, to edit a file named "document" belonging to user "tom," you would enter the following command: .be e //tom/document .ee .pp After the file's contents are copied into the buffer, 'ed' prints the number of lines it read. In our example, the buffer would now contain: .be 3 The quick brown fox jumps over the lazy dog. .ee If anything at all is present in the buffer, the "e" command destroys it before reading the named file. .pp As a matter of convenience, 'ed' remembers the file name specified on the last "e" command, so you do not have to specify a file name on the "w" command. With these provisions, a common editing session looks like .be 5 ] [bf ed] [bf e file] {editing} [bf w] [bf q] .ee The "file" command ("f") is available for finding out the remembered file name. To print out the name, just type: .be [bf f] file .ee .pp You might also want to check that .be ] [bf ed file] .ee is exactly the same as .be ] [bf ed] [bf e file] .ee That is, 'ed' performs an "e" command for you if you give it a file name on the command line. .SH "Errors - the Query command" Occasionally, an error of some kind is encountered. Usually, these are caused by misspelled file names, although there are other possibilities. Whenever an error occurs, 'ed' types .be ? .ee Although this is rather cryptic, it is usually clear what caused the problem. If you need further explanation, just enter "?" and 'ed' responds with a one-line explanation of the error. For example, if the last command you typed was an "e" command, 'ed' is probably saying that it could not find the file you asked for. You can find out for sure by entering "?": .be 4 [bf e myfile] ? [bf ?] I can't open the file to read .ee Except for the messages in response to "?", 'ed' rarely gives other, more verbose error messages; if you should see one of these, the best course of action is to report it to whoever maintains the editor at your installation. .SH "Printing text - the Print command" You are likely to need to print the text you have typed to check it for accuracy. The "print" command "p" is available to do this. "P" is different from the commands seen thus far; "e", "w", and "a" have been seen to work on the whole buffer at once. For a small file, it might be easiest to print the entire buffer just to check on some few lines, but for very large files this is clearly impractical. The "p" command therefore accepts "line numbers" that indicate which lines to print. Try the following experiment: .be 13 ] [bf ed file] 3 [bf 1p] The quick brown fox [bf 3p] the lazy dog. [bf 1,2p] The quick brown fox jumps over [bf 1,3p] The quick brown fox jumps over the lazy dog. .ee "1p" tells 'ed' to print line 1 ("The quick brown fox"). "3p" says to print the third line ("the lazy dog."). "1,2p" tells 'ed' to print the first [ul through] the second lines, and "1,3p" says to print the first [ul through] the third lines. .pp Suppose we want to print the last line in the buffer, but we don't know what its number is. 'Ed' provides an abbreviation to specify the last line in the buffer: .be [bf $p] the lazy dog. .ee The dollar sign can be used just like a number. To print everything in the buffer, we could type: .be 4 [bf 1,$p] The quick brown fox jumps over the lazy dog. .ee .pp If for some reason you want to stop the printing before it is done, press the BREAK key on your terminal. If you receive no response from BREAK, 'ed' is waiting for you to enter a command. Otherwise, 'ed' responds with .be ? .ee and waits for your next command. .SH "More Complicated Line Numbers" 'Ed' has several ways to specify lines other than just numbers and "$". Try the following command: .be [bf p] the lazy dog. .ee 'Ed' prints the last line. Does 'ed' always print the last line when it is given an unadorned "p" command? No. The "p" command by itself prints the "current" line. The "current" line is the last line you have edited in any way. (As a matter of fact, the last thing we did was to print all the lines in the buffer, so the last line was edited by being printed.) 'Ed' allows you to use the symbol "." (read "dot") to represent the current line. Thus .be [bf .p] the lazy dog. .ee is the same as .be [bf .,.p] the lazy dog. .ee which is the same as just .be [bf p] the lazy dog. .ee .pp "." can be used in many ways. For example, .be 9 [bf 1,2p] The quick brown fox jumps over [bf 1,.p] The quick brown fox jumps over [bf .,$p] jumps over the lazy dog. .ee This example shows how to print all the lines up to the current line (1,.p) or all the lines from the current line to the end of the buffer (.,$p). If for some reason you would like to know the number of the current line, you can type .be [bf .=] 3 .ee and 'ed' displays the number. (Note that the last thing we did was to print the last line, so the current line became line 3.) .pp "." is not particularly useful when used alone. It becomes much more important when used in "line-number expressions." Try this experiment: .be [bf .-1p] jumps over .ee ".-1" means "the line that is one line before the current line." .be [bf .+1p] the lazy dog. .ee ".+1" means "the line that is one line after the current line." .be 3 [bf .-2,.-1p] The quick brown fox jumps over .ee ".-2,.-1p" means "print the lines from two lines before to one line before the current line." .pp You can also use "$" in line-number expressions: .be [bf $-1p] jumps over .ee "$-1p" means "print the line that is one line before the last line in the buffer, i.e., the next to the last line." .pp Some abbreviations are available to help reduce the amount of typing you have to do. Typing a newline by itself is equivalent to typing ".+1p"; [cc]mc | typing a caret, "^", or a single minus sign, "-", [cc]mc followed by a newline is equivalent to typing ".-1p"; and typing a line-number expression followed by a newline is equivalent to typing that line-number expression followed by "p". Examples: [cc]mc | .be 8 [cc]mc {type a newline by itself} the lazy dog. [bf ^] jumps over [cc]mc | [bf -] The quick brown fox [cc]mc [bf 1] The quick brown fox .ee .pp It might be worthwhile to note here that almost all commands expect line numbers of one form or another. If none are supplied, 'ed' uses default values. Thus, .be w file .ee is equivalent to .be 1,$w file .ee and .be a .ee is equivalent to .be .a .ee (which means, append text [ul after] the current line.) .SH "Deleting Lines" As yet, you have seen no way of removing lines that are no longer wanted or needed. To do this, use the "delete" command "d": .be 1,2d .ee deletes the first through the second lines. "D" expects line numbers that work in the same way as those specified for "p", deleting one line or any range of lines. .be d .ee deletes only the current line. It is the same as ".d" or ".,.d". .pp After a deletion, the current line pointer is left pointing to the first line [ul after] the group of deleted lines, unless the last line in the buffer was deleted. In this case, the current line is the last line [ul before] the group of deleted lines. .SH "Text Patterns" Frequently it is desirable to be able to find a particular "pattern" in a piece of text. For example, suppose that after proofreading a report you have typed in using 'ed' you find a spelling error. There must be an easy way to find the misspelled word in the file so it can be corrected. One way to do this is to count all the lines up to the line containing the error, so that you can give the line number of the offending line to 'ed'. Obviously, this way is not very fast or efficient. 'Ed' allows you to "search" for patterns of text (like words) by enclosing the pattern in slashes: .be [bf /jumps/] jumps over .ee 'Ed' looks for the pattern you specified, and moves to the first line which contains the pattern. Note that if we had typed .be [bf /jumped/] ? .ee 'ed' would inform us that it could not find the pattern we wanted. .pp 'Ed' searches [ul forward] from the current line when it attempts to find the pattern you specified. If 'ed' reaches the last line without seeing the pattern, it "wraps around" to the first line in the file and continues searching until it either finds the pattern or gets back to the line where it started (line "."). This procedure ensures that you get the "next" occurrence of the pattern you were looking for, and that you don't miss any occurrences because of your current position in the file. .pp Suppose, however, that you do not wish to find the "next" occurrence of a word, but the [ul previous] one instead. Very few text editors provide this capability; however, 'ed' makes it simple. Just surround the pattern with backslashes: .be [bf \quick\] The quick brown fox .ee Remember: [ul back]slashes search [ul back]ward. The backward search (or backscan, as it is sometimes called) wraps around the file in a manner similar to the forward search (or scan). The search begins at the line before the current line, proceeds until the first line of the file is seen, then begins at the last line of the file and searches up until the current line is encountered. Once again, this is to ensure that you do not miss any occurrences of a pattern due to your current position in the file. .pp [cc]mc | In pattern searches, and in other commands which we will get to later, 'ed' allows you to leave off the trailing the delimiter. I.e., instead of typing .be [bf /jumps/] .ee you can type .be [bf /jumps] .ee to search forward for the first occurrence of the pattern "jumps". Similarly, to search backwards, you may type .be [bf \quick] .ee instead of .be [bf \quick\] .ee This feature can save considerable time and frustration when you are doing some involved editing, and accidentally leave off the trailing delimiter ("/" or "\"). The rest of this guide will continue to use examples with the trailing delimiter, but you do not have to in your actual editing. .pp [cc]mc 'Ed' also provides more powerful pattern matching services than simply looking for a given string of characters. (A note to beginning users: this section may seem fairly complicated at first, and indeed you do not really need to understand it completely for effective use of the editor. However, the results you might get from some patterns would be mystifying if you were not provided with some explanation, so look this over once and move on.) .pp The pattern that may appear within slashes (or backslashes) is called a "regular expression." It contains characters to look for and special characters used to perform other operations. The following characters .be % ? $ [ * @ { .ee have special meaning to 'ed': .ta 6 .in +10 .HI 5 % Beginning of line. The "%" character appearing as the first element in a pattern matches the beginning of a line. It is most frequently used to locate lines with some string at the very beginning; for example, .be /%The/ .ee finds the next line that begins with the word "The". The percent sign has its special meaning .ul only if it is the first element of the pattern; otherwise, it is treated as a literal percent sign. .ne 14 .HI 5 ? Any character. The question mark "?" in a regular expression matches [ul any] character (except a beginning-of-line or a newline). It can be used like this: .be /a?b/ .ee to find strings like .be 4 a+b a-b a b arbitrary .ee However, "?" is most often used with the "closure" operator "*" (see below). .HI 5 $ End of line. The dollar sign appearing as the last element of a pattern matches the newline character at the end of a line. Thus, .be /today$/ .ee can be used to find a line with the word "today" at the very end. Like the percent sign, the dollar sign has no special meaning in positions other than the end of a pattern. .HI 5 [] Character classes. The square brackets are used to match "classes" of characters. For example, .be /[A-Z]/ .ee finds the next line containing a capital letter, .be /%[abcxyz]/ .ee finds the next line beginning with an a, b, c, x, y, or z, and .be /[~0-9]/ .ee finds the next line which contains a non-digit. Character classes are also frequently used with the "closure" operator "*". .HI 5 * Closure. The asterisk is used to mean "any number of repetitions (including zero) of the previous pattern element (one character or a character class in brackets)." Thus, .be /a?*b/ .ee finds lines containing an "a" followed by any number of characters and a "b". For example, the following lines are matched: .be ab abnormal Recording Media, by Dr. Joseph P. Gunchy .ee As another example, .be /%=*$/ .ee matches only those lines containing all equal-signs (or nothing at all). If you wish to ensure that only non-empty lines are matched, use .be /%==*$/ .ee Always remember that "*" (closure) matches [ul zero] or more repetitions of an element. .HI 5 @@ Escape. The "at" sign has special meaning to 'ed'. It is the "escape" character, which is used to prevent interpretation of a special character which follows. Suppose you wish to locate a line containing the string "a * b". You may use the following command: .be /a @@* b/ .ee The "at" sign "turns off" the special meaning of the asterisk, so it can be used as an ordinary text character. You may have occasion to escape any of the regular expression metacharacters (%, ?, $, [, *, @@, or {) or the slash itself. For example, suppose you wished to find the next occurrence of the string "1/2". The command you need is: .be /1@@/2/ .ee .HI 5 {} Pattern tags. As seen in the next section, it is sometimes useful to remember what part of a line was actually matched by a pattern. By default, the string matched by the entire pattern is remembered. It is also possible to remember a string that was matched by only a part of a pattern by enclosing that part of the pattern in braces. Hence to find the next line that contains a quoted string and remember the text between the quotes, we might use .be /"{?*}"/ .ee If the line thus located looked like this .be This is a line containing a "quoted string". .ee then the text remembered as matching the tagged part of the pattern would be .be quoted string .ee .in -10 .pp The last important thing you need to know about patterns is the use of the "default" pattern. 'Ed' remembers the last pattern used in any command, to save you the trouble of retyping it. To access the remembered pattern, simply use an "empty" string. For example, the following sequence of commands could be used to step through a file, looking for each occurrence of the string "ICS": .be 4 /ICS/ // // (and so on) .ee .pp One last comment before leaving pattern searching. The constructs .be /pattern/ \pattern\ .ee are not separate commands; they are components of line number expressions. Thus, to print the line after the next line containing "tape", you could say .be /tape/+1p .ee Or, to print a range of lines from one before to one after a line with a given pattern, you could use .be /pattern/-1,/pattern/+1p .ee .SH "Making Substitutions - the Substitute command" This is one of the most used editor commands. The "substitute" command "s" is used to make small changes within lines, without retyping them completely. It is used like this: .be [cc]mc | starting-line,ending-line s [/pattern/new-stuff[/]] [cc]mc .ee For instance, suppose our buffer looks like this: .be 4 [bf 1,$p] The quick brown fox jumps over the lazy dog. .ee To change "jumps" to "jumped," .be [bf 2s/jumps/jumped/p] jumped over .ee Note the use of the trailing "p" to print the result. If the "p" had been omitted, the change would have been performed (in the buffer) but the changed line would not have been printed out. .pp If the last string specified in the substitute command is empty, then the text matching the pattern is deleted: .be 4 [bf s/jumped//p] over [bf s/% */ jumps /p] jumps over .ee Recalling that a missing pattern means "use the last pattern specified," try to explain what the following commands do: .be 4 [bf s///p] jumps over [bf s// /p] jumps over .ee (Note that, like many other commands, the substitute command assumes you want to work on the current line if you do not specify any line numbers.) .pp What if you want to change "over" into "over and over"? You might use .be [bf s/over/over and over/p] jumps over and over .ee to accomplish this. There is a shorthand notation for this kind of substitution that was alluded to briefly in the last section. (Recall the discussion of "tagged" patterns.) By default, the part of a line that was matched by the whole pattern is remembered. This string can then be included in the replacement string by typing an ampersand ("&") in the desired position. So, instead of the command in the last example, .be s/over/& and &/ .ee could have been used to get the same result. If a portion of the pattern had been tagged, the text matched by the tagged part in the replacement could be reused by typing "@@1": .be .bf s/jump{?*}/vault@@1/p vaults over and over .ee It is possible to tag up to nine parts of a pattern using braces. The text matched by each tagged part may then be used in a replacement string by typing .be @@n .ee where n corresponds to the nth "{" in the pattern. What does the following command do? .be s/{[~ ]*} {?*}/@@2 @@1/ .ee .pp [cc]mc | Some more words on substitute: the slashes are known as "delimiters" and [cc]mc may be replaced by any other character except a newline, as long as the same character is used consistently throughout the command. Thus, .be [bf s#vaults#vaulted#p] vaulted over and over .ee is legal. Also, note that substitute changes only the first occurrence of the pattern that it finds; if you wish to change all occurrences on a line, you may append a "g" (for "global") to the command, like this: .be [bf s/ /*/gp] ****vaulted*over*and*over .ee [cc]mc | In the replacement part of a substitute command, the character "&", .ul as the only character in the pattern, means "the replacement part of the previous substitute command". (This allows an empty replacement pattern as well.) Thus, to step through the buffer, and change selected occurrences of one pattern into another, you might do the following: .be [bf /pat1/] Line containing pat1. [bf s/pat1/stuff1/p] Line containing stuff1. [bf //] Another line with pat1. [bf //] Yet another line with pat1. [bf s//&/p] Yet another line with stuff1. .ee You may leave off the trailing delimiter in the substitute command. This will cause 'ed' to print out the changed line. I.e., "s/stuff/junk" is the same as "s/stuff/junk/p". .be [bf /quick/] The quick brown fox [bf s/quick/really fast] The really fast brown fox .ee If you wish to delete an occurrence of a pattern, you may leave it off. 'Ed' will delete the pattern, and then print the line. In other words, "s/stuff" is the same as "s/stuff//p". .be [bf p] The quick brown fox [bf s/quick] The brown fox .ee Finally, you may leave off the search pattern and replacement string entirely. If you do, 'ed' will behave as though you had typed "s//&/p", in other words, substitute the previous replacement pattern for the previous search pattern, and print. .be [bf 1,$d] [bf a] [bf line 1] [bf line 2] [bf .] [bf 1s/line/this is &/p] this is line 1 [bf 2s] this is line 2 .ee This can save considerable typing. .SH "Line Changes, Insertions, and Concatenations" [cc]mc Two "abbreviation" commands are available to shorten common operations applying to changes of entire lines. These are the "change" command "c" and the "insert" command "i". .pp The change command is a combination of delete and append. Its format is .be starting-line,ending-line c .ee This command deletes the given range of lines, and then goes into append mode to obtain text to replace them. Append mode works exactly the same way as it does for the "a" command; input is terminated by a period standing alone on a line. Examine the following editing session to see how change might be used: .be 9 .bf 1000 1,$c Ed is an interactive program used for the creation and modification of "text. . c the creation and modification of "text." "Text" may be any collection of character data. . .bf 0 .ee As you can see, the current line is set to the last line entered in append mode. .pp The other abbreviation command is "i". "I" is very closely related to "a"; in fact, the following relation holds: .be starting-line i .ee is the same as .be starting-line - 1 a .ee In short, "i" inserts text [ul before] the specified line, whereas "a" inserts text [ul after] the specified line. [cc]mc | .pp The join command "j" can be used to put two or more lines together into a single line. It works like this: .be starting-line,ending-line j[/string[/]] .ee The defaults for starting-line and ending-line are "^" and "." respectively, that is, "join the line before the current line to the current line". You may specify in "string" what is to replace the newline(s) which currently separate the lines which are to be joined. If you do not specify any string, 'ed' will replace the newline with a single blank. If you do specify a string, you may leave off the trailing delimiter (which can be any character), and 'ed' will print out the resulting joined line. An extended example should make this clear: .be [bf 1,$p] The quick brown fox jumps over the lazy dog. [bf 2,$s/% *//] [bf 1,$p] The quick brown fox jumps over the lazy dog. [bf 1,2j] The quick brown fox jumps over [bf 1,2j/ the back of /p] The quick brown fox jumps over the back of the lazy dog. .ee [cc]mc .SH "Moving Text" Throughout this guide, we have concentrated on what may be called "in-place" editing. The other type of editing commonly used is often called "cut-and-paste" editing. The move command "m" is provided to facilitate this kind of editing, and works like this: .be starting-line,ending-line m after-this-line .ee If you wanted to move the last fifty lines of a file to a point after the third line, the command would be .be $-49,$m3 .ee Any of the line numbers may, of course, be full expressions with search strings, arithmetic, etc. .pp You may, if you like, append a "p" to the move command to cause it to print the last line moved. The current line is set to the last line moved. .SH "Global Commands" The "global" command "g" is used to perform an editing command on all lines in the buffer that match a certain pattern. For example, to print all the lines containing the word "editor", you could type .be g/editor/p .ee If you wanted to correct some common spelling error, you would use .be g/old-stuff/s//new-stuff/gp .ee which makes the change in all appropriate lines and prints the resulting lines. Another example: deleting all lines that begin with an asterisk could be done this way: .be g/%@@*/d .ee .pp "G" has a companion command "x" (for "exclude") that performs an operation on all lines in the buffer that do .ul not match a given pattern. For example, to delete all lines that do .ul not begin with an asterisk, use .be x/%@@*/d .ee .pp "G" and "x" are very powerful commands that are essential for advanced usage, but are usually not necessary for beginners. Concentrate on other aspects of 'ed' before you move on to tackle global commands. .SH "Marking Lines" During some types of editing, especially when moving blocks of text, it is often necessary to refer to a line in the buffer that is far away from the current line. For instance, say you want to move a subroutine near the beginning of a file to somewhere near the end, but you aren't sure that you can specify patterns to properly locate the subroutine. One way to solve this problem is to find the first line of the subroutine, then use the command ".=": .be 4 [bf /subroutine/] subroutine think [bf .=] 47 .ee and write down (or remember) line 47. Then find the end of the subroutine and do the same thing: .be 4 [bf /end/] end [bf .=] 71 .ee Now you move to where you want to place the subroutine and enter the command .be [bf 47,71m.] .ee which does exactly what you want. .pp The problem here is that absolute line numbers are easily forgotten, easily mistyped, and difficult to find in the first place. It is much easier to have 'ed' remember a short "name" along with each line, and allow you to reference a line by its name. In practice, it seems convenient to restrict names to a single character, such as "b" or "e" (for "beginning" or "end"). It is not necessary for a given name to be uniquely associated with one line; many lines may bear the same name. In fact, at the beginning of the editing session, all lines are marked with the same name: a single space. .pp To return to our example, using the 'k' command, we can mark the beginning and ending lines of the subroutine quite easily: .be 6 [bf /subroutine/] subroutine think [bf kb] [bf /end/] end [bf ke] .ee We have now marked the first line in the subroutine with "b" and the second line with "e". .pp To refer to names, we need more line number expression elements: ">" and "<". Both work in line number expressions just like "$" or "/pattern/". The symbol ">" followed by a single character mark name means "the line number of the first line with this name when you search .ul forward". The symbol "<" followed by a single character mark name means "the line number of the first line with this name when you search .ul backward". (Just remember that '<' points backward and '>' points forward.) .pp Now in our example, once we locate the new destination of the subroutine, we can use "] .ee If present, the is passed to the shell to be executed. Otherwise, an interactive shell is created. After either the command or the shell exits, 'ed' prints a "~" to indicate that the shell escape has completed. If the first character of the is a "!", then the "!" is replaced with the text of the previous shell command. An unescaped "%" in the will be replaced with the current saved file name. If the shell command is expanded, 'ed' will echo it first, and then execute it. .pp This feature is useful when you want to temporarily stop editing and do something else, or find something out, without having write your file and leave the editor. .be {editing session} [bf ~lf -l %] lf -l file sam a/r 06/17/84 16:25:08 19463 sys file ~ .ee .pp For a deeper discussion of using the shell from within a program, see the help on the 'shell' subroutine. In particular, due to operating system constraints, you [ul must not] run another instance of the editor from the new shell, or you will end up clobbering your current edit buffer. .pp .bf WARNING: Until Prime supports EPFs, and the editor is reloaded in EPF format, you [ul must not] run any external commands (like 'lf') from a shell started from 'ed'. If you do, the new program will load [ul over] 'ed', and wipe out your current editing session. You can use commands which are internal to the shell (like 'cd'), without any ill effect. This restriction, for various arcane reasons, does [ul not] apply to the Subsystem screen editor, 'se'. .# and who uses 'ed' any more, anyway? .pp In essence, this feature is provided in the editor with an eye to the future. .# These last two paragraphs should be deleted when EPFs are supported. [cc]mc .SH "Summary" This concludes our tour through the world of text editing. In the section that follows, you will find a brief introduction to the Software Tools Subsystem screen editor 'se', which supports all of the line-oriented commands of 'ed' as well as full screen editing capabilities, while giving you a "window" into your edit buffer. Following that, we have included for your convenience a short summary of all available line editing commands supported by 'ed' and 'se', many of which were not discussed in this introduction, but which you will undoubtedly find useful.