-*-Text-*-  DOCOND Node: Top Up: (EMACS) Next: Flags DOCOND is a program for putting "assembly conditionals" in text files. At the beginning of the DOCOND input file go declarations of the names of various "flags" or assembly switches, Throughout the rest of the file may appear conditionals which test the state of a flag. Processing the input file with DOCOND causes the contents of failing conditionals to be deleted. The contents of successful conditionals remain, but the conditional syntax itself is deleted, leaving text which is free of DOCOND commands. In addition to conditionals within the text, conditional replacements may be specified as declarations, and macros written in TECO can be called from points in the text. * Menu: * Flags:: How to declare flags. * Relate:: Expressing relationships between flags. * Condit:: How to put conditionals in the text. * Macros:: Macro calls in the text. * Replace:: Conditional global replacements. * Run:: Running DOCOND.  DOCOND Node: Flags, Previous: Top, Up: Top, Next: Relate Declaring DOCOND Flags. DOCOND processing is controlled by binary flags, whose names are chosen by the user. Each flag has a "setting", which iseither "+" or "-" (or, in the source file, "?", meaning that the setting is unknown as yet). A DOCOND conditional always tests the setting of some flag. The first stage of DOCOND processing asks the user what setting to use for each flag; when all the settings are known, DOCOND processes the conditionals in the text according to those settings. Each DOCOND input file must begin with a DOCOND declarations section which is terminated with the string "{end}" followed by a CRLF. Each flag used in the file must be declared in this section. Implications and conditional replacements are also declared there. Since each DOCOND construct is enclosed in braces, nothing stops you from having other sorts of text (such as -*-Text-*-) in the DOCOND declarations section, but whatever it is will all be deleted when DOCOND is finished running. A flag declaration looks like {Flag:?}. Notice the "?"! The "?" is a placeholder which you must specify; it will be replaced by the setting of the flag, either "+" or "-", when that is known. Here are some examples: {Flag:?FOO} {Flag:?DoubleFoo} You can actually provide a setting for the flag in the source file, by writing "+" or "-" instead of the "?". This is actually useful, since you can declare a flag named "Comment" which is always off, {Flag:-Comment} and then use conditionals on this flag as comments: {+Comment: anything at all} If you have no declarations but Flag declarations, DOCOND will ask you for the settings of all the flags, in the order they are declared. The Print declaration allows you to print out an arbitrary string at declaration processing time (presumably, to give the user directions on how to decide what flag settings to specify). Here is an example: {Print:FOO should be "+" if your version can process Lisp code. } {Flag:?FOO}  DOCOND Node: Relate, Previous: Flags, Up: Top, Next: Condit Expressing Relationships between Flags. Although DOCOND conditionals can be nested, it is often convenient to have redundant flags which express combinations of other flags. Or, you might have several mutually exclusive alternatives, with a flag for each alternative. In that case, it would be a nuisance to be asked for the setting of each flag separately, when all but one must be "-". For these situations, DOCOND provides the "relationship declarations" Implies, Alternatives, and Default. Implies allows you to set one flag conditional on the setting of another. Alternatives tells DOCOND that exactly one of a list of flags must be "+" and the others "-". DOCOND then knows just to ask for the name of the one which is "+". Default allows you to provide a flag with a default setting which is used unless overridden by an Implies or Alternative (or by a manual setting made before doing MM DOCOND). A DOCOND implication says that if one flag is set on (or off), another flag should be set automatically. In general, an implication specifies a flag and setting as the condition, and a flag to be set in response. The setting always precedes the flagname (it is always thus, in DOCOND), and no extra spaces are allowed anywhere in the construct. Here is the general pattern: {Implies:+FOO=>-BAR} A default declaration says that rather than ask the user for the value of a certain flag, a specific default setting should be assumed. {Default:-FOO} says that FOO is off by default. This is not the same as giving FOO a constant value of "-" -- that is, declaring FOO with {Flag:-FOO} because implications of flags set earlier can override the default. The user can also override it using the DOCOND Set Flag command. For example, you can use Implies and Default together to declare that the FOO-or-BAR flag should be "+" if either FOO or BAR is "+": FOO-or-BAR is + if FOO or BAR is: {Implies:+FOO=>+FOO-or-BAR} {Implies:+BAR=>+FOO-or-BAR} {Default:-FOO-or-BAR} {Flag:?FOO-or-BAR} Note that text not within brackets in the declaration section is in effect a comment, since it will be deleted without affecting DOCOND. That the Implies declarations which can set FOO-or-BAR precede the Flag declaration for FOO-or-BAR is essential, because both types are processed in one pass through the declarations section, and if the Flag declaration were seen first, since the flag would still be unset, DOCOND would ask the user for the setting. For the same reason, the above example must come after the declarations of FOO and BAR. The location of the Default declaration doesn't actually matter, because it is processed, not by its position, but at the time when the Flag declaration is processed. However, it is good practise to put it in the position which would be correct if it were processed in sequence. The remaining type of relationship declaration is the Alternatives declaration, which says that, of a list of flags, exactly one should be "+" and the rest "-". When the Alternatives declaration is processed (in sequential order, like Implies and Flag), if none of the flags in the list is set to "+", the user is asked to specify one of them. The specified one is set to "+", and the rest to "-". If one is already set to "+", Alternatives just sets the rest to "-" without having to ask. Thus, an alternative can be selected by an earlier Implies, or by the MM DOCOND Set Flag command (*Note Run: Run.). Here is an example of the Alternatives declaration: {Alternatives:ITS,Twenex,Lispm} {Flag:?ITS} {Flag:?Twenex} {Flag:?Lispm} Note that the Alternatives declaration does not eliminate the need to declare the individual flags in Flag declarations, but the latter must come after the Alternatives, or else DOCOND would ask about each flag individually when it came to the Flag declarations.  DOCOND Node: Condit, Previous: Relate, Up: Top, Next: Macros In-text Conditionals. The fundamental feature of DOCOND is the conditional which causes a string of text to appear or not appear in the output according to the setting of some flag. Each conditional tests only one flag, but conditionals can be nested to test more than one; in addition, the Implies and Default constructs can be used to make a new flag correspond to any Boolean combination of other flag settings. *Note Boole: Relate. A conditional must contain the name of the flag, the setting to test for, and the conditionalized text. Here is an example: {+FOO: text to appear only if FOO is "on" (or "+")} A conditional appears vaguely like the other DOCOND constructs, but note these differences: 1) in a conditional, the "{" is followed by a "+" or a "-". 2) conditionals appear PAST the {end} of the declarations section, whereas the other constructs appear only WITHIN the declarations section. Note that all text not within a conditional will always appear in the output, so that I want to {+FOO:win} {-FOO:lose} . will result, if FOO is +, in I want to win . or, if FOO is -, in I want to lose . If you want no spurious CRLFs in the output, put none in the input: I want to {+FOO:win}{-FOO:lose}. Note also that there is no difficulty in having braces in unconditional text, since "{" is recognized as a conditional only when followed by a "+" or "-", but braces appearing inside a conditional must be balanced (because nested conditionals work). Note that conditional global replacements can affect the conditionals, both the text they contain and the flag names!  DOCOND Node: Macros, Previous: Condit, Up: Top, Next: Replace In-text Macro Calls. In addition to conditionals, DOCOND provides a feature for including macro calls in the text. Unlike most macro processors, DOCOND does not need to define a macro-writing language, because the macros are just named EMACS commands written in TECO. {*macroname:stringarg} specifies a call to the command named with the string argument provided to it. The macro call is deleted from the buffer when it is processed, and replaced by the string (if any) returned by the called macro (in which case, the newly inserted string is rescanned for conditionals and macro calls). For example, suppose we have a macro named MM Type Out which takes a string argument and types it out; then {*Type Out:FOO} would print "FOO" when executed. Macro calls can successfully be included in conditionals; they will be expanded only if the conditionals succeed. Conditionals can also be included in a macro call, but the macro call is processed first, so that the string argument passed to the macro will unconditionally contain the conditionals. Only if the macro returns those conditionals to be reinserted and rescanned will those conditionals actually be processed as such. One macro provided by DOCOND for just this purpose is called Refill. Call Refill on the line after the end of a paragraph ... last line of paragraph. {+FOO:{*Refill:}} to refill that paragraph, if conditionals or replacements have caused it not to be properly filled. To provide a macro FOO for use in DOCOND macro calls, you must define it yourself. Any method of defining a named EMACS command will do, including putting a specification of the variable MM FOO in the source file's local modes, but there is also a special facility called the Local Variable declaration in DOCOND itself which can be used: {Local Variable:MM FOO=lots of TECO commands} which can be used to define the variable MM FOO only during actual DOCOND processing. Putting "MM FOO:lots of TECO commands" in the local modes of the source file would define MM FOO at all times when the file was being edited, not just during DOCOND processing.  DOCOND Node: Replace, Previous: Macros, Up: Top, Next: Run Conditional Global Replacements. If one pair of alternatives appears very frequently throughout the text, it would be painful to replace it with a pair of conditionals each time it is needed. The alternative is to use a conditional global replacement declaration. One version can actually be used in the text and then replaced by the other on the appropriate condition. A global replacement declaration must appear in the declarations section, and specifies a flag and setting as the condition, a string to replace, and a string to replace with. For example, {Replace:+FOO=>old->new} says to replace old with new throughout, if FOO is +. Replacement is done using 1mmReplace Stringoldnew, so that, among other things, instances of "old" are found only when surrounded by delimiter characters, and certain control characters must be quoted as described under Replace String (*Note Repl: (EMACS)Replace.). Spaces are significant, so don't put in any excess ones. Replacements, like other declarations, are processed in serial order, but they do not apply to the declarations section; only to the text after it. For a more complicated action than just replacing one string with another, you can direct an arbitrary TECO program to be run to turn the old string into what you want. Do this by using "-->>" instead of "->" and writing the TECO code instead of the string to replace with. The difference between a -> replacement and a -->> replacement is the difference between MM Query Replace and 1,MM Query Replace. Here is an example: {Replace:+FOO=>**-->>fkd fwk} deletes every instance of "**" together with the following word.  DOCOND Node: Run, Previous: Replace, Up: Top Running DOCOND. The previous nodes tell everything about what to put in an input file for DOCOND. This is how to use DOCOND to process one. First, visit the input file, and do M-X Load LibDOCOND to load the DOCOND program itself. Then, in the simplest case, just do M-X DOCOND. DOCOND will ask you for the setting of each flag, processing implications of settings as you tell them to it. When it knows all the flag settings, it will process the buffer and return with everything done. To protect you from filing the output back over the input file, DOCOND clears the visit file names as soon as it starts. Thus, C-X C-S after DOCOND finishes will not be allowed. In addition, if there are any changes in the buffer when DOCOND is started, it offers to save them for you (if you don't save them, they will be lost). Before starting the complete DOCOND processing, you can set individual flags by means of the DOCOND Set Flag command present in the DOCOND library. This command expects an argument which contains a setting followed by a flag name, as in M-X DOCOND Set Flag+FOO The implications of the flags you set in this way will be processed as soon as you do M-X DOCOND. DOCOND Set Flag is useful primarily for having a large number of flags which are all normally "-". Rather than asking you about each of them, you might prefer to have to do DOCOND Set Flag for any that you wish to have "+", and let the rest be forced to "-" by Default declarations.