5 Managing Large Systems
Hemlock provides three tools which help to manage large systems:
- File groups, which provide several commands that operate on all the files in a possibly large collection, instead of merely on a single buffer.
- A source comparison facility with semi-automatic merging, which can be used to compare and merge divergent versions of a source file.
- A change log facility, which maintains a single file containing a record of the edits done on a system.
5.1 File Groups
A file group is a set of files, upon which various editing operations can be performed. The files in a group are specified by a file in the following format:
- Any line which begins with one "@" is ignored.
- Any line which does not begin with an "@" is the name of a file in the group.
- A line which begins with "@@" specifies another file having this syntax, which is recursively examined to find more files in the group.
This syntax is used for historical reasons. Although any number of file groups may be read into Hemlock, there is only one active group, which is the file group implicitly used by all of the file group commands. Page 9.5 describes the Compile Group command.
Select Group [Command]
This command prompts for the name of a file group to make the active group. If the name entered is not the name of a group whose definition has been read, then the user is prompted for the name of a file to read the group definition from. The name of the default pathname is the name of the group, and the type is "upd".
Group Query Replace [Command]
This command prompts for target and replacement strings and then executes an interactive string replace on each file in the active group. This reads in each file as if Find File were used and processes it as if Query Replace were executing.
Group Replace [Command]
This is like Group Query Replace except that it executes a non-interactive replacement, similar to Replace String.
Group Search [Command]
This command prompts for a string and then searches for it in each file in the active group. This reads in each file as if Find File were used. When it finds an occurrence, it prompts the user for a key-event indicating what action to take. The following commands are defined:
- Escape, Space, y
- Exit Group Search.
- Delete, Backspace, n
- Continue searching for the next occurrence of the string.
- Continue the search at the beginning of the next file, skipping the remainder of the current file.
- Go into a recursive edit at the current location, and continue the search when it is exited.
Group Find File (initial value nil) [Variable]
The group searching and replacing commands read each file into its own buffer using Find File. Since this may result in large amounts of memory being consumed by unwanted buffers, this variable controls whether to delete the buffer after processing it. When this variable is false, the default, the commands delete the buffer if it did not previously exist; however, regardless of this variable, if the user leaves the buffer modified, the commands will not delete it.
Group Save File Confirm (initial value t) [Variable]
If this variable is true, the group searching and replacing commands ask for confirmation before saving any modified file. The commands attempt to save each file processed before going on to the next one in the group.
5.2 Source Comparison
These commands can be used to find exactly how the text in two buffers differs, and to generate a new version that combines features of both versions.
Source Compare Default Destination (initial value "Differences") [Variable]
This is a sticky default buffer name to offer when comparison commands prompt for a buffer in which to insert the results.
Compare Buffers [Command]
This command prompts for three buffers and then does a buffer comparison. The first two buffers must exist, as they are the buffers to be compared. The last buffer, which is created if it does not exist, is the buffer to which output is directed. The output buffer is selected during the comparison so that its progress can be monitored. There are various variables that control exactly how the comparison is done.
If a prefix argument is specified, then only only the lines in the the regions of the two buffers are compared.
Buffer Changes [Command]
This command compares the contents of the current buffer with the disk version of the associated file. It reads the file into the buffer Buffer Changes File, and generates the comparison in the buffer Buffer Changes Result. As with Compare Buffers, the output buffer is displayed in the current window.
Merge Buffers [Command]
This command functions in a very similar fashion to Compare Buffers, the difference being that a version which is a combination of the two buffers being compared is generated in the output buffer. This copies text that is identical in the two comparison buffers to the output buffer. When it encounters a difference, it displays the two differing sections in the output buffer and prompts the user for a key-event indicating what action to take. The following commands are defined:
- Use the first version of the text.
- Use the second version.
- Insert the string " MERGE LOSSAGE " followed by both versions. This is useful if the differing sections are too complex, or it is unclear which is the correct version. If you cannot make the decision conveniently at this point, you can later search for the marking string above.
- Do a recursive edit and ask again when the edit is exited.
Source Compare Ignore Case (initial value nil) [Variable]
If this variable is non-nil, Compare Buffers and Merge Buffers will do comparisons case-insensitively.
Source Compare Ignore Indentation (initial value nil) [Variable]
If this variable is non-nil, Compare Buffers and Merge Buffers ignore initial whitespace when comparing lines.
Source Compare Ignore Extra Newlines (initial value t) [Variable]
If this variable is true, Compare Buffers and Merge Buffers will treat all groups of newlines as if they were a single newline.
Source Compare Number of Lines (initial value 3) [Variable]
This variable controls the number of lines Compare Buffers and Merge Buffers will compare when resynchronizing after a difference has been encountered.
5.3 Change Logs
The Hemlock change log facility encourages the recording of changes to a system by making it easy to do so. The change log is kept in a separate file so that it doesn't clutter up the source code. The name of the log for a file is specified by the Log file option (see page 3.3.3.)
Log Change [Command]
Log Entry Template (initial value ) [Variable]
Log Change makes a new entry in the change log associated with the file. Any changes in the current buffer are saved, and the associated log file is read into its own buffer. The name of the log file is determined by merging the name specified in the Log option with the current buffer's file name, so it is not usually necessary to put the full name there. After inserting a template for the log entry at the beginning of the buffer, the command enters a recursive edit (see section 1.13) so that the text of the entry may be filled in. When the user exits the recursive edit, the log file is saved.
The variable Log Entry Template determines the format of the change log entry. Its value is a Common Lisp format control string. The format string is passed three string arguments: the full name of the file, the creation date for the file and the name of the file author. If the creation date is not available, the current date is used. If the author is not available then nil is passed. If there is an @ in the template, then it is deleted and the point is left at that position.