Sunteți pe pagina 1din 40

The WinEdt Hackers Guide

Jason Alexander Colin Marquardt November 10, 1998

Contents
1 Macros 1.1 Basics . . . . . . . . . . . . . . . . . 1.2 Variables/Registers . . . . . . . . . . 1.2.1 Strings and things . . . . . . 1.2.2 Setting the values of registers 1.3 Procedures and Functions . . . . . . 1.4 Recursion . . . . . . . . . . . . . . . 1.4.1 A lengthy example . . . . . . 1.5 Interactive Macros . . . . . . . . . . 1.5.1 Getting data from the user . . 1.6 Appendix . . . . . . . . . . . . . . . 2 Syntax Highlighting 2.1 Basics . . . . . . . . . . . . . . . . . 2.1.1 Filter Sets . . . . . . . . . . . 2.1.2 Switches . . . . . . . . . . . . 2.1.3 Reserved Words . . . . . . . . 2.2 Filter Sets . . . . . . . . . . . . . . . 2.2.1 The Filter Sets Dialog . . . 2.2.2 Set Expressions . . . . . . . . 2.3 Switches . . . . . . . . . . . . . . . . 2.3.1 Global Switches . . . . . . . . 2.3.2 The Switches Dialog . . . . 2.3.3 Examples . . . . . . . . . . . 2.4 Reserved Words . . . . . . . . . . . . 2.4.1 The Reserved Words Dialog 2.4.2 A small example . . . . . . . 5 6 8 9 14 17 20 21 24 25 26 29 29 30 30 30 31 31 32 33 34 34 36 38 38 39

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . .

CONTENTS

Chapter 1 Macros
Macro programming in WinEdt can be frustrating at rst. Common sources of frustration for rst-time macro programmers are: not knowing what macro functions are available (or appropriate) for the desired task, not understanding the exibility of the macro functions that are available, or idiosyncracies of the WinEdt language. This chapter discusses all these areas, gives numerous examples of macro programming in WinEdt, and shows some dirty tricks and some conventions that are beginning to be formed by the WinEdt community. Please send reports of any errors or inadequacies (or neater examples, as well!) to jalex@uci.edu. This chapter discusses WinEdts macro feature on several dierent levels simultaneously. I have adopted a dangerous bend convention (rst used by the computer scientist Donald E. Knuth) to ag sections which go beyond what a rst-time macro programmer would be expected to know:
If your reading this on the rst time through, didnt you pay attention to the warning in previous paragraph? :-) Ill let it go this time, but you should really try to avoid sections like these in the future until you have experience with WinEdts macro language.

Sections which one might want to defer reading until the second or third time are marked with two dangerous bend signs. Whenever possible, macro examples will be given following A the two-column format employed in The L TEX Companion by Goossens, Mittelbach, and Samarin. The actual WinEdt macro code usually appears on the left-hand side with the corresponding WinEdt output appear on the right. For example,
InsText("WinEdt's language"); NewLine; InsText("...is powerful."); WinEdt's language ...is powerful.

1.1 An example macro 5

CHAPTER 1. MACROS

1.1

Basics

The simplest macros in WinEdts library insert text or additional lines into the current document.
Ins("String to insert"); Inserts a specied string (or the contents of a string register, e.g. %!9) using the current wrapping settings. InsText("String to insert"); Same as Ins except WinEdt will not wrap the inserted string if it goes beyond the right margin. NewLine; Inserts a new line at the current position. InsLine; Inserts a new line at the current position if and only if the current line is not empty. Used judiciously, this macro can prevent multiple blank lines from appearing in a document. Ins("This is some text..."); NewLine; NewLine; Ins("...and this is some more."); This is some text...

...and this is some more.

Ins("This is some text..."); InsLine; InsLine; Ins("...and this is some more.");

This is some text... ...and this is some more

If you want to insert several copies of the same thing, use Repeat(n, "...") where n is a number (or a register containing a numeric value) and the string parameter contains the argument to be repeated. The next example demonstrates how to insert multiple line breaks into a document using Repeat and NewLine:
Ins("From alpha..."); Repeat(2, "NewLine"); Ins("...to omega."); From alpha...

...to omega

Repeat also provides a way to move the cursor to a new position in the document when you know the oset from the current position. E.g.,
Repeat(20, CMD("Char Left")); Repeat(5, CMD("Line Down"));

moves the cursor twenty characters left and ve lines down from the current position. (Luckily, more ecient ways of moving the cursor exist since traveling long distances via Repeat takes time.) One important caveat about Repeat (which actually applies to many macros in WinEdts library) concerns using Repeat with macros that take string arguments. Since the second

1.1. BASICS

argument of Repeat is itself a string, if you attempt to repeat a command that takes a string argument, you must take care to correctly nest the strings. One correct use of Repeat to insert ten copies of the letter a into the document is the following:
Repeat(10, "Ins('a')"); aaaaaaaaaa

1.2 First use of nested strings One correct way of nesting strings uses dierent quotation marks to indicate the string inside the string (as above). Three more ways of writing this macro correctly are: Repeat(10, 'Ins("a")') Repeat(10, 'Ins(''a'')') Repeat(10, "Ins(""a"")"). It really doesnt matter which convention you adopt, so long as you understand it and can work with it. See 1.2.1 for a greater discussion of this topic.
Nothing keeps you from putting a lengthy sequence of macros in the second argument of Repeat: any valid macro sequence can appear in this second argument, including additional uses of Repeat. This allows one to write macros that perform a certain action a xed number of times. Notice the word xed occurring in that last sentence. Because the rst argument of Repeat is a numeric constant specifying how many times the second argument ought to be repeated, you must always know at the time of writing how many times the action must be repeated. More complicated macros, requiring an action to be repeated until some condition occurs (where it is not know ahead of time how many times the action will need to be repeated) should use the more powerful Loop macro.

Since weve already talked about moving the cursor around the screen, we might as well mention a few more ways to do it. If you just want to automate the kinds of cursor movements that you can do with the keyboardi.e., move around the screen, or scroll a bityoull be happy to know that these operations get handled via the exible CMD macro.
CMD("Char Left"); Move the cursor one character to the left. CMD("Char Right"); Move the cursor one character to the right. CMD("Line Up"); Move the cursor up one line. CMD("Line Down"); Move the cursor down one line. CMD("Page Up"); Move the cursor up one page. CMD("Page Down"); Move the cursor down one page.

The CMD macro provides access to many, many more commands than listed here. Think of CMD as the macro equivalent of a Swiss-army knife: over 170 dierent things can be done with CMD (admittedly, not all of them are ones that you will use frequently, if at all). Using

CHAPTER 1. MACROS

CMD is a simple two-step process: (1) look up the name of the desired command in WinEdts on-line documentation, (2) call CMD, giving it the name of the command in quotation marks as above.
Basically, CMD invokes commands that are essential to WinEdts behavior like cursor movements, screen refreshes, inserting bullets, setting bookmarks, and so on. One can also invoke all the dialog boxes used to customize WinEdts behavior, e.g., CMD("Preferences..."). Notice that there is some overlap with the Menu macro here, since both Menu and CMD can be used to bring up the Preferences dialog box. The need for two dierent macros, though, stems from the degree to which WinEdt allows customization of its menus. For example, one could delete the Preferences. . . choice from the Options menu, making it impossible to invoke the Preferences dialog box with the Menu macro. However, the Preferences dialog box will always be available via the CMD macro.

The real power of WinEdts macro language doesnt begin to emerge until we consider macros capable of conditional behavior taking dierent actions depending upon the current state of some parameter. But this means that WinEdt must allow for certain parameters to vary over time. Its time to consider variables or registers.

1.2

Variables/Registers

The WinEdt documentation uses the terms variable and register interchangeably, so lets rst note the dierence between the two terms, as traditionally understood, and then see where WinEdts macro language falls. Most (if not all) programming languages allow you to declare variables with names descriptive of their contents, like mass, number_of_loops, and so on. When you declare a variable, a chunk of memory gets allocated for storing a certain type of data.1 The important point being that variables have names. A register, on the other hand, cant be given a special name: its a chunk of storage that you have to refer to by whatever name the designer gave it. So what does WinEdt have? WinEdt has registersso you cant give them custom namesbut WinEdts registers are more exible than variables in languages like C. WinEdt will automatically allocate memory on an as-need basis for each of its registersyou dont have to worry about that at all (if you were the sort of person who would worry about it in the rst place). If you want, you can copy several pages of a document into a register that was previously used to hold a number, and WinEdt wont complain. So even if you dont like not being able to declare named variables to make your macros easier to understand, WinEdts registers can be quite powerful.

We can distinguish between four dierent types of registers: local, global, editor and document. There are eleven local registers, eleven global registers, and numerous document and editor registers. Luckily, though, one can usually identify the type of a register by looking at its name alone (though there are some exceptions). Identifying registers is easy: all WinEdt registers have a %-sign in front of them. Both editor and document registers consist of a single letter, upper or lower. The difference between these types of registers is primarily semantic rather than syntactic: editor registers contain values specifying the current state of WinEdt (current line position, column position, and so forth) and document registers contain values identifying properties of the
With some exceptions. Cs union type allows you to store dierent types of data in the same (approximately) chunk of memory.
1

1.2. VARIABLES/REGISTERS

active le type, le name, path, etc.). One cannot directly change the value of a document register, but macro functions exist for changing the value of editor registers. For example, %n, %p, and %t are all document registers; %n contains the name of the active le (the le currently having focus in the editor), %p contains the path of the active le, and %t contains the extension of the current le. So, if the active le is: c:\My Documents\Sundials-R-Us\Gnomon Sales\data.foo then %p equals c:\My Documents\Sundials-R-Us\Gnomon Sales, %n equals data, and %t equals .foo. Changing the active le causes the values of these registers to change. Examples of editor registers are: %c, containing the column position of the cursor and %l, containing the line position of the cursor. Note that certain editor registers eliminate the need for certain macros. Need the word the cursor is currently positioned on? Use %W, which contains the word located at the current cursor position (%L gives you the contents of the entire line). As I said above, editor registers can be changed: to change the value of %c, you have to move the cursor (manually or via the GotoCol or GotoCL macros). Local registers are the easiest to spot: %!0,. . . , %!9, and %!? are the eleven local registers. Global registers dier by lacking an exclamation point: %0,. . . , %9 are global registers (so is %I, but it has a special function well return to later). From the point of view of a macro programmer local registers are no dierent than global registers save that global registers retain their values between WinEdt sessions and should not have multi-line values. The prohibition on multi-line values arises because global registers have their values stored in the WinEdt.ini le and multi-line values can corrupt the WinEdt.ini le.
So what? Well, most of the time you will probably want to use local registers when writing WinEdt macros (especially ones that just save on some typing). But using global registers can allow you to create state-sensitive macros that respond dierently depending upon the current state of the editor, where the editor remembers its current state from time to time. Take a look at the macros located in %B\macros\math. These macros employ the method of global A A registers to toggle between two modes: a L TEX math mode, and a L TEX normal text mode. A number of macros are provided to hook to active strings. When done so, a gets translated to \alpha when math mode is on, but gets left as a in normal text mode.

1.2.1

Strings and things

Most of the macros in WinEdts standard library take arguments, some several. When reading arguments there are two dierent types of arguments WinEdt may expect to nd: numeric and string. A numeric argument can be a constant e.g., 17 a register (local or global) currently set to a numeric value, or an integer expression using the standard arithmetic operators +-*/. An integer expression means any well-formed expression using those operators, registers containing well-formed integer expressions, and constants (with parentheses used for grouping. The following are examples of valid integer expressions: 2+3 ((2+3)/16)

10 %!1+%!2 ((%!1*%!2)/12)*(-17/%!3)

CHAPTER 1. MACROS

The following macro illustrates a simple use of integer expressions:


1 2 3 4 5 6

LetRegNum(1,1); LetRegNum(2, "((12+%!1)/4)"); LetRegNum(3, "%!2 + %!2"); InsText("Reg. %%!1 = %!1"); NewLine; InsText("Reg. %%!2 = %!2"); NewLine; InsText("Reg. %%!3 = %!3");

Reg. %!1 = 1 Reg. %!2 = 3 Reg. %!3 = 6

1.3 Using integer expressions Line 1 stores the numerical value 1 in register %!1. In line 2, register %!2 receives the numerical value 3 because the result returned by WinEdt when performing arithmetic division truncates decimals. Finally, line 3 assigns to register %!3 the value 6 because when WinEdt processes the second argument of LetRegNum, register %!2 expands to the value 3 and 3 + 3 = 6 (in case you didnt know). Note the use of repeated %-signs in lines 46. Since WinEdt uses percent signs in the names of registers, you must tell WinEdt when you really want a percent sign instead of a register name. This is done by including two percent signs (%%) at the appropriate place. People familiar with other macro languages, such as TEX, are probably already familiar with the need to repeat certain special characters; if you are not such a person, just remember to type %% whenever you want % to appear in the text and you will get by ne.2 One occasionally needs to nest strings when writing simple macros (see example 1.2) and almost always when writing more complicated macros (see examples 1.4, and 1.5). Mastering nested strings is essential to becoming a real pro at WinEdts macro language. WinEdt recognizes several dierent ways to nest strings: Correct: "this 'this "this 'this is is is is a a a a 'string' inside a "string" inside a ""string"" inside ''string'' inside String" String' a String" a String'

Incorrect: 'this is NOT a 'string' inside a String' "this is NOT a "string" inside a String"
Although 1.3 used LetRegNum three times, that wasnt necessary. You might have a complicated integer expression that you want to evaluate several times, allowing the values stored in the registers appearing within that expression to change between evaluations. Using LetRegNum like we did above will Until you start working with nested strings. Then things become considerably more complicated even though the rules stay the same. Working with registers and percent signs inside nested strings will be dealt with in a later section, but see 1.4 and 1.5 for a taste of what will come.
2

1.2. VARIABLES/REGISTERS

11

give you headaches, since LetRegNum immediately evaluates its second argument to obtain an integer value for the assignment. The way around this problem is to store the complicated integer expression in a local register as a string. This allows one to suppress expansion of the named registers until you actually want to evaluate the expression. Heres an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 BeginGroup; LetReg(1,'((100*%%!2)+(10*%%!3)+(%%!2*%%!3)'); LetRegNum(2,0); LetRegNum(3,0); Loop('> Loop("> LetRegNum(4, ''%%!1'');> InsText(''%%%%%%%%!2 = %%%%!2, %%%%%%%%!3 = %%%%!3, %%%%%%%%!4 = %%%%!4'');> NewLine;> LetRegNum(3, %%%%!3+1);> IfNum(%%%%!3,3,''='',''Stop'','''');> ");> LetRegNum(2, %%!2+1);> LetRegNum(3,0);> IfNum(%%!2,3,"=","Stop","");> '); EndGroup; End;

1.4 Storing integer expressions for later use This macro produces the following output: %!2 %!2 %!2 %!2 %!2 %!2 %!2 %!2 %!2 = = = = = = = = = 0, 0, 0, 1, 1, 1, 2, 2, 2, %!3 %!3 %!3 %!3 %!3 %!3 %!3 %!3 %!3 = = = = = = = = = 0, 1, 2, 0, 1, 2, 0, 1, 2, %!4 %!4 %!4 %!4 %!4 %!4 %!4 %!4 %!4 = = = = = = = = = 0 10 20 100 111 122 200 212 224

How? First, the integer expression ((100*%!2)+(10*%!3)+(%!2*%!3) gets stored in %!1 (note the use of double parentheses to suppress expansion). Then %!2 and %!3 are initialized to 0. We then enter a doublynested loop. We take advantage of some expansion trickery in the rst line of the double loop. Here, LetRegNum is at level 2 since it appears in a string inside a string; if we wanted to suppress expansion of %!1, we would have to use at least four percent signs %%%%!1 to raise that occurrence of that register to level 3 (or higher). However, we dont want to suppress expansion since we want to use the contents of %!1 the complicated integer expression when assigning a value to %!4. Thus %%!1 gets expanded before WinEdt begins processing the LetRegNum call. When WinEdt begins processing the LetRegNum call, it rst expands the second argument of this macro the complicated integer expression we want to use! Thus, %!4 gets assigned the value 0 the rst time through the double loop, since both %!2 and %!3 equal 0.

String arguments can be explicitly specied e.g., "This is a string" or they can use registers (local or global) whose contents make sense when expanded. Make sense? Heres what I mean. Consider the macro InsText. It takes a single string argument and inserts it at the current cursor position. Clearly any string you specify makes sense here, for WinEdt will expand all registers present in the string and then insert the expanded

12

CHAPTER 1. MACROS

string into the document. However, consider the macro Loop. Here, the only strings which make sense are those which expand into a sequence of macros WinEdt can execute. Giving "This is a string" as an argument to InsText wont result in an error, but giving it as an argument to Loop will cause WinEdt to complain.
Dening the notion of a string making sense more precisely would require that we introduce the notion of a valid string, where the validity of a string depends upon the macro we are speaking of. (Exercise: prove that no string is valid for every macro.) I leave this to the hands of those more capable at theoretical computer science than myself.

New users often nd the way WinEdt handles string arguments one of the more puzzling aspects of WinEdts macro language. Heres an example:
LetReg(1, "This is some text."); Ins("%!1"); This is some text

LetReg takes two arguments, a numeric argument telling which one of the local registers (%!0,. . . ,%!9) to set and a string argument containing the soon-to-be value of the register.
registers can also be used in places where WinEdt expects a numeric argument and, by using registers with the Do macro, one can use registers to access string registers. The following example shows how to exploit this primitive type of pointer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 BeginGroup; LetRegNum(0,4); LetRegNum(1,5); LetRegNum(2,6); LetRegNum(3,7); LetReg(%!0, "Jellical cats come out tonight,"); LetReg(%!1, "Jellical cats come one, come all,"); LetReg(%!2, "The Jellical moon is shining bright,"); LetReg(%!3, "Jellicals come to the Jellical ball."); LetRegNum(8,4); Loop("InsText('Reg. #%%!8: ');> Do('InsText(""%%%%!%%!8"");> NewLine;> ');> LetRegNum(8,%%!8+1);> IfNum(%%!8, 7, '>', 'Stop','');> "); EndGroup;

%!4: %!5: %!6: %!7:

Jellical cats come out tonight, Jellical cats come one, come all, The Jellical moon is shining bright, Jellicals come to the Jellical ball.

1.5 Using registers as pointers Registers 0,. . . ,3 point to registers 4,. . . ,7 and are used to assign values to registers 4,. . . ,7 via LetReg. After assigning values to these registers, we loop four times, printing out the contents of one register (plus a NewLine) on each pass. Note how in the Loop macro we use register %!8 not only to control the number of iterations we perform, but also to determine the contents of which register we insert.

Omitting quotation marks in Ins("%!1") generates the WinEdt warning: String Parameter Expected. Why? Because Ins requires a string argument and %!1 isnt a string its the name of a local register containing a string. One might wonder why Ins("%!1") works, then. After all, why doesnt WinEdt interpret "%!1" as a string containing the sequence of characters %, !, and 1, causing the text %!1 to appear in the document? The answer lies in WinEdts treatment of strings parameters. Whenever WinEdt executes a macro requiring a string parameter, it rst expands the string parameter before using it.

1.2. VARIABLES/REGISTERS

13

When the parameter gets expanded, all registers at the bottom level (i.e., registers that arent suppressed) get replaced by their values, and every register of a higher level gets its level lowered by one. When WinEdt processes the macro Ins("%!1"), WinEdt replaces the register %!1 by its value because it occurs at the bottom level. WinEdt then inserts the translated expression into the document.
Strictly speaking, WinEdt doesnt keep track of levels at all; as far as WinEdt is concerned, all it works with are strings (or nested strings) and registers. My reason for introducing the concept of a level of a register is to make it easier to keep track of how many %-signs are needed at any given point. If you prefer not to think in terms of levels, heres how WinEdt actually handles strings and registers inside nested strings. %!1 is the name of a string register and gets replaced by its contents whenever WinEdt expands %!1. WinEdt also expands %% to a single percent sign: %. If you write a macro that has a register appearing inside a nested string, you can control when that register gets replaced by its value by the number of percent signs you stick in front of it. Consider the following macro: LetReg(1, "The best of all possible strings"); LetRegNum(2,1); IfNum(%!2, 1, "=",> "Repeat(3, 'InsText(""%%%%!1""); NewLine;')",> "Exit"> ); This macro is a convoluted way of inserting three copies of "The best of all possible strings" into the document (with line breaks appearing between each copy). However, it illustrates how WinEdt expands strings. When WinEdt begins executing this macro, it begins on the rst line with LetReg. WinEdt takes the string argument, expands it, and assigns the expanded string to register %!1. Since there were no register expressions occurring in the string argument, %!1 now contains The best of all possible strings. WinEdt then processes the second line and assigns %!2 the numeric value 1. When WinEdt begins to process the third line, it rst concatenates all the lines ending with > (this allows us to use line breaks to increase the readability of macros, since, technically, all WinEdt macros must lie on a single line). Once that has been done, WinEdt checks to see whether %!2 equals 1 or not. Since it does, WinEdt will execute the fourth argument of IfNum. Before WinEdt executes this fourth argument, it expands the string. After expansion, WinEdt faces the sequence of macros: Repeat(3, 'InsText("%%!1"); NewLine;') Notice how the four %-signs was reduced to two. Why? As WinEdt expanded the fourth argument of IfNum, it encountered the expression %% which it replaced by %. WinEdt then found another occurrence of the expression %% which also was replaced by %%. WinEdt left !1 alone since this was not part of any register. (WinEdt also adjusts the quotation marks so that the strings are nested correctly.) WinEdt then executes the Repeat macro. In doing so, WinEdt rst expands the second argument of Repeat. The sequence of commands after expansion is: InsText("%!1"); NewLine; which gets repeated three times. As WinEdt executes the InsText macro, it rst expands the string argument. In the process of expansion, WinEdt nally nds an occurrence of the register %!1 and replaces it by the text The best of all possible strings which WinEdt nally inserts into the document.

14

CHAPTER 1. MACROS

One might want to suppress WinEdts automatic replacement of registers (this happens most frequently when writing complicated macros containing nested loops). WinEdt provides two ways to suppress register replacement: (1) doubling the number of %-signs at the registers name raises its level by one (thus delaying its replacement), or (2) adding a ! before the string parameter prevents the entire string from being translated, eectively raising the level of every register inside the string by one. Suppressing translation of the entire string can be used to eliminate the need to include horribly long streams of parenthesis in deeply nested macros, but it doesnt provide the same level of control that method (1) has. LetReg(1, "It was..."); LetReg(2, "the best of times."); Ins("%!1 %!2");

It was... the best of times

LetReg(1, "It was..."); LetReg(2, "the best of times."); Ins("%!1 %%!2");

It was... %!2

LetReg(1, "It was..."); LetReg(2, "the best of times."); Ins(!"%!1 %!2");

%!1 %!2

1.2.2

Setting the values of registers

First of all, what registers have values one can modify from within a macro? Certainly the local string registers (%!0,. . . ,%!9), since these registers are intended to be the macro writers main temporary storage area. You can also modify the value of the global string registers (%0,. . . ,%9) but, if you do so, you must keep in mind the following very important restriction: Do not attempt to place an expression spanning multiple lines inside any global string register. Since the values of these registers are stored permanently in your WinEdt.ini le, this le can become corrupted if one assigns multi-line values to the global string registers. This restriction does not usually present a problem since one rarely is tempted to use a global register. And, in the cases where one does need a global register, there is either no need to use multi-line values, or this limitation can be easily circumvented. See ?? for further discussion. WinEdt provides several ways to modify the values of the local string registers. Modications which do not require any input from the user can be done using LetReg (assigning string values to local registers) or LetRegNum (assigning numerical values to a local register). WinEdt also provides a way to write interactive macros that collect input from the user, but discussion of these macro methods wont appear until 1.5.
LetRegNum(StrRegister: 0..9, Num_Expression: -999999999..999999999); This function can be used to assign the result of a numeric expression to the string Register (eg. %!0).

1.2. VARIABLES/REGISTERS
LetReg(StrRegister: 0..9, "Value"); Assigns the specied value to the String Register (eg. %!0).

15

If you really want to y in the face of danger, you can assign values to the global registers (but do heed the above warning) via LetStrthe global register equivalent of LetReg. LetStr assumes you know what youre doing when you make assignments and it will not check to see if you attempt to assign a multi-line value to a global register. As said before, unless you are careful this is a really easy way to irreversibly damage your WinEdt.ini le.
LetStr(StrRegister: 0..9, "Value"); Assigns the specied value to the Global String Register (eg. %0). WinEdt provides another way to set the value of local string registers which often comes in handy. GetSel copies the currently selected block of text into the specied string register, if the active le has selected text. If no text is selected, the behavior of GetSel depends on the value of its rst parameter: if 0, the specied string register receives the empty string; if 1, the specied string register receives the entire document. Obviously, one should exercise caution when using the latter case: you probably dont want to select the entire document if the next command is CMD('Delete') or CMD('Sort Lines...')! Occasionally, the need arises to check the character to the immediate left or right of the cursor, performing some conditional action based on what you nd there. GetSel provides a way to do this. Note, though, that this technique should only be used for isolated tests; using this technique inside a loop can cause the macro to run slowly because CMD('Select Char Left') and CMD('Select Char Right') do not execute quickly. The following macro demonstrates how to use GetSel in this way. Can you guess what this macro might be useful for?
1 2 3 4 5 6 7 8 9

CMD('Backspace'); CMD('Select Char Left'); GetSel(0,9); CMD('Char Right'); IfStr('%!9',' ','=','InsText("");End',''); IfStr('%!9','.','=','InsText("''''");End',''); IfStr('%!9',',','=','InsText("''''");End',''); IfStr('%!9','!','=','InsText("''''");End',''); IfStr('%!9','?','=','InsText("''''");End','InsText(''"'')'); 1.6 Conditional insertion of characters based on surrounding text

Lets walk through this macro to see what, exactly, it does. First of all, line 1 shows I lied when I said the macro checks the character to the left of the cursor; the macro begins by deleting the character to the left of the cursor. Once thats done, lines 24 copy the character to the left of the cursor into register %!9 and then move right. (We need to move right in line 4 because the command in line 2 causes the cursor to move one character to the left. If we did not move right one character, the text inserted in lines 59 would appear in the wrong place.) Lines 59 demonstrate one way of performing a multiple-way branchthat is, a conditional operation like Cs switch statement or TEXs \ifcase. Since WinEdt doesnt have command providing a multiple-way branch outright, we need to manufacture one by using multiple If... statements. Simply use one If... test for each possible branch, where each If... test (they need not all be the same) has an empty elseclause. If you want to specify a default branch, that is, a sequence of commands to be executed when none of your explicit If... tests succeed (always a good idea), put this sequence of commands in the else-clause of the last If... test. The above macro uses this construction: notice the use of End; to terminate macro execution after a successful IfStr test and how the IfStrs of lines 58 all have empty else-clauses.

16

CHAPTER 1. MACROS

Lines 59 check the character in register %!9 to see whether its a space, period, comma, exclamation point, question mark, or other (thats the default case). If its a space, WinEdt inserts into the text at the current cursor position. If its one of the four punctuation symbols, WinEdt inserts '' into the text. In all other cases, a single " gets inserted. Note how four '-marks were needed in lines 69 to get two '-marks in the text. When would such a macro be needed? Consider what would happen if " were made an active string with this macro bound to it. Then whenever a " was typed, WinEdt would replacing the " with one of three possibilities depending upon the character preceding the ". In other words, this macro would create smart quote behavior inside WinEdt, similar to that available in Emacs or word processors like Microsoft Word. Macro 1.6 runs slowly, so slowly it might frustrate some users. If you need to write macros that test surrounding text in order to decide what type of action to take, a faster way needs to be found. The author has found that, when speed is of the essence, avoiding CMD("Select Char Left") entirely gives the best results. Using CMD("Select Char Left") (or its sister command CMD("Select Char Right")) slows macro execution down because they use Windows messaging commands to perform the indicated actionsinternally, essentially the same sorts of procedures as if you move the cursor into position, held the Shift key down, and then moved either left or right. I.e., a Windows message is generated, sent through the message loop, dispatched, and processed. All that involves unnecessary computational overhead. This overhead can be avoided by using GotoCol, GotoLin, or GotoCL to move the cursor into the correct position, SetSel(0) to rst deselect everything, and then SetSel(1) (some other nonzero number may also be used) to begin the selection process. At this point, using GotoCol, etc. moves the cursor to the specied position, selecting all the text in between the cursor position when SetSel(1) was called at the new position. At this point, GetSel may be used to copy the selected text into the desired register. Macro 1.6, rewritten using these techniques, will then look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

CMD('Backspace'); Mark(0); IfNum('%c',1,'=','InsText("");End',''); SetSel(1); GotoCol('(%c-1)'); GetSel(0,9); SetSel(0); Goto(0); IfStr('%!9',' ','=','InsText("");End',''); IfStr('%!9','.','=','InsText("''''");End',''); IfStr('%!9',',','=','InsText("''''");End',''); IfStr('%!9','!','=','InsText("''''");End',''); IfStr('%!9','?','=','InsText("''''");End',> 'InsText(''"'')'); End; 1.7 Faster conditional insertion of characters based on surrounding text

After deleting the undesired " character in line 1, the cursor is correctly positioned for inserting the desired character(s) (either or '' or "). However, selecting the text requires that we move the cursor to the right by one, once the text has been selected. The use of Mark(0) in line 2, following by Goto(0) in line 8, performs these needed movements. If you try both forms of the macro on a fast (but not blazingly so) computer, you may detect the speed dierence between the two versions.

1.3. PROCEDURES AND FUNCTIONS

17

Aside from the local and global string registers, most of WinEdts other registers have their values changed indirectly through the use of other macro commands. For example, the editor registers %c and %l contain, respectively, the current column and line number (the current column and line number identies the position of the cursor in the active document). You cannot use LetRegNum to change the value of these registers. To change the value of %c or %l, you must either manually move the cursor (the changes are automatically reected in the values of %c and %l) or use GotoCol, GotoLin or GotoCL to jump the cursor to a particular spot in the document.
GotoLin(LineNum: 1..16000000); Go to the specied line and track the Carets position. GotoCol(ColumnNum: 1..99999999); Go to the specied column and track the Carets position. GotoCL(ColumnNum: 1..99999999, LineNum: 1..16000000); Go to the specied text position and track the Caret.

However, WinEdt does allows the user to change a few document registers directly through the commands SetFileName and SetFileMode. These commands will probably be used rather infrequently, but they are there in the event you need to use them.
SetFileName("File Name"); Changes the le name of the current document. SetFileMode("File Mode"); Changes the Mode of the current document and resets certain properties. Check WinEdts documentation on modes for more information.

1.3

Procedures and Functions

Macro languages can save time and reduce errors by automating repeated tasks. As people become more familiar with the exibility of a macro language, they tend to write longer macros to perform more complicated tasks. As macros grow in length, it becomes important (from the programmers point of viewthe macro interpreter couldnt care less!) to impose some sort of structure upon the macros, making them easier to follow and to write. This structure usually involves the creation of subroutines and procedures, so that a single subroutine can be called every time its needed, obviating the need to include that code at every point its used. A As a trivial example, suppose we want a macro to automatically create a new LTEX document, conguring the document by adding text at various places. In particular, suppose we want the document to look like this when the macro completes operation:

18

CHAPTER 1. MACROS

\documentclass[12pt]{article} \usepackage{amsmath} \usepackage{verbatim} \begin{document}

\bibliography{mybibliography} \bibliographystyle{plain} \end{document}

One way to code the macro without using subroutines (or procedures) would be:
1 2 3 4 5 6 7 8 9 10 11 12 13

CMD("New"); Mark(0); Ins("\documentclass[12pt]{article}"); NewLine; Ins("\usepackage{amsmath}"); NewLine; Ins("\usepackage(verbatim}"); NewLine; NewLine; Ins("\begin{document}"); NewLine; NewLine; Ins(" "); NewLine; NewLine; CMD("Go To Beginning Of Line"); Ins("\bibliography{mybibliography}"); NewLine; Ins("\bibliographystyle{plain}"); NewLine; Ins("\end{document}"); Goto(0); CMD("Next Bullet");

1.8 Macro without subroutines Without explicitly instructing WinEdt, in line 7, to go to the beginning of the line, the text of lines 810 would be inserted in the wrong column. Note how we used Mark in line 2 to memorize a cursor position and Goto in line 12 to return to that position. (The only reason for returning to that position is that it moved the cursor before the bullet, thus guaranteeing that the call to CMD("Next Bullet") would snap the cursor to the desired point.) This macro works perfectly well and most people would stop here. One problem, though, A is that LTEX documents have a certain structure to them: a preamble (everything appearing before the \begin{document}) and what Ill call a postamble (everything appearing after the \end{document}). This macro assumes the postamble to be emptya reasonable A assumption since L TEX ignores anything in the postamblebut, conceivably, there may be instances where the postamble would not be empty: version control information might be placed there, information about the author, etc. Since the preamble and postamble constiA tute logically separate parts of a LTEX document, lets rewrite the macro using subroutines to reect this fact. While were at it, lets include a subroutine for all the middle stu not appearing in either the preamble or postamble. (Although further enhancement of this macro might seem an unnecessary exercise in obfuscation, it illustrates how to use subroutines. In the future well see many cases where using subroutines clarify the operation of a macro.)

1.3. PROCEDURES AND FUNCTIONS

19

Strictly speaking, WinEdt doesnt provide for subroutines. WinEdt provides the Exe macro, which looks for a specied macro le; if the le exists, WinEdt executes the sequence of commands contained within that le. But this allows us to write code that behaves as if WinEdt allowed one to dene subroutines: simply write your code for the function, but save it to a le with a descriptive name and use Exe("...") to call the subroutine.

Rewriting macro 1.8 so it uses subroutines as described means we must create two macro les on disk, one for the preamble and one for the postamble. You can save your macro les wherever you want to, just make sure you remember where they are. The author nds it convenient to prex the name of macro les containing subroutines with two underscore characters, __, so he can tell just by looking at the le name that they arent stand-alone macro les (and that he might get into trouble if he deletes them!). Since the postamble subroutine is the easiest to write, lets start with it:
Relax;

1.9 Postamble subroutine for macro 1.8 Assume the postamble subroutine is saved as %B\macros\__Postamble.edt, where the %B register stands for the WinEdt base directory. The preamble subroutine isnt much longer:
Ins("\documentclass[12pt]{article}"); NewLine; Ins("\usepackage{amsmath}"); NewLine; Ins("\usepackage(verbatim}"); NewLine; NewLine;

1.10 Preamble subroutine for macro 1.8 (Assume the preamble subroutine is saved as %B\macros\__Preamble.edt.) And for the middle stu subroutine we have:
Ins("\begin{document}"); NewLine; NewLine; "); NewLine; NewLine; Ins(" CMD("Go To Beginning Of Line"); Ins("\bibliography{mybibliography}"); NewLine; Ins("\bibliographystyle{plain}"); NewLine; Ins("\end{document}");

1.11 Middle stu subroutine for macro 1.8 (Assume it was saved as %B\macros\__MiddleStuff.edt.) When rewritten using subroutines, macro 1.8 looks like:

20

CHAPTER 1. MACROS
CMD("New"); Mark(0); Exe("%B\macros\__Preamble.edt"); Exe("%B\macros\__MiddleStuff.edt"); Exe("%B\macros\__Postamble.edt"); Goto(0); CMD("Next Bullet");

1 2 3 4 5 6 7

1.12 Macro with subroutines Compare macro 1.12 to 1.8. Trivially, we see that 1.12 is shorter, but not so much so that this should convince us to use subroutines whenever possible. The author believes that the logical structure of 1.12 is clearer than 1.8 but this, too, may be disputed. However, three advantages of using subroutines are as follows: (1) future modications of macro code become easier since the code has been broken down into bite-size chunks, and (2) debugging macros becomes easier since one can (usually) debug the subroutines in isolation from the main code, and (3) the need to use strings containing strings containing strings. . . disappears. Judicious use of subroutines should enable you to avoid working with nested strings of level greater than two. If you nd WinEdts conventions for nested strings and repeated %-signs confusing, this alone might convince you to use subroutines.
Using subroutines can make writing complicated macros easier, too. You can dene Exe to be an active string so that when you double-click on it, WinEdt will automatically try to open the specied macro le. Simply go to Options Settings... Active Strings and bind the macro [Do('Open(%?)')] to a double-click of Exe(?).

1.4

Recursion

Good macro languages allow for recursive programming, and WinEdts language does not prove exception to the rule. Recursive programming in WinEdt requires that we use the method of subroutines sketched in 1.3. Since writing recursive functions often requires several macro les to be saved to disk, we need to indicate in our examples what macro code belongs to which macro le. The convention that shall be adopted is to surround macro code by comments indicating the le name and where the le ends. This allows us to include the code for several les in the same display. E.g.,
// Filename: _MyMacro.edt ... // Endfile // Filename: _MyOtherMacro.edt ... // Endfile

Consider the following simple example:

1.4. RECURSION
// Filename: %B\macros\guide\_recursion.edt InsText("a"); IfNum(%c,10,'<',Exe("%B\macros\guide\_recursion.edt")',''); InsText("b"); // Endfile

21

1.13 A simple recursive macro When started at the beginning of a line, WinEdt produces
aaaaaaaaabbbbbbbbb

If started ve spaces in, we get


aaaabbbb

(Only four as appear when started ve spaces in because column numbering starts at 1. When at the beginning of a line, the cursor is in column 1. Five spaces in, the cursor is at column 6, so WinEdt can only insert four as until the test fails.)

1.4.1

A lengthy example

Consider the following problem, posed by Heiner Richter: can WinEdt be customized so that it will automatically convert any string of digits (such as 1235678) to the form 1.235.678? Before starting, lets generalize the problem to the following: customize WinEdt so that it will take a string of digits and insert the contents of a string register after every three digits (counting from the right). This generalization makes the macro more useful since conventions vary on whether to use a period, comma, raised dot, or space when separating digits. First o, lets consider how this macro will be invoked. We dont want to invoke the macro until the digit string has been fully entered, but how do we postpone execution of the macro until the string has been completed? One natural way of doing this is to use active strings. But what active string? We cant make every digit active because WinEdt will then invoke the macro each time we type a digit. We could require that the user wrap the digit string will an identier unlikely to occur in ordinary text, say @digits{...}, but this solution is clumsy: we want the macro to make it easier to type a string of digits, and typing @digits{12345} when you want 12,345 just makes more work for yourself. One solution recognizes that a digit string has, as a natural delimiter, a digit followed by a space. Thus we can make the strings 0 (zero followed by a space),. . . , 9 (nine followed by a space) active. This guarantees that the macro gets invoked only at the end of a digit string. Second, we note that the macro will need to do some initialization: we need to place the desired delimiter into a string register and set a counter to 0 so that we can count o three digits at a time. Now, we can write the macro using either Loop or recursion. The problem using Loop is that it requires us to nest strings andif the macro is longthis can

22

CHAPTER 1. MACROS

be a headache. However, if we use recursion, we have to be careful of how we set the initial conditions. We cannot set the initial conditions inside the same subroutine used for the recursion because each time the recursion occurs the initial conditions will be re-established! Consequently, we will put the initialization code in a macro called _APstartup.edt, calling the recursive subroutine at the very end.
1 2 3 4 5 6 7 8 9 10

// Filename: %B\macros\ap\_APstartup.edt BeginGroup; StartWorking("Adding separators..."); LetReg(5,','); // <--- Change this if you want commas instead of periods LetRegNum(6,0); // Stop indicator LetRegNum(7,%c); // Original column position LetRegNum(8,0); // Found digit indicator GotoCol('%c-1'); // Backup behind the space delimiter Exe('%B\macros\AddPeriods\_APchew.edt'); // Endfile

1.14 Initialization routine for the add periods macro Line 1 contains BeginGroup so that the separator addition can be undone with a single Undo. We call StartWorking in line 2 out of courtesy for the user since the macro might take some time to complete. Register %!5 contains the delimiter string (here we use a comma). Register %!6 contains a binary ag indicating whether the macro has completed (well see later why this is necessary). Register %!7 contains the column that the cursor will return to when macro execution nishes. Finally, register %!8 contains the number of digits weve found so far. After initialization, WinEdt calls the macro _APchew.edt. This subroutine decides where to place the separators. Consider part of it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 SetSel(0); SetSel(1); IfNum(%c,1,'=',> 'Exe("%B\macros\AddPeriods\_APend.edt")',> ''); GotoCol('(%c-1)'); GetSel(0,9); IfStr('%!9','0','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\_APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\_APend.edt")','');

1.15 Part of the recursive subroutine called in 1.14

1.4. RECURSION

23

Lines 15 copy the character to the left of the cursor (if there is one) into register %!9. The test in line 2 checks to see if we at the beginning of a line (calling GotoCol with a negative argument generates an error message). If the character to the left of the cursor is a digit, one of two possible actions can occur. If we have counted four digits, insert a separator, since three digits have passed since the end of the digit string or the last separator inserted, and then set the digit counter (register %!8) to zero again. If we have not yet encounter four digits, add one to the digit counter and move left one space. Now, the trick is telling whether the character copied into register %!9 is a digit or not. Recall the discussion on page 15 about how to get the logical equivalent of a switch statement in WinEdts language. We use that technique here: we have ten dierent IfStr tests to see whether the copied character is 0,. . . ,9. In 1.15, we have only listed the code for the rst IfStr test (the complete code can be found in the Appendix). Line 7 of 1.15 increments register %!8 by 1. Line 8 checks to see if this is the fourth digit found. If it is, all text is deselected by a call to SetSel. (At this point we have not yet deselected the character copied into register %!9. Without deselecting it, the InsText of line 11 would delete that digit!) Finally, we move the cursor to the left one column, reset the digit counter, and increment the counter tracking the number of separators inserted. Nothing is done if the character stored in %!9 was not the fourth digit found. When the character in %!9 is not a digit, the ten IfStr tests in _APchew fail. Then %!6 gets assigned the value 1 (this occurs at line 155 in the full listing of the macro in the appendix). The IfNum test of macro 1.15, line 20, calls the shutdown routine. The complete listing of this macro is listed below:
// Filename: %B\macros\ap\_APend.edt GotoCol(%!7); SetSel(0); EndGroup; StopWorking; Exit; // Endfile

The shutdown routine moves the cursor to the correct nal position, deselects all text, ends the group started in _APstart.edt, and returns the cursor to its normal mode.
You might wonder why we hassle with the %!6 ag indicating when the processing of the digit string has completed. The reason has to do out of concern for speed. Exit causes the macro to prematurely terminate, preventing it from backing out of the recursive Exe calls properly. Ordinarily, one wouldnt need to do this, but the multiple-way branching used in this macro results in a signicant speed decrease.

24

CHAPTER 1. MACROS

1.5

Interactive Macros

WinEDT provides several macros that can be used to make your macros a little more userfriendly. The macros listed below fall into three types: getting data from the user (either numeric or string), prompting the user to make a choice at a certain key point in macro processing, or displaying the notorious Windows hourglass cursor (with an explanatory message in the WinEDT message area). The particular macros are:
EnterLongReg(StrRegister: 0..9, "Prompt","Caption") Prompts you to enter the value of the specied string register (%!0. . . %!9). Allows multi-line values. EnterReg(StrRegister: 0..9, "Prompt","Caption") Prompts you to enter the value of the specied string register (%!0. . . %!9). The value is a one-line string. GetLongString("Prompt","Caption") Same as EnterLongReg except that the value is stored in a special %!? string register (an extension of %!0. . . %!9) GetString("Prompt","Caption") Same as EnterReg except that the value is stored in a special %!? string register (an extension of %!0. . . %!9) GetDim Displays the dialog allowing you to enter the values of %!x and %!y numeric registers. Their values are used in Macros that insert n m environments (such as Array.edt). GetCounter Displays the dialog that allows you to enter the values of %!z numeric register. Its value can be used for repeat loop and such. . . Prompt("Prompt",Type,Buttons: 0..3, "Macro 1","Macro 2") Displays the dialog box with the specied prompt. Macro execution is resumed after the user closes the dialog box. Type and Buttons above can be any number in the range 0,1,2, or 3. These numbers alter the dialog boxes appearance and behavior in the following way: Types 0, 1, 2, or 3 tell the dialog box to appear as either a Information, Conrmation, Warning, or Error box, respectively. Button values 0, 1, 2, or 3 cause the dialog box to have OK/Cancel buttons (where clicking on Cancel terminates macro execution), an OK button, OK/Cancel buttons (where clicking on Cancel will invoke a special user macro), or Yes/No buttons. StartWorking("Message") Changes the Cursor to the Hour Glass form and displays the specied message in the last eld of the Status Line. Intended to indicate time-consuming macros, StopWorking Restores the cursor and removes the message from the status line.

With the exception of the last two macros (whose function should, hopefully, be moreor-less clear), all of these macros cause a dialog box to be displayed, allowing the user to enter a certain kind of data. If youve never done any Windows programming before, you might feel a certain rush of power at the ability to create a dialog box with such ease.

1.5. INTERACTIVE MACROS

25

1.5.1

Getting data from the user

Close inspection will reveal some apparent redundancy between some of the above macros. For example, the macros GetLongString and GetString seem to be two ways of doing the same thing (sticking a string in the register %!?), and the dierence between EnterLongReg and EnterReg also might not be immediately clear. The basic dierence between them concerns the form of the dialog box that gets created. If you use either GetLongString or EnterLongReg the dialog box that appears has a large multi-line edit box allowing the user to type in whole paragraphs of text. On the other hand, GetString and EnterReg only use a single-line edit box, which (I suppose) implicitly tells the user to be concise. WinEdt doesnt perform any length checking on the argument for either of the short entry commands, so nothing prevents the user from typing an entire paragraph into the single-line edit box if they want. The following macro illustrates one possible use of the GetString command:
1 2 3 4 5 6 7 8 9 10 11 12 13

BeginGroup; GetString("What environment do you want to create?","Insert Environment"); LetRegNum(9,%c); // Store current column number Mark(0); InsText("\begin{%!?}"); NewLine; GotoCol(%!9); InsText(" "); NewLine; GotoCol(%!9); InsText("\end{%!?}"); Goto(0); CMD("Next Bullet"); EndGroup;

1.16 The Insert Environment macro Line 1 begins a group so that the entire macro operation can be undone by a single undo operation. Line 2 contains the call to GetString that asks the user to type in the name of the environment that they want to insert. Line 3 stores the current column position of the cursor in the register %!9 so that we can correctly position the rest of the lines. For example, suppose the user wants to use this macro to insert a cases environment inside of an equation. Typically, this macro will be invoked when the user has typed only the following:
and so we define the incredibly important function as follows: \[ f(x) =

where the cursor is at the point indicated by . Now, without keeping track of the column that the Insert Environment macro was invoked from (and consequently without including lines 3, 7, and 9 in the macro denition), the macro output would look like:

26
and so we define the incredibly important function as follows: \[ f(x) = \begin{cases} \end{cases}

CHAPTER 1. MACROS

which is probably not what the user wanted. The Newline macro creates a new line and moves the cursor beneath the f, the InsText(" ") macro inserts the box directly beneath the x, and the second Newline macro creates a new line and moves the cursor directly beneath the (assuming that WinEdts default line wrapping conventions are on). Including lines 3, 7, and 9 causes the macro to insert the environment so that the \begin and \end have the correct vertical alignment like so:
and so we define the incredibly important function as follows: \[ f(x) = \begin{cases} \end{cases}

1.6
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

Appendix

SetSel(0); SetSel(1); // Check to see if we are at the beginning of a line. If so, // invoke __APend. IfNum(%c,1,'=',> 'Exe("%B\macros\AddPeriods\__APend.edt")',> ''); GotoCol('(%c-1)'); GetSel(0,9); IfStr('%!9','0','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','1','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",>

1.6. APPENDIX
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','2','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','3','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','4','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','5','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''>

27

28
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','6','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','7','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','8','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> ''> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")',''); IfStr('%!9','9','=',> 'LetRegNum(8,"%%!8+1");> IfNum("%%!8","4","=",> "SetSel(0);> GotoCol(''%%%%c+1'');> InsText(''%%%%!5'');> GotoCol(''%%%%c-1'');> LetRegNum(8,0);> LetRegNum(7,''%%%%!7+1'')",> ""> );> Exe("%B\macros\AddPeriods\__APchew.edt")',> 'LetRegNum(6,1)'> ); IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

CHAPTER 1. MACROS

Chapter 2 Syntax Highlighting


Syntax Highlighting is another one of the powerful features of WinEdt. Certain parts of your text can be highlighted, that means formatted visually in a dierent color or font. This allows to have your document structured in an easy to spot way. In addition, Syntax Highlighting can help you to avoid typos. The behaviour of the Syntax Highlighting feature is dependent on the mode of your document. Of course, you can customize the highlighting completely. To show you how is the aim of this chapter.

2.1

Basics

Before experimenting with Syntax Highlighting settings, it is a good idea to save your current state of WinEdts customization. All customizations are stored in the le winedt.ini1 . Use the menu entry Options Save Settings As... make a backup copy of your current winedt.ini under another name. If you want, you can then revert to your previous state by renaming this le to winedt.ini. You also have a factory settings winedt.ini in the subdirectory \support. WinEdt provides a way to exchange settings from some dialogs (including the Syntax Highlighting) via an human-readable format. You can access this feature by clicking the secondary mouse button in the dialog. Now, the context menu oers you the entries Extract..., Append... and Load From....

Syntax Highlighting in WinEdt is based on the idea of three dierent highlighting levels. These levels specify the syntax elements which are subject to highlighting. Believe it, you want it that way!
1

If you havent specied an alternative ini-le when calling WinEdt.

29

30

CHAPTER 2. SYNTAX HIGHLIGHTING

2.1.1

Filter Sets

Take, for example, a simple text where you give some numeric values. Some of these values are negative, and you want to spot them immediately. A good way to achieve this is to use a dierent color for the minus sign in front of theses negative values, say blue. No problem, you tell WinEdt to color all occurrences of the minus sign blue.2 To oppose the negative values, you decide to mark important positive values with an explicit plus sign in front of them. Again, you want this plus sign to be in an other color than black, this time red. This is nice and also easy, and would be done using a syntax element what WinEdt calls a Filter Set.

2.1.2

Switches

You look now at your partly colored text. It looks good, but youd wish that also the values itself would be colored, not only minus and plus. From what you know now, you could tell WinEdt to color all 1s green, all 2s green, and so on. It would work, and you could even group the numbers together, using only one of WinEdts Filter Sets. But no, you arent satised with that, you want the negative numbers blue and the important positive numbers with a plus before it in red. You have now entered a new dimension of highlighting, the dimension of the Switches. Switches set a number of successive, random characters to a certain color (or font), depending on a condition. In our case, the condition is the minus or plus sign. If a minus sign is followed by a number, then you want to have both in blue. You dont want numbers without minus or plus to be colored, nor do you want a blue hyphen or such. The condition itself is specied as a Filter Set, as we have already seen.

2.1.3

Reserved Words

There is another syntax element that you could want to highlight. Switches switch to another look depending on the condition, and the order of the characters to highlight doesnt matter; they only need to match some criteria (such as being a number in our example)3 . To impress and atter your boss, you want now to have his name, Miller, in bold font. You dont want to have all uppercase Ms, all is, ls, es and rs in bold, just this specic order that forms the word Miller. This is a so called Reserved Word, and of course you can base it on a certain condition too, e. g. a Mr before it. Most problems that you have for highlighting can be solved with a combination of these three syntax elements.
2 3

How this is done is explained later in this chapter. Often the criterion is be any character.

2.2. FILTER SETS

31

2.2

Filter Sets

As we have seen, Filter Sets form the basic syntax element in WinEdts Syntax Highlighting. They are used in the other two highlighting syntax elements, the Switches and the Reserved Words. In addition, Filter Sets are also used in the context of Active Strings.

2.2.1

The Filter Sets Dialog

If you look into the dialog for Filter Sets (open Options Highlighting on the rst tab page), youll see that there are a lot of predened Filter Sets. This is the list on the left of this dialog. Browse through the entries and check how these look, but do not delete or modify any of these predened sets. You can, of course, add your own entries here. In fact, this is why this chapter is written. The order of the entries in the list box does not matter.4 Use the secondary mouse button (usually the right button) to Insert a new entry. Type in a descriptive name for your Filter Set (it is not restricted to one word, use whatever you want). This name is not to be confused with the denition of the Filter Set! Immediately below the list of Filter Sets there is a eld which is called Denition. You specify the criteria for the Filter Set selected above here. Please see section 2.2.2 for information about these Set Expressions. In the middle column in this dialog there are two elds which are Filters, Before: and After:. If your Filter Set is dependent on another Filter Set, you specify this here. To extend our introductory example, you could want to have a Filter Set which is +-. This is either a plus Before a minus or a minus After a plus. To use a Filter Set in this list box it has to be dened rst. Although you could write directly in this box (say, a +), this alone is not functioning without a matching Filter Set entry on its own. The checkboxes for the lters can specify further restrictions: if the option Before: is checked then the beginning of line is not an admissible position for a character to belong to the lter, if the option After: is checked then the end of line is not an admissible position for a character to belong to the lter. Below the Filters eld is Options, where you can enable a Filter Set for highlighting of certain modes. You dont have to enable highlighting for a Filter Set in order to use it elsewhere! You only enable a Filter Set if you want to highlight something directly with it. A Filter Set can be given a priority from 0 (lowest) to 9 (highest), which determines highlighting inside Switches and Reserved Words.
Filter Sets (as well as Switches and Reserved Words) are highlighted with respect to the Priority value. Priority can be specied to determine highlighting of the currently selected lter set inside Switches and Reserved Words. This does not mean that when two or more Filter Sets compete, the one
4

As long as you do not specify entries with the same name. In this case, the last of these entries is used.

32

CHAPTER 2. SYNTAX HIGHLIGHTING

with the higher priority is highlighted. In such a case, always the last specied Filter Set applies, regardless of priority. However, a Filter Set with a high priority rules over a Switch with a lower priority.

The Sample eld shows you how your Filter Set will look if you have given it certain Font or Color attributes in the right column of this dialog. Of course, this does only apply in your document if it matches the enabled mode denition.

Note that certain elds in this dialog (or, to be correct, in almost every WinEdt dialog) give useful context-sensitive menus, that means they respond to the secondary mouse button.

2.2.2

Set Expressions

You use Set Expressions to specify the Denition eld in the Filter Set dialog. There are four predened sets: Numeric, Alpha, Upper and Lower. These sets are language sensitive, that means their denition is dependent on the Language Settings in Windows Control Panel. To dene sets, you use the following syntax: character : Either "?", where ? stands for any character, or #{code}, with 0 < code <= 255. interval: character..character set: Either a predened set or a [sequence of characters and intervals]. [] is also allowed and means the empty set. operators: ~ (not), + (union), - (dierence), * (intersection)

2.3. SWITCHES Examples: Character: "a" "b" #32 Interval: a..z Set: Numeric ["ab"] ["a","b"] ["+-*/^<>=(){}&#[]"] [] Operators: ~[] Alpha+Numeric Alpha-Lower SetA*SetB the letter a, the letter b, the ASCII code 32. the lowercase letters a, b, c . . . z. the numbers 0 to 9 (a predened set), the letters a and b, also the letters a and b, Math stu (from the default WinEdt entry), the empty set.

33

not empty, that means All, union of the predened sets Alpha and Numeric, thus specifying all letters and all numbers, all letters minus the lowercase ones, giving the uppercase ones (which happens to have its own predened set, Upper), gives you the elements that are in SetA as well as in SetB. (I cannot think of a straightforward example, sorry . . . )

These examples show the basics of dening Set Expressions. We will come to some more complicated denitions in later, concrete examples. Making up not-too-easy examples for Filter Sets only is hard. Since a good and sensible Switch usually requires a good and sensible Filter Set too, we will give its both denitions in the section about Switches. If you are not sure about the correct syntax of a Filter Sets denition: dont hesitate to experiment. You cannot do much wrong as long as you do not modify WinEdts default entries. Enable the Filter Set you are working on and give it an easy to spot color. If you think it is right, you can again switch it o and use it in e. g. the Reserved Words tab page (remember, you dont have to highlight a Filter Set to use it elsewhere).

2.3

Switches

A Switch tells WinEdt to highlight certain parts of your text. These parts are started by a clearly dened condition, and are ended on another condition. Unless in Filter Sets, you dont dene the part of the text to highlight, you dene which condition switches highlighting on instead.

34

CHAPTER 2. SYNTAX HIGHLIGHTING

2.3.1

Global Switches

Global Switches are one of the things that WinEdt 1.414 (the 32-bit version) introduced. These allows highlighting to extend over more than one line. Because of the complicated algorithm WinEdt has to use, enabling Global Switches can be slow, especially for longer documents. By default, Global Switches are only enabled for TEX documents. You can set the settings for other modes via the menu Options Preferences Defaults. Here is a Disable Global Switches checkbox. Global Switches for the current document can be enabled or disabled in Project Document Settings Options (accessible also from the Mode Field in the status line). In the examples it is assumed that you have turned on Global Switches, but you will not always need it. If highlighting over more than one line doesnt work, check your setting.

2.3.2

The Switches Dialog

To dene or modify a Switch, you use the second tab page in Options Highlighting. As in the tab page for Filter Sets, there are already some entries, which give an idea how such an A entry looks. If you use WinEdt to write TEX or LTEX documents, you will recognize some of these Switches. As in the other dialogs for Syntax Highlighting(and almost every dialog in WinEdt), a mouse click with the secondary button (which is usually the right one) pops up a context menu with commands for manipulating entries, such as Inserting a new one. In the dialog for dening Switches, only the middle column diers from that of the Filter Sets dialog. Since you should know a little about Filter Sets when playing with Switches, Im not going to explain the rest of the dialog here. The remarks in the section 2.2.1 (The Filter Sets Dialog) apply here as well. In the middle column in this dialog there are two elds which are Filters. These say Begin: and End: here. As you can imagine, you tell WinEdt what Filter Set begins or ends a Switch here. To select such a Filter Set from the list, it has to be dened before. To understand what the checkboxes in front of the Begin: and End: elds do, we rst must explain how the Denition eld comes into play. The Begin: Filter and Denition To take up our example in the introduction of this chapter, assume we want to specify a Switch for marking all negative numbers. There are basically two dierent possibilities to make such a combination of a Filter Set and a Switch work. In a rst case, you only need to give the minus Filter Set in the Begin: eld, provided you have set up the Filter Set. The eld Denition can stay empty. Since highlighting starts according to the Begin: eld, the minus and the following number will be highlighted. The second possibility is to specify a - (without the quote signs) in the Denition eld, and Numeric in the Begin: eld (with the checkbox not checked). Since Numeric is a

2.3. SWITCHES

35

predened set, you dont even have to create a new Filter Set. As already said, highlighting starts according to the Begin: eld. In this case, we have Numeric there, so the numbers in our document will be highlighted. But, and this is the crucial point, the minus will not be highlighted! You have to decide whether this is acceptable. You could, of course, set up and enable a Filter Set with minus in addition. While this is practicable, it is usually better to think about other ways.
Now, there seems to be a third way of setting up this Switch. This would be to make - the Begin: specier, and to set Numeric as the Denition. Good idea, but . . . With Filter Sets, you were allowed to have (predened) sets in the Denition eld. This, however, is not possible with Switches. WinEdt treats text in the Denition eld in the Switches dialog verbatim! Specifying Numeric here would expect the word Numeric after the minus sign.

Lets sum up what this Begin: checkbox does: Begin: unchecked: Definition + Filter Set The Switch starts if the characters specied in the Denition eld (taken verbatim) precede the syntax elements as specied by the Filter Set in the Begin: eld. The characters in the Denition eld are not highlighted since Syntax Highlighting starts if the Filter Set matches. Begin: checked: Filter Set + Definition The Switch starts if the Filter Set in the Begin: eld matches and is followed by the Denition, which is taken verbatim. Here, Denition is highlighted, since it comes after the Filter Set which begins the Switch. In the Options section of this dialog there is a checkbox named BOLN (Beginning Of Line). If this box is checked, then the whole Switch only applies if it starts at the beginning of a line. Ending a Switch After setting up a condition which begins a Switch, you now need another condition which end this Switch. This is achieved by the End: eld in the Filters section. Also, a Switch has a Scope in which it is highlighted. Text outside the scope of a Switch is not highlighted; this is the second condition which ends a Switch. As you see, the listbox for End: gives the list of all dened Filter Sets. The Switch is ended when the End: Filter Set applies. The checkbox before the End: eld tells whether the occurrence of this Filter Set is part of the Switch, that means whether it is highlighted or not. Now, what is the scope of a Switch? The Scope eld in the Options section can have a number from 0 to 4. The meaning of these numbers is: 0 The Switch ends with the rst non-alpha character. This is meant for TEX control sequences. 1 The Switch ends at the end of line. This is useful for one-line comments in programming languages.

36

CHAPTER 2. SYNTAX HIGHLIGHTING

2 The Switch ends at the hard return (not used). 3 The Switch ends at the rst empty line. This can be used for TEX Math sequences ($...$). 4 The Switch ends with the specied End: Filter Set. Take care, as this is potentially slow in large documents. Priority Switches can be nested. The default settings of nested switches are combined if the switches have equal priorities and the inner switch has the option Default Font or Default Color enabled. A Switch with a lower priority is ignored inside a Switch with greater priority.

2.3.3

Examples

The following examples are given in the syntax which WinEdt uses to Extract... the entries in the Syntax Highlighting dialogs. This syntax should be self-explanatory. The Negative Number scheme Let us see how the example with the negative number can be set up. We already noted that here are (at least) two ways to achieve this. We begin with the rst possibility, which only needs a Filter Set to begin the Switch. The Filter Set with which our Switch begins is simply a minus sign, followed by a number. We know already that there is a predened set called Numeric which provides exactly this. Thus, the Filter Set with the name -Numeric is:
Name:-Numeric Definition:["-"] Before:0 After:1Numeric Enabled:0 Priority:0 Color:1040

You can see, the Denition of the Filter Set is a minus, in a syntax that follows the rules from section 2.2.2, Set Expressions. The Before: eld is not checked (the 0) and empty. The After: eld contains the (predened) set Numeric and is checked, so that a minus ending a line does not get highlighted (without this, in addition to Numeric, the end of the line would be valid). The Filter Set itself is not enabled, since we only use it indirectly in the Switch. Priority is zero, the color is the standard color, but this does not come to eect since the Filter Set is not enabled. Okay. We have all what we need to begin the Switch. But how do we switch it o? The highlighting should stay in eect for all digits in the negative number, but not for text or other non-numeric characters. Therefore, a good End: condition is not numeric. But before we come to set this Filter Set up, lets think a little: a number, if it is not an integer,

2.3. SWITCHES

37

can also have a decimal point. If we would simply say: switch o on all but numbers, the decimal point would switch highlighting o too. Since we do not want this, we must also allow the decimal point. We can count the decimal point as numeric in this case, but of course it is not included in the predened set Numeric. Thus the Filter Set with the name Not Numeric is:
Name:Not Numeric Definition:~Numeric-["."] Before:0 After:0 Enabled:0 Priority:0 Color:1040

We remember: the tilde (~) is the negation symbol in the Set Expression syntax. The Denition reads as follows: we want not numeric, which leaves all other characters in the ASCII table except the numbers from 0 to 9. From this remaining set of characters we subtract also the minus sign.5 Thus, the Filter Set species all characters except the numbers from 0 to 9 and the minus. We can now use this set to end our Switch. Since this is possibility One, let us call this Switch Negative Number 1.
Name:Negative Number 1 Definition: Begin:1-Numeric End:0Not Numeric Enabled:1* Priority:2 Color:3082 Case Sensitive:0 BOLN:0 Scope:1

As said before, this switch does not need a Denition, since all is done with Filter Sets. The Begin: eld is checked (the 1). This means, we remember, that WinEdt expects the sequence Filter Set + Definition. As our Denition is empty, it would not matter whether this eld is checked or not; the Filter Set alone does the work. But in contrast to possibility Two, let us have this eld checked. The End: eld is not checked, since we do not want the Filter Set after our Negative Number to be highlighted. This Filter Set is our just created Not Numeric set. The Switch itself is enabled (since we want the highlighting), the * means all modes. Of course, you can restrict highlighting of this Switch to specic modes, just enter the names here (multiple entries divided by semicolons). Priority is 2, that means the Switch can be overridden by Filter Sets, Switches and Reserved Words with higher priority values. The color is set to 3082, which happens to be
Of course, you can specify this Filter Set in other ways, as long as it is logically correct and follows the syntax for Set Expressions.
5

38

CHAPTER 2. SYNTAX HIGHLIGHTING

bright green. The Switch is not case sensitive (why should it?) and it does not need to start at the beginning of the line (but it can). The scope of the Switch is 1, that means it is switched o at the end of the line if it is not already switched o before. Now, we have set up our rst highlighting scheme!

2.4

Reserved Words

Reserved Words are the third syntax element in WinEdts Syntax Highlighting algorithm. They are sequences of characters given explicitly, and like Switches, their activation can be controlled by certain conditions, the Filter Sets. Reserved Words are mostly used to get highlighting of keywords of programming languages. Given WinEdts TEX background (a programming language to typeset texts), it is not surprising that most of the entries in the default setup of WinEdts Reserved Words dialog are aimed at TEX. Highlighting of Reserved Words, however, is not restricted to programming languages. To give a relatively useful example not connected to programming, we wanted to get the word Miller highlighted in an ordinary text. If this example doesnt convince you, think about a foreign business partner, whose complicated name you have to write over and over (I have to resist the temptation to invent a funny name here). Politeness commands you to have the name spelled correctly, and highlighting helps you with this. Only the correct spelling will be highlighted. (Of course, WinEdt can help you also with Active Strings, spell checking or word completion.)

2.4.1

The Reserved Words Dialog

The Reserved Words Dialog does not look very complicated. In the left column, there are two elds, called Reserved Words and Words. The upper one lists groups of Reserved Words that build a unit, e. g. all keywords for the programming language C. In the list-box below you give the words itself, e. g. while and volatile for the language C. To get back to our example, Miller could be one word (given one per line in the Words eld) in the group Complicated Names (given in the Reserved Words eld). As in all the other dialogs for Syntax Highlighting, a mouse click with the secondary (usually the right) button pops up a context menu with commands for manipulating entries, such as Inserting a new one in the eld Reserved Words. The eld Filters lets you specify whether a Filter Set needs to come Before: or After: the Reserved Word. The checkboxes here dene whether the beginning of line (the Before: checkbox) or the end of line (the After: checkbox) is not an admissible position for the Reserved Word. That means, if you check the Before: eld, a Reserved Word will not be highlighted if it starts immediately at the beginning of the line. Reserved Words can be enabled for certain modes. The priority can be specied to determine highlighting of the currently selected group of Reserved Words inside Switches.

2.4. RESERVED WORDS

39

The Case Sensitive checkbox tells whether the words given should be treated case sensitive or case insensitive. About speed, the WinEdt online help has to say this (in TEX, every command starts with a backslash): It makes a dierence to specify a TEX command by its rst letter and use \ as a Filter Set or to dene all TEX Control Sequences under \CS. The second method is less ecient! (read: slower)

2.4.2

A small example

Let us look at one of the default entries in WinEdt. It highlights some words that are used in the introductory text le to WinEdt. This group of Reserved Words is called Special:
Name:Special Before:0~Alpha After:0~Alpha Enabled:1 Priority:4 Color:1027 Case Sensitive:1 TeX LaTeX WinEdt BibTeX DVIWIN MiKTeX YAP emTeX

Both Before: and After: elds are not checked, so the Reserved Words in this group can start at the beginning of the line and can end at the end of the line. The denition ~Alpha (not Alpha) ensures that the words are not highlighted if they are part of another word. This group is enabled, the empty eld here tells that highlighting is in eect in all modes. Priority is 4, so all highlighting with a lower priority is overridden. These words are highlighted with a certain color. Case Sensitive:1 tells WinEdt to take care to highlight only words which match the entries in the group in case. Thus, Latex is not highlighted, only LaTeX is. This group of Reserved Words contains eight words, namely TeX, LaTeX, WinEdt, BibTeX, DVIWIN, MiKTeX, YAP and emTeX. Most other entries in the Reserved Words dialog are no more complicated than this one. If you understand what the Filter Set in the Before: and After: eld does, you will have no problem. I get incorrect highlighting! Sort your keywords in decreasing order (WinEdt has a Sort Lines function). If you do not do this, you get wrong highlighting with words that begin with the same letter(s). Sorting

40

CHAPTER 2. SYNTAX HIGHLIGHTING

the words in decreasing order makes sure that longer words become before shorter ones when having the rst letters in common, which is essential in most cases.
Note: this example is a TEX example. You do not need to know about this language, just notice that all TEX commands start with a backslash. Say you have the Reserved Words \par and \part. If you have not taken care to sort the words in decreasing order, WinEdt would highlight only the letters p, a and r of part. When applying its algorithm, WinEdt goes through the list of Reserved Words and sees that the pattern \par matches the word \part perfectly (see it as a stencil), and highlights it. This looks like \part. WinEdt does not go further down the list (which can be rather long, and usually is) for speed reasons, so it does not see that the stencil \part would match even better. If, however, you have sorted the words in decreasing order, then \part is found rst, and correctly applied. WinEdt would not need to go further down the list of Reserved Words, since there will be only \par, which does not t the stencil because of the missing t. There is another way to get correct highlighting in this case, and this has a pleasing side-eect. To be honest, this second way was invented in the rst place to get the side-eect. So lets see what the side-eect A is. In TEX or L TEX you can dene functions yourself. You could now dene a function called \parent. Since A this is neither standard TEX or L TEX you will not have it in the Reserved Words list. Without taking care, you will have the \par part of your function highlighted, resulting in \parent. This is really annoying. The solution is to specify an After: Filter Set. In our TEX example, a ~Alpha (not Alpha, you remember) Filter Set matches best, since normally TEX commands may only have alphabetic characters. The ~Alpha Filter Set here says: After a Reserved Word may come everything except an alphabetic character. This prevents highlighting of words that do not t exactly in writing (while it leniently overlooks all nonalphabetic characters after the word). Our \parent function does not t exactly in writing, and thus is not highlighted. Great. Lets get back to the \part example from the beginning: here too, \par does not t \part exactly anymore. It does not matter whether the list of Reserved Words is sorted in increasing or decreasing order: WinEdt can not apply its highlighting. It has to nd an exact match, and only \part matches \part.

S-ar putea să vă placă și