Contents of Article


Introduction

Example: Changing tagged lines

Why use tagged lines ?

Relative line tag notation

Line label and line tag co-location

Primary-command tag usage

Primary-command tag examples

The TAG primary command

Using tags for line control ranges

The DROP and KEEP commands

Using Labels and Tags with the LINE Command



Introduction


SPFLite contains an exciting new technology extension to ISPF: Line Tags You will note a number of similarities between a line tag and a line label.


Note:  User Lines provide an alternate means to segregate lines into two groups, known as U lines and V lines, where U lines are a set of lines of particular interest to a user at a given point in time, and "non-User" lines are everything else. The terms User Line and U line mean the same thing; and, non-User Line, V line and ordinary data line, all mean the same thing.


User lines have a number of similarities with excluded lines, but User lines are not hidden and then revealed the way excluded lines are. If you only need two types of lines to work with, using User Lines may be simpler than using tagged lines.


See Working with User lines for more information.


A line tag is a : colon followed by one or more letters, and appears in the sequence area.


Note: The line number sequence area size on the edit screen is adjustable from 5 to 8 positions. This means the maximum size of a label or tag that you can type into a sequence area is from 4 to 7 letters, after the leading dot or colon. Internally, SPFLite maintains an 8-position sequence area, and only displays as much as will fit.


This means that labels and tags on the primary command line can actually use the maximum internal size (a dot or colon plus up to 7 letters). When you do this, only part of the label or tag is displayed, but the entire value is present. That should not pose a problem if the tags are being managed by macros, but if you enter such tags manually, be careful you don't confuse yourself, since you won't see the entire tag displayed on the edit screen.


Tags are associated with the data line itself, not the particular line number they are on at the moment. So, if lines are inserted or deleted prior to a tagged line, or if the tagged line itself is moved, the tag stays with the line.


You can enter a tag on a line by typing it in the sequence area, and you can remove by blanking it out, just like you would with a label. However, as you will see, there are other, more powerful ways of tagging and untagging lines.


The major difference between a tag and a label is that the same tag name can appear on multiple lines. Like labels, tags can be used on primary commands to reference a set of lines to be acted upon.


If you like, you can think of the single dot that precedes a label, and the two dots that make up the colon preceding a tag, to help you remember that a label applies to a single line, while tags apply to multiple lines (usually).


A given tag name usually will end up appearing on multiple lines, because that's where tags derive their power. But there is no reason why a particular tag name can't be on just a single line.


Example: Changing tagged lines


Let's say we have the following file, and manually entered a tag name of :T on the lines shown, and then issue a CHANGE command that uses those lines:



When you are done, the file display will look like this:



Tags are persistent.  If you are editing this file and have a PROFILE option of STATE ON, and these tags are present, you can close this file and then reopen it later, and again, the three :T tag names will still be there.


Why use tagged lines ? 


Well, consider why excluded lines are used. (Review "Working with excluded lines" section as needed for more information). Excluded lines are a way to sub-divide, or partition, a file into two groups or subsets: the excluded group, and the unexcluded group. You can use X or NX on commands to select between these two groups.


But suppose you needed three or four groups – or maybe, lots of groups. What if you needed to do extensive work on one or more of these groups, including things like FIND and CHANGE that normally unexclude lines when string are found and changed, and thus might change a line from being in one group to being in another?  Excluded lines don't help much any more in cases like this. But tagged lines do. Tagged lines are a much more powerful facility for managing your data. You will see this as the discussion proceeds.


You may wish to review Case Study: Implementing Bookmarks in Keyboard Macros for an example that combines line tags and key mapping.


Two points to note here:


    • First, because tags are more powerful than exclusions, there is more involved in using them. There are additional commands and considerations. These are discussed in detail. Be prepared to do a little studying up before you grasp the whole picture.


    • Second, labeled lines, tagged lines, excluded lines and User Lines can be combined for even more powerful data selection capabilities. Users involved in activities like data management will see possibilities to perform certain types of data mining operations on text data, using labeled, tagged, excluded, and User lines, which could be quite useful in inspecting or analyzing very large text files.


Relative line tag notation


Like labels, tags may take a relative notation, although it's a bit simpler. (The relative label formats  <  <=  >  and  >=  are not used on tags.)


relative tag defines a collection of lines in the edit file with respect to a tag. The following relative line tags exist:


:ABC                                                all lines tagged with :ABC

 

:\ABC  or  :<>ABC  or  :¬ABC                all lines other than lines tagged with :ABC


:ZALL                                                all lines having any tag whatsoever regardless of tag name

 

:\ZALL  or  :<>ZALL  or  :¬ZALL                all lines having no tag present


Note that :ABC is just an example here, whereas :ZALL is literally specified as a special tag name, reserved to collectively reference all lines having a line tag of any kind. It is illegal to actually enter a tag of :ZALL into the sequence area of a line.


The Z prefix on ALL comes from conventions IBM uses for ISPF reserved names, such as .ZFIRST.


Line label and line tag co-location


The label of a line, and the tag of a line, are two separate, independent attributes of a line (along with the exclusion status of a line). This means a line may be labeled or not labeled, tagged or not tagged, and excluded or not excluded, all independently of each other.


When a line has both a label and a tag at the same time, the screen display will only show the label, since a label is always unique, but a tag is normally not unique. What happens is that the usually-blank column between the sequence area and column 1 of the data line will contain a : colon as a reminder that there is a tag defined for that line. You can't see the tag, but at least you know one is there.


Sometimes that usually-blank column is called the gap column.  As with character positions in the sequence area, the gap column has no column number.


Let's say we have the following file, and we manually entered a tag name of :T on lines 2, 4 and 6, and then on line 4, then we also entered a label of .AA The file display will look like this:



Notice the : colon after label .AA on line 4. Suppose you put the cursor on line 4, column 4, where the A of ABC is underlined above. The status line for the line/column indicator will look like this. Notice that in addition to the line and column, you will see the hidden tag name:


         L  000004  C 4  :T


The status line only shows tag names when the tag for a line is hidden. When there is no tag/label co-location going on, the line/column display will not display tag names, even for lines that have tags.


Why not just show tag names all the time in the line/column display, instead of only when there is co-location?  Mainly to keep the status line as simple and uncluttered as possible. We don't want to distract you with information you can see anyway just by looking at the main screen.


Now, just to explore this idea, suppose we were to set up the following keyboard mapping:


       Alt-period = {.}

       Alt-semicolon = {:}


These are not defaults; you would have to do this key mapping yourself.


This will allow us to use the keyboard to clear the sequence area of labels or tags – even in cases where you couldn't directly get to a tag, or type over it, because co-location was hiding it.


If you placed the cursor on line 4, and were to press Alt-period, the label and colon would go away, the tag would reappear, and line 4 would look like this:



Whereas, if you placed the cursor on line 4, and were to press Alt-semicolon, the tag and colon would go away, and the line 4 would look like this:



In both cases, once the label/tag co-location is no longer present, the : colon in the gap column and the extra :T tag name that was present in the status line's line/column display will disappear.


Primary-command tag usage


In any primary command that references data lines, a tag name can be used instead of a label or pair of labels. Only one tag may appear (except for the TAG primary command, which has a special syntax.)


You can combine tags and labels on the same command to select lines. What happens is that the list of effective lines is the intersection of the labels and tags, so that only the tags that exist within the specified line label range are available to the command.


You can combine the X or NX option, and the MX or DX option, along with tags, on various commands, just as you could do if you were selecting lines or line ranges using labels.


If a command has both a tag name and X or NX, then lines with the given tag are selected limited by their X or NX status.


Primary-command tag examples


CHANGE ABC DEF ALL :T

Change text on all lines tagged with :T.


CHANGE ABC DEF ALL :T X

Change text on all lines tagged with :T, limited to excluded lines only. Changed lines will be unexcluded.


CHANGE ABC DEF ALL :T X DX

Change text on all lines tagged with :T, limited to excluded lines only. Changed lines will remain excluded.


CHANGE ABC DEF ALL :\T

Change text on all lines which are NOT tagged with :T.


CHANGE ABC DEF ALL :T .A .B  X

Change text on all lines which are tagged with :T, limited to excluded lines only, that are within the range of labels .A and .B


CHANGE ABC DEF ALL :ZALL

Change text on all lines tagged with a tag of any kind.


CHANGE ABC DEF ALL :\ZALL NX MX

Change text on all lines which have no tags of any kind and are not excluded. Changed lines will be made excluded afterwards.


The TAG primary command


The full potential of line tags is only realized when you use the TAG primary command to set, clear or toggle a given line tag en masse across many lines. It's a powerful command, and has many options. The TAG command description also discusses it, but let's go over it here.


       Database users may see conceptual similarities between the TAG command and SQL's UPDATE / SELECT WHERE statements.


Here's the syntax of it:


TAG        [ :tag-name ]


[ search-string [ NF ] ]


[ start-column [ end-column ] ]


[ ON | OFF | TOGGLE | ASSERT | SET ]


[ FIRST | LAST | NEXT | PREV | ALL ]


[  PREFIX | SUFFIX | WORD | CHAR ]


[ line-control-range ]


[ X | NX ]


[ MX | DX ]


That's a lot. We will take this one step at a time.


    • The tag-name names the tag that is to be set, cleared or toggled. It's optional, because if you omit it, TAG can be used to clear all tags in a given line range when you are doing a TAG OFF or TAG ASSERT operation. Normally you will be using the tag-name operand., and for ON and TOGGLE it is required. The tag-name here represents the target of the TAG command's activity – what tag name will be used to set tags on with, for example. So, this tag is called the target tag name.  The target tag, when used, must appear immediately after the TAG command name, and no where else.


Otherwise, it could possibly get confused with being part of the line-control range, and we wouldn't want that to happen, would we?


This is one of the few places where SPFLite has positional requirements for its command options. In most cases, you can put operands in any order you want, but not for this one.


    • The search-string is used to locate particular lines for which you wish to set, clear, assert or toggle a line tag. If you omit the search-string, the command does not base its line-selection criteria on the contents of the lines, only their location in the file. A search-string is required for the ASSERT option. Note:  A search-string on a TAG command is just like a search-string on a FIND command, which means the same kinds of SPF string types are permitted, such as C, T, X, P and R strings.


    • If you use a search-string, you can use the NF option, which means not found.  It works just like the NFIND command does, by selecting lines in which the search-string is not found. (Recall that the NFIND command can also be spelled as NF.)


Why didn't we make an NTAG command or something, to be “consistent” with NFIND?  Since TAG is pretty complicated already, having two complicated tag commands just didn't seem like a good idea. Besides, most of what an NTAG command would have done is covered by the ASSERT option, so keep reading.


    • The start-column and end-column are used to limit the columns where the search-string is searched for, and this works just like it does on a FIND command.


    • The ON, OFF, TOGGLE, ASSERT and SET control what exactly the TAG command is going to do. Normally you are going to use TAG to tag things, and so ON is the default. You can abbreviate TOGGLE to TOG. ON and OFF are straight-forward. To TOGGLE a tag means (a) if a line has no tag, set the specified tag name, (b) if the line has the specified tag, clear that tag, and (c) if the line has a tag other than the specified tag, leave that tag alone; don't change it and don't clear it.


The SET option requires a tag name and a search-string. If the search string is found on the line (or, not found if the NF option is used), then the line is assigned the tag name. If search string is not found on the line (or, is found, if the NF option is used), then the line is cleared of any existing tags. SET may thus be used to assign a tag to a line range without have to pre-clear any existing tags in a separate step.


    • The ASSERT option calls for some explanation. The short answer of what ASSERT does is this:  It does exactly the same thing that OFF does, but the sense of the NF option in inverted. What in the world does that mean?  Well, if you wanted to “assert” that a string existed on an already tagged line, what would it mean in practice?  You would have to check to see if the string was there, and if it was, you'd leave the existing tag alone and not change it. But if the string wasn't there, you would erase the tag, since your “assertion test” had failed. So, a command like TAG OFF ‘string' NF would accomplish this – tags are turned off if the string is not found. However, even though that is a perfectly good TAG command, it kind of looks like a “double negative” with “backward logic”. It's just not the way people generally think about things. So, instead of this double-negative stuff, you can use “positive logic” and describe this operation in terms of what you want to be there, instead of what you don't want to be there. So, the command TAG ASSERT ‘string' will do exactly the same thing as TAG OFF ‘string' NF, without forcing your poor brain through contortions and back-flips trying to figure it out.

You can also use NF on ASSERT, though it would probably be used less frequently than ASSERT without NF. What would an ASSERT NF be used for?  Say you had some tagged lines, and you wanted to make sure (assert) that some unwanted string was not there (NF). You could say TAG OFF ‘string', but if you have gotten into the habit of thinking in terms of assertions rather than just on/off, this format could be useful to you. Whether you use OFF or ASSERT is really a case of which makes more sense to you at the time.


    • The FIRST, LAST, PREV, NEXT, and ALL options are like FIND and CHANGE as well. Normally you will want to act upon all lines that meet the search criteria of the command; that's where the power of the TAG command lies, after all. So, unlike other similar commands that default to NEXT, the TAG command defaults to ALL.


You should be aware that there is no “repeat tag” command that is comparable to RFIND or RCHANGE. If you choose to use FIRST, LAST, PREV or NEXT on TAG, it would ordinarily involve manual cursor placement if you wanted to repeat your initial single-line TAG command. However, you can use the ITERATOR Technique to get around this. See the Application Note: The ITERATOR Technique in Command Macro Support for more information.


    • PREFIX, SUFFIX, WORD and CHAR are just like FIND and CHANGE, with CHAR being the default.


    • The X and NX options are like FIND and CHANGE. They limit the selection of lines that TAG will operate on to either excluded or unexcluded lines.


    • Tagging or untagging a line is comparable to finding a string with FIND or CHANGE; this is true whether you actually put a string value on the TAG command or not. So, tagging a line that is excluded will unexclude it. If you want to modify that action, you can use the MX or DX options, which work the same way as they do on a FIND or CHANGE.


One important point to remember is that TAG will either set a tag on, off or toggle it, if the lines provided to TAG meet the criteria you specify. If they don't meet that criteria, the “tag status” of such lines is unchanged – existing tags will be left alone, and untagged lines will not get tagged, it they are not selected for processing by the TAG command.


So, for example, a TAG :T ON 'string' will tag lines having 'string', but other lines that already had some kind of tag but didn't' have 'string' will not be “untagged” – they will be left alone.


Remember that TAG ASSERT ‘string' is the same as TAG OFF ‘string' NF, and TAG ASSERT ‘string' NF is the same as TAG OFF ‘string'. They both describe the same action, one with positive logic and one with negative logic.


Using tags for line control ranges


And now, saving the best for last …


Notice the line-control-range operand. Just like other commands, this operand allows you to select one or more lines to operate on. If you don't specify a line-control-range, TAG will operate on a CC block, if you have defined one. If you haven't defined a CC block, TAG will operate on the entire file, subject to any other options you may have specified.


Otherwise, the line-control-range operand can be one or two line labels (including relative line notation), and/or it can be a line tag (or relative tag notation), and/or a X or NX excluded-line selection.


The line control range for TAG can have a tag?  Yes.


The way this works is that a tag-name here, as a line-control-range, chooses which lines the TAG command will operate on. The tag-name at the beginning of the TAG command is then used to specify a new tag name to be given to all chosen lines. If any of those lines already have a tag, they will be replaced by the new tag, if the ON option is used or is defaulted.


If there can be two tag names in a TAG command, how do I know which is which?  The tag immediately following the TAG command name is the value used for setting or toggling the new tag name on a data line. That tag is called the target tag name. A tag name appearing anywhere else is considered to be part of the line-control range, used for selecting eligible lines. Tag names in the line-control range can be also a relative tag like :\ABC, but the target tag cannot be; it has to be a simple tag name.


This is one of the few places in SPFLite where there are order dependencies on primary command operands. In most cases, the order you specify things doesn't matter, but here it does.


What could a TAG command with two tags present be used for?


Well, suppose you wanted to find all lines that had the set of strings GORT, KLATU, BARADA and NIKTO on them. But, the strings could be in any order, and might be separated by an unknown amount of text. You might be able to create a regular expression to find two such strings, but to find four of them, in any order, would require 4 * 3 * 2 = 24 different possible orderings. Even if you're an expert at regular expressions, that would be pretty tough.


Here's where tags comes to the rescue. What we can do is first find all lines with GORT on them, and tag them as :G. Then, only looking at the lines tagged with :G, find lines with KLATU, and tag them with :K, etc. When you're done, you will have a set of lines tagged with :N which will contain the set of all four words, regardless of the order they appear on the line. You can call these strings WORDS on the TAG command, if that's what they are, just like on a FIND command. (We'll skip that here.)  The sequence of TAG commands would work like this:


TAG :G 'GORT'  

TAG :K 'KLATU'  :G

TAG :B 'BARADA' :K

TAG :N 'NIKTO'  :B


If you wanted to, the initial TAG could be limited to a line range, like this:

TAG :G 'GORT' .ABC .DEF

or to a CC block, or to an excluded range, like this:

TAG :G 'GORT' X

but we'll continue with the discussion assuming that we're starting with the whole file, not just part of it.


The final tag :N can then be used to access only those lines having all four words. Now, suppose you wanted to view only these lines. You could say X ALL :\N to exclude all lines that don't contain these four words, or you could say DELETE ALL :\N to delete them.


Is it necessary to use all those tag names?  Is there any way we can get by with using fewer names?  Yes.


Don't try to just alternate tags, like using :A then :B then :A again, in order to achieve this. It won't work right.


Now, if you were to enter a TAG command that looks like TAG :T 'string' :T, it's asking the editor to select lines already tagged with :T that have 'string' on them, and then tag them with :T again.  That won't do what we want here.


In plain English, it's called “going nowhere fast”, and is just as useful as saying CHANGE ABC ABC ALL. However, SPFLite is nice enough to remind you of this fact, and will report, No lines (re)tagged.


However, you can selectively remove tags from lines in which a desired string is not found. So, you can reduce the number of tags needed to just one.


It's a little bit more complicated syntax, but you can use the RETRIEVE or CRETRIEV command (often mapped to F12) to pull up the more-complicated command and type over it; that will make it a little easier to do.


Let's revise the example above using just one tag:


TAG :A  'GORT'      

TAG OFF 'KLATU'  NF :A

TAG OFF 'BARADA' NF :A

TAG OFF 'NIKTO'  NF :A

 

That's a little better. The first TAG proceeds like the previous example. The remaining TAG commands successively “whittle away” at the list of lines represented by tag :A, so that any lines where the required words are not found (NF) no longer qualify as being in the :A list, and their :A tags get turned OFF.


If you format the command as shown above, you can almost read it, going left to right: “Turn any TAG OFF where the WORD  'KLATU' is Not Found (NF) on lines currently tagged with :A.


You could say, TAG :A OFF WORD 'KLATU' NF :A, but since you are only dealing with lines already tagged as :A and you aren't renaming it to something else, there is no need to specify the target tag-name after the TAG command name. It's easier to just leave it out.


A fine point:  It will not work if you happen to attempt a command like TAG :B OFF WORD 'KLATU' NF :A. In a command like this, all lines selected for the tag command are coming from lines tagged with :A. If you then ask TAG to turn off lines having tag :B, the TAG OFF function will confirm the existing tag before clearing it. It will not find any lines with :B on them, and so you will get the No lines (re)tagged message. However, there is nothing wrong in itself with asking for specific tags to be cleared. Suppose you had a range of lines from .ONE to .TWO and you wanted any line tags of :B removed but lines with any other tags left alone. You can say TAG :B OFF .ONE .TWO and that is perfectly fine.


Now, the results of the tagging operation can be found using the tag :A, and you don't have to keep track of which tag name to use, because there's only one.


One more fine point. The command TAG OFF 'KLATU' NF :A removes any tag from lines already tagged with :A in which the string is not found. Suppose you left off the :A tag and just said, TAG OFF 'KLATU' NF. Would that “work” ?  In many cases, it would. What happens is that you would be asking the editor to look at every line of the file, and to remove every tag on every line where that particular string is not found. There are two problems with this. First, if the file is very large, re-examining every line, instead of limiting the search to only lines that had already been tagged with :A in the prior step, could take longer. Second, if you had any other tags you were using for any other purpose, they would be cleared out as well. You are free to take this shortcut if you wish, but it's important to understand what you are asking for.


If you get in the habit of doing this type of tagging with a single tag name, you may need to clear out any existing ones before you start. Otherwise your results might include more lines than you intended. Tags can be cleared by using TAG :A OFF.


One more thing about TAG and RETRIEVE. TAG is mostly forgiving about the order you type the operands to it. So, the list of commands above can be rewritten to put the string last. Let's do that, and to keep it even simpler, we will dispense with the quotes, too (we are among friends here, right?)  So, you'd have this series of commands:


TAG :A GORT      

TAG OFF NF :A KLATU

TAG OFF NF :A BARADA

TAG OFF NF :A NIKTO

 

Now, for the third and fourth commands, you can retrieve what you entered for the second command, press the End key, backspace over the string (or use the mouse to do the same thing) and then type in the new string each time. That way you only have to type the part of TAG that is different and not redo the whole thing all over again.


Hopefully if you are still with us so far, you may agree that this technique will work and you can follow along the explanation. You may also feel it's a little weird. Remember what we said about ASSERT and double negatives?  That's why it exists – to address problems like this. The task at hand that we really want to do is to assert that the desired words are present. That particular viewpoint is more important than the whys and hows of turning off tags if the word are not present. It is for problems like this that ASSERT was made. Let's rewrite this from negative logic to positive logic.


TAG :A GORT      

TAG ASSERT KLATU :A

TAG ASSERT BARADA :A

TAG ASSERT NIKTO :A

 

Does this make more sense?  First, find all lines with GORT, then assert that those lines also have KLATU and the other words. Now, let's take it a step further, and say that we want to make sure (assert) that the word REMEMBER is not present on any of the lines tagged with :A. That can be done like this:


TAG ASSERT REMEMBER NF :A

Why go through the trouble of using ASSERT?  Why was it even made available?  Mainly for users editing very large data files. In the process of doing “data mining” activities, they may have a large number of tags set throughout their file. It is very important as one is trimming off tags, looking for exactly the right data, that you ask for the right things at the right time. By being able to describe tagging operations in the terms (positive or negative logic) that make the most sense to you it will decrease the likelihood that you would make a mistake.


The DROP and KEEP commands


Our discussion of tags so far has dealt with tagged lines as individual ‘units' each acted upon independently. When you use DROP and KEEP, you can deal with tagged lines in groups.


A tag group is a set of two or more adjacent lines that have the same tag name. A tag group is preceded and followed by:

    • The Top of Data or Bottom of Data line
    • A line without a tag
    • A line with a different tag than the tag group has


Notice it says two or more lines.  If you have single, individual tagged lines where the line before or after does not have the same tag, that line is not a tag group. Such ‘lone' tagged lines are ignored by DROP and KEEP.


The DROP and KEEP may be thought of as “structured DELETE commands”. The purpose of both of them is to delete lines. The DROP command is focused on which lines are to be deleted, while KEEP is focused on what lines are not to be deleted.


What is the idea behind DROP and KEEP?


Well, if you have used one or more TAG commands to group together blocks of lines having some common feature, it is possible that some of those lines are duplicates. DROP and KEEP provide a means to quickly get rid of all those duplicate lines in a single command.


DROP and KEEP apply their deletion rules to every tag group in the entire file having the specified tag name.


The reason there aren't options like PREV and NEXT, etc. is that if you only wanted to work on a small area, you could just manually delete lines and not use DROP and KEEP. If you need to work on a large block of the file, but not the entire file, you can use line labels on a TAG command to limit their range .


You mean you can have labels and tags on the same command at the same time?  Yes. It works by selecting lines with the specified tag, but only those within the line label range. This feature works on the TAG command, and any others that accept generalized line-range arguments, but not on DROP and KEEP themselves.


For example, if you had several tag groups defined using tag :T, but you didn't want tag groups between lines .A and .B to be modified, you could use a TAG command to temporarily rename the :T tags between .A and .B to something else (let's call it :TT for “temporary” :T tag). Then, use your DROP or KEEP as usual, referencing tag :T. Once you're done, you can use another TAG command to rename the :TT tags back to :T.


For example, suppose you had a file with blank lines in it, and you wanted to collapse spans of multiple blank lines into single blank lines. Here is a way you could to this:


TAG :B OFF

TAG :B P'^' NF

KEEP FIRST :B


This does the following:

    • Ensure that no lines are tagged with :B in the file.
    • Search the entire file for lines in which non-blank characters (P'^') are not found (NF). Lines that are entirely blank will not have any non-blank characters.
    • For each tag block having line tag :B, KEEP only the FIRST line of each block (delete all other lines except for the FIRST line of each block)


A command like TAG  :B  P'^'  NF  may seem a little unusual: Find lines in which non-blanks are not found?  However, this is necessary to handle situations where a “blank” line is actually a zero-length line. In those cases, there is no data on the line to find.  So, we have to define the search in terms of not finding something, so that those zero-length lines will be found and tagged along with our search for blank lines.


This example also illustrates why lone tagged lines are not considered as tag blocks. If they were, DROP and KEEP might delete them as well, and rather than getting rid of duplicate lines, you'd get rid of every line. There is no need for DROP and KEEP to delete every line, since we already have DELETE for that purpose.


Since only blank lines were selected, it probably doesn't matter whether the first or last line of each block is retained; the effect is the same. When you apply this technique to your own data, you may have some particular reason why you might want to use the LAST line vs. the FIRST one.


Recalling the note above, suppose you wanted to remove extra blank lines, but not inside the range of .A and .B, where .A precedes .B in the file; assume .A and .B are already defined. DROP and KEEP don't directly support this, since they do not take generalized line-range operands with label ranges or X or NX options. Instead, you could accomplish it with something like this:


TAG :B OFF

TAG :B P'^' NF

TAG :BT :B .A .B                        -- inside the range .A to .B rename tags :B to :BT

KEEP FIRST :B                                -- the lines tagged with :BT are ignored

TAG :B :BT .A .B                        -- rename the temporary :BT tags back to :B


Suppose you had wanted to remove all groups of multiple blank lines, but any individual blank lines are to be left as is. This could be done by replacing the KEEP command above with DROP:


DROP ALL :B


Using Labels and Tags with the LINE Command


You can manage line labels and line tags using the LINE primary command. For example, to put a tag of :ABC on line 10, you can issue the command:

LINE ':ABC' .10

Remember to quote the label, because in this example, the first operand ':ABC' is what goes into the sequence area, and the second operand .10 is where the first operand is placed.


When doing a normal edit, there is usually no need to do such a thing; you would just put the tag on the line directly. However, when running a programmable macro the LINE primary command is the only way to do this. You would need to 'wrap' the LINE primary command in an SPF_CMD function call in your .MACRO file, like this:

SPF_CMD ("LINE ':ABC' .10")


It is possible to set, clear and toggle both line labels and line tags from the LINE primary command. The possible options are as follows:


LINE '.label'           -- Enter label into sequence area


LINE '..label'          -- Toggle label; enter label if no label present,

                       -- else clear any label that is present


LINE '.'                -- Clear any label that may be present


LINE '..'               -- Clear any label that may be present; same as LINE '.'


LINE ':tag'             -- Enter tag into sequence area


LINE '::tag'            -- Toggle tag; enter tag if no tag present,  

                       -- else clear any tag that is present


LINE ':'                -- Clear any tag that may be present


LINE '::'               -- Clear any tag that may be present; same as LINE ':'


See LINE - Apply Line Command and Working with the LINE Primary Command for more information on the LINE command.


See Special Line Commands in Using the KEYMAP Dialog for more information on performing these same actions within a KEYMAP definition.



Created with the Personal Edition of HelpNDoc: Create iPhone web-based documentation