restore — restore all marks from a given set
Marks and ranges that were saved in a numbered set can be added back
to the current set of marks and ranges in several ways, using a
restore command, which is usually written with a single < symbol,
instead of the full command name restore.
There are three sets available for storing marks.
The simplest method is to use a restore command to
replace the current set of marks and ranges with a stored one.
Each of the following commands achieves this:
: restore 1
: < 1
There are three additional ways to restore sets of marks and ranges.
The first is to retain only marks and ranges in the current set
that are also marked in the stored set, by using an &-suffix
for set intersection.
The next option is to include all marks and ranges from both the
current set and the stored set, with an |-suffix for set union:
The last option is to restrict the set of marks and ranges to
those that appear exclusively in either the current set, or in
the stored set, but not in both, using an ^-suffix for
Consider finding all label names in a C program.
A first attempt can be to mark all identifiers followed by a colon:
: m @ident :
But this will also mark parts of conditional expressions,
it matches case clauses in switch statements, and also bitfield declarations.
None of these should be included:
z = (expr) ? x : y;
int r : 6;
Note that default clauses in switch statements would not be marked,
since default is a keyword and not an identifier.
To prevent the unintended matches we can use sets.
First, we find the charateristic pattern of a conditional expression,
and we save all those marks in a set:
: m ?; s : # find p ? r : s
: n :; b # move mark to the identifier before the :
: >1 # save these identifiers in set 1
: r # clear the marks
Next we find all names that precede colons, and move
the mark to places where we can recognize the context that must be excluded:
: m @ident : # find identifiers followed by a colon
: n; n # move mark to token following the colon
: unmark /^[0-9]$ # exclude bitfield declarations name : nr
: b; b; b # move mark back to the token before the identifier
: unmark case # exclude case statements
: n # move back to the identifier
We left the final marks on the identifier names that precedes the colon,
just like we did in the set of marks saved earlier in set 1.
Now we can do a set difference to exclude all the marks that corresponded
to conditional expressions, and we have the intended set of marks left:
: <^1 # exclude conditional expressions
: d # display the matching lines