latex - winedt hacker's guide

40
The WinEdt Hacker’s Guide Jason Alexander Colin Marquardt November 10, 1998

Upload: nishu-gupta

Post on 07-Mar-2015

94 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: LaTeX - WinEdt Hacker's Guide

The WinEdt Hacker’s Guide

Jason Alexander

Colin Marquardt

November 10, 1998

Page 2: LaTeX - WinEdt Hacker's Guide

2

Page 3: LaTeX - WinEdt Hacker's Guide

Contents

1 Macros 51.1 Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61.2 Variables/Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

1.2.1 Strings and things . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91.2.2 Setting the values of registers . . . . . . . . . . . . . . . . . . . . . . 14

1.3 Procedures and Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171.4 Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

1.4.1 A lengthy example . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211.5 Interactive Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

1.5.1 Getting data from the user . . . . . . . . . . . . . . . . . . . . . . . . 251.6 Appendix . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

2 Syntax Highlighting 292.1 Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29

2.1.1 Filter Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302.1.2 Switches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 302.1.3 Reserved Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

2.2 Filter Sets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 312.2.1 The “Filter Sets” Dialog . . . . . . . . . . . . . . . . . . . . . . . . . 312.2.2 Set Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

2.3 Switches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 332.3.1 Global Switches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 342.3.2 The “Switches” Dialog . . . . . . . . . . . . . . . . . . . . . . . . . . 342.3.3 Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

2.4 Reserved Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 382.4.1 The “Reserved Words” Dialog . . . . . . . . . . . . . . . . . . . . . . 382.4.2 A small example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

3

Page 4: LaTeX - WinEdt Hacker's Guide

4 CONTENTS

Page 5: LaTeX - WinEdt Hacker's Guide

Chapter 1

Macros

Macro programming in WinEdt can be frustrating at first. Common sources of frustrationfor first-time macro programmers are: not knowing what macro functions are available (orappropriate) for the desired task, not understanding the flexibility of the macro functionsthat are available, or idiosyncracies of the WinEdt language.

This chapter discusses all these areas, gives numerous examples of macro programming inWinEdt, and shows some dirty tricks and some conventions that are beginning to be formedby the WinEdt community. Please send reports of any errors or inadequacies (or neaterexamples, as well!) to [email protected].

This chapter discusses WinEdt’s macro feature on several different levels simultaneously.I have adopted a “dangerous bend” convention (first used by the computer scientist DonaldE. Knuth) to flag sections which go beyond what a first-time macro programmer would beexpected to know:

� If your reading this on the first time through, didn’t you pay attention to the warning in previousparagraph? :-) I’ll let it go this time, but you should really try to avoid sections like these in the

future until you have experience with WinEdt’s macro language.

Sections which one might want to defer reading until the second or third time are markedwith two dangerous bend signs. Whenever possible, macro examples will be given followingthe “two-column” format employed in The LATEX Companion by Goossens, Mittelbach, andSamarin. The actual WinEdt macro code usually appears on the left-hand side with thecorresponding 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

Page 6: LaTeX - WinEdt Hacker's Guide

6 CHAPTER 1. MACROS

1.1 Basics

The simplest macros in WinEdt’s library insert text or additional lines into the currentdocument.

Ins("String to insert");Inserts a specified string (or the contents of a string register, e.g. “%!9”) using the current wrappingsettings.

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, "...") — wheren is a number (or a register containing a numeric value) and the string parameter containsthe argument to be repeated. The next example demonstrates how to insert multiple linebreaks 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 youknow the offset from the current position. E.g.,

Repeat(20, CMD("Char Left"));Repeat(5, CMD("Line Down"));

moves the cursor twenty characters left and five lines down from the current position. (Luck-ily, more efficient 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 WinEdt’s

library) concerns using Repeat with macros that take string arguments. Since the second

Page 7: LaTeX - WinEdt Hacker's Guide

1.1. BASICS 7

argument of Repeat is itself a string, if you attempt to repeat a command that takes a stringargument, you must take care to correctly nest the strings. One correct use of Repeat toinsert 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 different quotation marks to indicate the string insidethe 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 doesn’t matter which convention you adopt, so long as you understand it and canwork 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 fixed number of times. Notice the wordfixed occurring in that last sentence. Because the first argument of Repeat is a numeric constant specifyinghow many times the second argument ought to be repeated, you must always know at the time of writinghow many times the action must be repeated. More complicated macros, requiring an action to be repeateduntil some condition occurs (where it is not know ahead of time how many times the action will need to berepeated) should use the more powerful Loop macro.

Since we’ve already talked about moving the cursor around the screen, we might aswell mention a few more ways to do it. If you just want to automate the kinds of cursormovements that you can do with the keyboard—i.e., move around the screen, or scroll abit—you’ll be happy to know that these operations get handled via the flexible 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 ofCMD as the macro equivalent of a Swiss-army knife: over 170 different things can be donewith CMD (admittedly, not all of them are ones that you will use frequently, if at all). Using

Page 8: LaTeX - WinEdt Hacker's Guide

8 CHAPTER 1. MACROS

CMD is a simple two-step process: (1) look up the name of the desired command in WinEdt’son-line documentation, (2) call CMD, giving it the name of the command in quotation marksas above.

� Basically, CMD invokes commands that are essential to WinEdt’s behavior — like cursor movements,screen refreshes, inserting bullets, setting bookmarks, and so on. One can also invoke all the dialog

boxes used to customize WinEdt’s behavior, e.g., CMD("Preferences..."). Notice that there is some overlapwith the Menu macro here, since both Menu and CMD can be used to bring up the Preferences dialog box. Theneed for two different macros, though, stems from the degree to which WinEdt allows customization of itsmenus. For example, one could delete the Preferences. . . choice from the Options menu, making it impossibleto invoke the Preferences dialog box with the Menu macro. However, the Preferences dialog box will alwaysbe available via the CMD macro.

The real power of WinEdt’s macro language doesn’t begin to emerge until we considermacros capable of conditional behavior — taking different actions depending upon the cur-rent state of some parameter. But this means that WinEdt must allow for certain parametersto vary over time. It’s time to consider variables or registers.

1.2 Variables/Registers

� The WinEdt documentation uses the terms ‘variable’ and ‘register’ interchangeably, so let’s firstnote the difference between the two terms, as traditionally understood, and then see where WinEdt’s

macro language falls. Most (if not all) programming languages allow you to declare variables with namesdescriptive of their contents, like mass, number_of_loops, and so on. When you declare a variable, a chunkof memory gets allocated for storing a certain type of data.1 The important point being that variables havenames. A register, on the other hand, can’t be given a special name: it’s a chunk of storage that you haveto refer to by whatever name the designer gave it.

So what does WinEdt have? WinEdt has registers—so you can’t give them custom names—but WinEdt’sregisters are more flexible than variables in languages like C. WinEdt will automatically allocate memory onan as-need basis for each of its registers—you don’t have to worry about that at all (if you were the sort ofperson who would worry about it in the first place). If you want, you can copy several pages of a documentinto a register that was previously used to hold a number, and WinEdt won’t complain. So even if you don’tlike not being able to declare named variables to make your macros easier to understand, WinEdt’s registerscan be quite powerful.

We can distinguish between four different types of registers: local, global, editor anddocument. There are eleven local registers, eleven global registers, and numerous documentand editor registers. Luckily, though, one can usually identify the type of a register bylooking 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 dif-ference between these types of registers is primarily semantic rather than syntactic: editorregisters contain values specifying the current state of WinEdt (current line position, columnposition, and so forth) and document registers contain values identifying properties of the

1With some exceptions. C’s union type allows you to store different types of data in the same (approxi-mately) chunk of memory.

Page 9: LaTeX - WinEdt Hacker's Guide

1.2. VARIABLES/REGISTERS 9

active file type, file name, path, etc.). One cannot directly change the value of a documentregister, 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 theactive file (the file currently having focus in the editor), %p contains the path of the activefile, and %t contains the extension of the current file. So, if the active file 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 file 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 eliminatethe 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 ofthe 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 differ by lacking an exclamation point: %0,. . . , %9 are global registers (so is%I, but it has a special function we’ll return to later). From the point of view of a macroprogrammer local registers are no different than global registers save that global registersretain their values between WinEdt sessions and should not have multi-line values. Theprohibition on multi-line values arises because global registers have their values stored in theWinEdt.ini file and multi-line values can corrupt the WinEdt.ini file.

�� So what? Well, most of the time you will probably want to use local registers when writing WinEdtmacros (especially ones that just save on some typing). But using global registers can allow you to

create state-sensitive macros that respond differently depending upon the current state of the editor, wherethe editor remembers it’s current state from time to time.

Take a look at the macros located in %B\macros\math. These macros employ the method of globalregisters to toggle between two modes: a LATEX math mode, and a LATEX normal text mode. A number ofmacros are provided to hook to active strings. When done so, ‘a gets translated to \alpha when math modeis on, but gets left as ‘a in normal text mode.

1.2.1 Strings and things

Most of the macros in WinEdt’s standard library take arguments, some several. Whenreading arguments there are two different types of arguments WinEdt may expect to find:numeric and string. A numeric argument can be a constant — e.g., 17 — a register (localor global) currently set to a numeric value, or an integer expression using the standardarithmetic operators +-*/. An “integer expression” means any well-formed expression usingthose operators, registers containing well-formed integer expressions, and constants (withparentheses used for grouping. The following are examples of valid integer expressions:

2+3

((2+3)/16)

Page 10: LaTeX - WinEdt Hacker's Guide

10 CHAPTER 1. MACROS

%!1+%!2

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

The following macro illustrates a simple use of integer expressions:

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

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

1.3 Using integer expressions

Line 1 stores the numerical value 1 in register %!1. In line 2, register %!2 receives thenumerical value 3 because the result returned by WinEdt when performing arithmetic di-vision truncates decimals. Finally, line 3 assigns to register %!3 the value 6 because whenWinEdt processes the second argument of LetRegNum, register %!2 expands to the value 3and 3 + 3 = 6 (in case you didn’t know).

Note the use of repeated %-signs in lines 4–6. Since WinEdt uses percent signs in thenames of registers, you must tell WinEdt when you really want a percent sign instead of aregister 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 withthe need to repeat certain “special” characters; if you are not such a person, just rememberto type %% whenever you want % to appear in the text and you will get by fine.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 WinEdt’s macro language.WinEdt recognizes several different ways to nest strings:

Correct:"this is a 'string' inside a String"

'this is a "string" inside a String'

"this is a ""string"" inside a String"

'this is a ''string'' inside 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 wasn’t necessary. You might have a complicatedinteger 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

2Until you start working with nested strings. Then things become considerably more complicated eventhough the rules stay the same. Working with registers and percent signs inside nested strings will be dealtwith in a later section, but see 1.4 and 1.5 for a taste of what will come.

Page 11: LaTeX - WinEdt Hacker's Guide

1.2. VARIABLES/REGISTERS 11

give you headaches, since LetRegNum immediately evaluates its second argument to obtain an integer valuefor the assignment.

The way around this problem is to store the complicated integer expression in a local register as astring. This allows one to suppress expansion of the named registers until you actually want to evaluate theexpression. Here’s an example:

1 BeginGroup;

2 LetReg(1,'((100*%%!2)+(10*%%!3)+(%%!2*%%!3)');

3 LetRegNum(2,0);

4 LetRegNum(3,0);

5 Loop('>

6 Loop(">

7 LetRegNum(4, ''%%!1'');>

8 InsText(''%%%%%%%%!2 = %%%%!2, %%%%%%%%!3 = %%%%!3, %%%%%%%%!4 = %%%%!4'');>

9 NewLine;>

10 LetRegNum(3, %%%%!3+1);>

11 IfNum(%%%%!3,3,''='',''Stop'','''');>

12 ");>

13 LetRegNum(2, %%!2+1);>

14 LetRegNum(3,0);>

15 IfNum(%%!2,3,"=","Stop","");>

16 ');

17 EndGroup;

18 End;

1.4 Storing integer expressions for later use

This macro produces the following output:

%!2 = 0, %!3 = 0, %!4 = 0%!2 = 0, %!3 = 1, %!4 = 10%!2 = 0, %!3 = 2, %!4 = 20%!2 = 1, %!3 = 0, %!4 = 100%!2 = 1, %!3 = 1, %!4 = 111%!2 = 1, %!3 = 2, %!4 = 122%!2 = 2, %!3 = 0, %!4 = 200%!2 = 2, %!3 = 1, %!4 = 212%!2 = 2, %!3 = 2, %!4 = 224

How? First, the integer expression ((100*%!2)+(10*%!3)+(%!2*%!3) gets stored in %!1 (note the use ofdouble parentheses to suppress expansion). Then %!2 and %!3 are initialized to 0. We then enter a doubly-nested loop. We take advantage of some expansion trickery in the first 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 don’t want to suppress expansion since we want to use the contents of %!1 — thecomplicated integer expression — when assigning a value to %!4. Thus %%!1 gets expanded before WinEdtbegins processing the LetRegNum call. When WinEdt begins processing the LetRegNum call, it first expandsthe second argument of this macro — the complicated integer expression we want to use! Thus, %!4 getsassigned the value 0 the first time through the double loop, since both %!2 and %!3 equal 0.

String arguments can be explicitly specified — e.g., "This is a string" — or they canuse registers (local or global) whose contents “make sense” when expanded. Make sense?Here’s what I mean. Consider the macro InsText. It takes a single string argument andinserts 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

Page 12: LaTeX - WinEdt Hacker's Guide

12 CHAPTER 1. MACROS

string into the document. However, consider the macro Loop. Here, the only strings whichmake sense are those which expand into a sequence of macros WinEdt can execute. Giving"This is a string" as an argument to InsText won’t result in an error, but giving it asan argument to Loop will cause WinEdt to complain.

� Defining the notion of a string “making sense” more precisely would require that we introduce thenotion 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 attheoretical computer science than myself.

New users often find the way WinEdt handles string arguments one of the more puzzlingaspects of WinEdt’s macro language. Here’s 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 registerswith the Do macro, one can use registers to access string registers. The following example shows

how to exploit this primitive type of pointer.

1 BeginGroup;

2 LetRegNum(0,4);

3 LetRegNum(1,5);

4 LetRegNum(2,6);

5 LetRegNum(3,7);

6 LetReg(%!0, "Jellical cats come out tonight,");

7 LetReg(%!1, "Jellical cats come one, come all,");

8 LetReg(%!2, "The Jellical moon is shining bright,");

9 LetReg(%!3, "Jellicals come to the Jellical ball.");

10 LetRegNum(8,4);

11 Loop("InsText('Reg. #%%!8: ');>

12 Do('InsText(""%%%%!%%!8"");>

13 NewLine;>

14 ');>

15 LetRegNum(8,%%!8+1);>

16 IfNum(%%!8, 7, '>', 'Stop','');>

17 ");

18 EndGroup;

%!4: Jellical cats come out tonight,

%!5: Jellical cats come one, come all,

%!6: The Jellical moon is shining bright,

%!7: 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 (plusa NewLine) on each pass. Note how in the Loop macro we use register %!8 not only to control the numberof 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 Para-

meter Expected. Why? Because Ins requires a string argument and %!1 isn’t a string — it’sthe name of a local register containing a string. One might wonder why Ins("%!1") works,then. After all, why doesn’t WinEdt interpret "%!1" as a string containing the sequence ofcharacters %, !, and 1, causing the text %!1 to appear in the document?

The answer lies in WinEdt’s treatment of strings parameters. Whenever WinEdt executesa macro requiring a string parameter, it first expands the string parameter before using it.

Page 13: LaTeX - WinEdt Hacker's Guide

1.2. VARIABLES/REGISTERS 13

When the parameter gets expanded, all registers at the bottom level (i.e., registers thataren’t suppressed) get replaced by their values, and every register of a higher level gets itslevel lowered by one. When WinEdt processes the macro Ins("%!1"), WinEdt replaces theregister %!1 by its value because it occurs at the bottom level. WinEdt then inserts thetranslated expression into the document.

� Strictly speaking, WinEdt doesn’t keep track of levels at all; as far as WinEdt is concerned, all itworks 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, here’s 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 WinEdtexpands %!1. WinEdt also expands %% to a single percent sign: %. If you write a macro that has a registerappearing inside a nested string, you can control when that register gets replaced by its value by the numberof 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" intothe document (with line breaks appearing between each copy). However, it illustrates how WinEdt expandsstrings.

When WinEdt begins executing this macro, it begins on the first line with LetReg. WinEdt takes thestring argument, expands it, and assigns the expanded string to register %!1. Since there were no regis-ter 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 first concatenates all the lines ending with > (thisallows us to use line breaks to increase the readability of macros, since, technically, all WinEdt macros mustlie on a single line). Once that has been done, WinEdt checks to see whether %!2 equals 1 or not. Since itdoes, WinEdt will execute the fourth argument of IfNum.

Before WinEdt executes this fourth argument, it expands the string. After expansion, WinEdt faces thesequence 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 theexpression %% 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 first expands the second argument ofRepeat. The sequence of commands after expansion is:

InsText("%!1"); NewLine;

which gets repeated three times. As WinEdt executes the InsText macro, it first expands the string argu-ment. In the process of expansion, WinEdt finally finds an occurrence of the register %!1 and replaces it bythe text The best of all possible strings which WinEdt finally inserts into the document.

Page 14: LaTeX - WinEdt Hacker's Guide

14 CHAPTER 1. MACROS

� One might want to suppress WinEdt’s automatic replacement of registers (this happens most fre-quently when writing complicated macros containing nested loops). WinEdt provides two ways to

suppress register replacement: (1) doubling the number of %-signs at the register’s name raises its level byone (thus delaying its replacement), or (2) adding a ! before the string parameter prevents the entire stringfrom being translated, effectively 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 longstreams of parenthesis in deeply nested macros, but it doesn’t 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 thelocal string registers (%!0,. . . ,%!9), since these registers are intended to be the macro writer’smain 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 globalstring register. Since the values of these registers are stored permanently in yourWinEdt.ini file, this file can become corrupted if one assigns multi-line values tothe global string registers.

This restriction does not usually present a problem since one rarely is tempted to use a globalregister. And, in the cases where one does need a global register, there is either no needto use multi-line values, or this limitation can be easily circumvented. See §?? for furtherdiscussion.

WinEdt provides several ways to modify the values of the local string registers. Modifi-cations which do not require any input from the user can be done using LetReg (assigningstring 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, butdiscussion of these macro methods won’t 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).

Page 15: LaTeX - WinEdt Hacker's Guide

1.2. VARIABLES/REGISTERS 15

LetReg(StrRegister: 0..9, "Value");Assigns the specified value to the String Register (eg. %!0).

If you really want to fly in the face of danger, you can assign values to the global regis-ters (but do heed the above warning) via LetStr—the global register equivalent of LetReg.LetStr assumes you know what you’re doing when you make assignments and it will notcheck 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 file.

LetStr(StrRegister: 0..9, "Value");Assigns the specified 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 specified string register, if the active file

has selected text. If no text is selected, the behavior of GetSel depends on the value of its first parameter: if0, the specified string register receives the empty string; if 1, the specified string register receives the entiredocument. Obviously, one should exercise caution when using the latter case: you probably don’t want toselect 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, performingsome conditional action based on what you find there. GetSel provides a way to do this. Note, though, thatthis technique should only be used for isolated tests; using this technique inside a loop can cause the macroto 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 beuseful for?

1 CMD('Backspace');2 CMD('Select Char Left');3 GetSel(0,9);4 CMD('Char Right');5 IfStr('%!9',' ','=','InsText("‘‘");End','');6 IfStr('%!9','.','=','InsText("''''");End','');7 IfStr('%!9',',','=','InsText("''''");End','');8 IfStr('%!9','!','=','InsText("''''");End','');9 IfStr('%!9','?','=','InsText("''''");End','InsText(''"'')');

1.6 Conditional insertion of characters based on surrounding text

Let’s walk through this macro to see what, exactly, it does. First of all, line 1 shows I lied when I saidthe macro checks the character to the left of the cursor; the macro begins by deleting the character to theleft of the cursor. Once that’s done, lines 2–4 copy the character to the left of the cursor into register %!9and then move right. (We need to move right in line 4 because the command in line 2 causes the cursor tomove one character to the left. If we did not move right one character, the text inserted in lines 5–9 wouldappear in the wrong place.)

Lines 5–9 demonstrate one way of performing a multiple-way branch—that is, a conditional operationlike C’s switch statement or TEX’s \ifcase. Since WinEdt doesn’t have command providing a multiple-waybranch 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 else-clause. If you want to specify a default branch, that is, a sequence of commands to be executed when noneof your explicit If... tests succeed (always a good idea), put this sequence of commands in the else-clauseof the last If... test. The above macro uses this construction: notice the use of End; to terminate macroexecution after a successful IfStr test and how the IfStrs of lines 5–8 all have empty else-clauses.

Page 16: LaTeX - WinEdt Hacker's Guide

16 CHAPTER 1. MACROS

Lines 5–9 check the character in register %!9 to see whether it’s a space, period, comma, exclamationpoint, question mark, or other (that’s the default case). If it’s a space, WinEdt inserts ‘‘ into the text atthe current cursor position. If it’s one of the four punctuation symbols, WinEdt inserts '' into the text. Inall other cases, a single " gets inserted. Note how four '-marks were needed in lines 6–9 to get two '-marksin the text.

When would such a macro be needed? Consider what would happen if " were made an active stringwith this macro bound to it. Then whenever a " was typed, WinEdt would replacing the " with one of threepossibilities depending upon the character preceding the ". In other words, this macro would create “smartquote” 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 testsurrounding 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 thebest results.

Using CMD("Select Char Left") (or its sister command CMD("Select Char Right")) slows macroexecution down because they use Windows messaging commands to perform the indicated actions—internally,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 first deselect everything,and then SetSel(1) (some other nonzero number may also be used) to begin the selection process. At thispoint, using GotoCol, etc. moves the cursor to the specified position, selecting all the text in between thecursor position when SetSel(1) was called at the new position. At this point, GetSel may be used to copythe selected text into the desired register.

Macro 1.6, rewritten using these techniques, will then look like:

1 CMD('Backspace');2 Mark(0);3 IfNum('%c',1,'=','InsText("‘‘");End','');4 SetSel(1);5 GotoCol('(%c-1)');6 GetSel(0,9);7 SetSel(0);8 Goto(0);9 IfStr('%!9',' ','=','InsText("‘‘");End','');10 IfStr('%!9','.','=','InsText("''''");End','');11 IfStr('%!9',',','=','InsText("''''");End','');12 IfStr('%!9','!','=','InsText("''''");End','');13 IfStr('%!9','?','=','InsText("''''");End',>14 'InsText(''"'')');15 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 desiredcharacter(s) (either ‘‘ or '' or "). However, selecting the text requires that we move the cursor to theright by one, once the text has been selected. The use of Mark(0) in line 2, following by Goto(0) in line8, 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 difference between the two versions.

Page 17: LaTeX - WinEdt Hacker's Guide

1.3. PROCEDURES AND FUNCTIONS 17

Aside from the local and global string registers, most of WinEdt’s other registers havetheir values changed indirectly through the use of other macro commands. For example, theeditor registers %c and %l contain, respectively, the current column and line number (thecurrent column and line number identifies 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 %cor %l, you must either manually move the cursor (the changes are automatically reflectedin the values of %c and %l) or use GotoCol, GotoLin or GotoCL to jump the cursor to aparticular spot in the document.

GotoLin(LineNum: 1..16000000);

Go to the specified line and track the Caret’s position.

GotoCol(ColumnNum: 1..99999999);

Go to the specified column and track the Caret’s position.

GotoCL(ColumnNum: 1..99999999, LineNum: 1..16000000);

Go to the specified text position and track the Caret.

However, WinEdt does allows the user to change a few document registers directlythrough the commands SetFileName and SetFileMode. These commands will probablybe used rather infrequently, but they are there in the event you need to use them.

SetFileName("File Name");

Changes the file name of the current document.

SetFileMode("File Mode");

Changes the ”Mode” of the current document and resets certain properties. Check WinEdt’s documen-tation on modes for more information.

1.3 Procedures and Functions

Macro languages can save time and reduce errors by automating repeated tasks. As peoplebecome more familiar with the flexibility of a macro language, they tend to write longermacros to perform more complicated tasks. As macros grow in length, it becomes impor-tant (from the programmer’s point of view—the macro interpreter couldn’t care less!) toimpose 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 singlesubroutine can be called every time it’s needed, obviating the need to include that code atevery point it’s used.

As a trivial example, suppose we want a macro to automatically create a new LATEXdocument, configuring the document by adding text at various places. In particular, supposewe want the document to look like this when the macro completes operation:

Page 18: LaTeX - WinEdt Hacker's Guide

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 CMD("New");2 Mark(0);3 Ins("\documentclass[12pt]{article}"); NewLine;4 Ins("\usepackage{amsmath}"); NewLine;5 Ins("\usepackage(verbatim}"); NewLine; NewLine;6 Ins("\begin{document}"); NewLine; NewLine;7 Ins(" "); NewLine; NewLine;8 CMD("Go To Beginning Of Line");9 Ins("\bibliography{mybibliography}"); NewLine;10 Ins("\bibliographystyle{plain}"); NewLine;11 Ins("\end{document}");12 Goto(0);13 CMD("Next Bullet");

1.8 Macro without subroutines

Without explicitly instructing WinEdt, in line 7, to go to the beginning of the line, the textof lines 8–10 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 reasonfor returning to that position is that it moved the cursor before the bullet, thus guaranteeingthat 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,is that LATEX documents have a certain structure to them: a preamble (everything appear-ing before the \begin{document}) and what I’ll call a “postamble” (everything appearingafter the \end{document}). This macro assumes the postamble to be empty—a reasonableassumption since LATEX ignores anything in the postamble—but, conceivably, there may beinstances where the postamble would not be empty: version control information might beplaced there, information about the author, etc. Since the preamble and postamble consti-tute logically separate parts of a LATEX document, let’s rewrite the macro using subroutinesto reflect this fact. While we’re at it, let’s include a subroutine for all the middle stuff not ap-pearing in either the preamble or postamble. (Although further enhancement of this macromight seem an unnecessary exercise in obfuscation, it illustrates how to use subroutines. Inthe future we’ll see many cases where using subroutines clarify the operation of a macro.)

Page 19: LaTeX - WinEdt Hacker's Guide

1.3. PROCEDURES AND FUNCTIONS 19

� Strictly speaking, WinEdt doesn’t provide for subroutines. WinEdt provides the Exe macro, whichlooks for a specified macro file; if the file exists, WinEdt executes the sequence of commands contained

within that file. But this allows us to write code that behaves as if WinEdt allowed one to define subroutines:simply write your code for the function, but save it to a file with a descriptive name and use Exe("...") tocall the subroutine.

Rewriting macro 1.8 so it uses subroutines as described means we must create two macrofiles on disk, one for the preamble and one for the postamble. You can save your macrofiles wherever you want to, just make sure you remember where they are. The author findsit convenient to prefix the name of macro files containing subroutines with two underscorecharacters, __, so he can tell just by looking at the file name that they aren’t stand-alonemacro files (and that he might get into trouble if he deletes them!).

Since the postamble subroutine is the easiest to write, let’s 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 isn’t 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 stuff subroutine we have:

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}");

1.11 Middle stuff subroutine for macro 1.8

(Assume it was saved as %B\macros\__MiddleStuff.edt.)

When rewritten using subroutines, macro 1.8 looks like:

Page 20: LaTeX - WinEdt Hacker's Guide

20 CHAPTER 1. MACROS

1 CMD("New");2 Mark(0);3 Exe("%B\macros\__Preamble.edt");4 Exe("%B\macros\__MiddleStuff.edt");5 Exe("%B\macros\__Postamble.edt");6 Goto(0);7 CMD("Next Bullet");

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 thatthis should convince us to use subroutines whenever possible. The author believes thatthe 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 modifications of macro codebecome easier since the code has been broken down into bite-size chunks, and (2) debuggingmacros becomes easier since one can (usually) debug the subroutines in isolation from themain 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 levelgreater than two. If you find WinEdt’s conventions for nested strings and repeated %-signsconfusing, this alone might convince you to use subroutines.

� Using subroutines can make writing complicated macros easier, too. You can define Exe to bean active string so that when you double-click on it, WinEdt will automatically try to open the

specified macro file. 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 WinEdt’s language does notprove exception to the rule. Recursive programming in WinEdt requires that we use themethod of subroutines sketched in §1.3. Since writing recursive functions often requiresseveral macro files to be saved to disk, we need to indicate in our examples what macro codebelongs to which macro file. The convention that shall be adopted is to surround macro codeby comments indicating the file name and where the file ends. This allows us to include thecode for several files in the same display. E.g.,

// Filename: _MyMacro.edt...// Endfile

// Filename: _MyOtherMacro.edt...// Endfile

Consider the following simple example:

Page 21: LaTeX - WinEdt Hacker's Guide

1.4. RECURSION 21

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

1.13 A simple recursive macro

When started at the beginning of a line, WinEdt produces

aaaaaaaaabbbbbbbbb

If started five spaces in, we get

aaaabbbb

(Only four as appear when started five 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 atcolumn 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 thatit will automatically convert any string of digits (such as 1235678) to the form 1.235.678?Before starting, let’s generalize the problem to the following: customize WinEdt so thatit will take a string of digits and insert the contents of a string register after every threedigits (counting from the right). This generalization makes the macro more useful sinceconventions vary on whether to use a period, comma, raised dot, or space when separatingdigits.

First off, let’s consider how this macro will be invoked. We don’t want to invoke themacro until the digit string has been fully entered, but how do we postpone execution ofthe macro until the string has been completed? One natural way of doing this is to useactive strings. But what active string? We can’t make every digit active because WinEdtwill then invoke the macro each time we type a digit. We could require that the user wrapthe digit string will an identifier unlikely to occur in ordinary text, say @digits{...}, butthis solution is clumsy: we want the macro to make it easier to type a string of digits, andtyping @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 bya space. Thus we can make the strings ‘0 ’ (zero followed by a space),. . . , ‘9 ’ (nine followedby a space) active. This guarantees that the macro gets invoked only at the end of a digitstring.

Second, we note that the macro will need to do some initialization: we need to placethe desired delimiter into a string register and set a counter to 0 so that we can count offthree digits at a time. Now, we can write the macro using either Loop or recursion. Theproblem using Loop is that it requires us to nest strings and—if the macro is long—this can

Page 22: LaTeX - WinEdt Hacker's Guide

22 CHAPTER 1. MACROS

be a headache. However, if we use recursion, we have to be careful of how we set the initialconditions. We cannot set the initial conditions inside the same subroutine used for therecursion 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, callingthe recursive subroutine at the very end.

1 // Filename: %B\macros\ap\_APstartup.edt2 BeginGroup;3 StartWorking("Adding separators...");4 LetReg(5,','); // <--- Change this if you want commas instead of periods5 LetRegNum(6,0); // Stop indicator6 LetRegNum(7,%c); // Original column position7 LetRegNum(8,0); // Found digit indicator8 GotoCol('%c-1'); // Backup behind the space delimiter9 Exe('%B\macros\AddPeriods\_APchew.edt');10 // 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 sometime to complete. Register %!5 contains the delimiter string (here we use a comma). Register%!6 contains a binary flag indicating whether the macro has completed (we’ll see later whythis is necessary). Register %!7 contains the column that the cursor will return to whenmacro execution finishes. Finally, register %!8 contains the number of digits we’ve found sofar.

After initialization, WinEdt calls the macro _APchew.edt. This subroutine decides whereto place the separators. Consider part of it:

1 SetSel(0); SetSel(1);

2 IfNum(%c,1,'=',>

3 'Exe("%B\macros\AddPeriods\_APend.edt")',>

4 '');

5 GotoCol('(%c-1)'); GetSel(0,9);

6 IfStr('%!9','0','=',>

7 'LetRegNum(8,"%%!8+1");>

8 IfNum("%%!8","4","=",>

9 "SetSel(0);>

10 GotoCol(''%%%%c+1'');>

11 InsText(''%%%%!5'');>

12 GotoCol(''%%%%c-1'');>

13 LetRegNum(8,0);>

14 LetRegNum(7,''%%%%!7+1'')",>

15 "">

16 );>

17 Exe("%B\macros\AddPeriods\_APchew.edt")',>

18 ''>

19 );

20 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\_APend.edt")','');

1.15 Part of the recursive subroutine called in 1.14

Page 23: LaTeX - WinEdt Hacker's Guide

1.4. RECURSION 23

Lines 1–5 copy the character to the left of the cursor (if there is one) into register %!9. Thetest in line 2 checks to see if we at the beginning of a line (calling GotoCol with a negativeargument 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 fourdigits, 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 ornot. Recall the discussion on page 15 about how to get the logical equivalent of a switch

statement in WinEdt’s language. We use that technique here: we have ten different IfStr

tests to see whether the copied character is 0,. . . ,9. In 1.15, we have only listed the code forthe first 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 fourthdigit found. If it is, all text is deselected by a call to SetSel. (At this point we have notyet 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, resetthe 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 theappendix). The IfNum test of macro 1.15, line 20, calls the shutdown routine. The completelisting of this macro is listed below:

// Filename: %B\macros\ap\_APend.edtGotoCol(%!7);SetSel(0);EndGroup;StopWorking;Exit;// Endfile

The shutdown routine moves the cursor to the correct final position, deselects all text, endsthe group started in _APstart.edt, and returns the cursor to its normal mode.

� You might wonder why we hassle with the %!6 flag indicating when the processing of the digit stringhas 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 wouldn’t needto do this, but the multiple-way branching used in this macro results in a significant speed decrease.

Page 24: LaTeX - WinEdt Hacker's Guide

24 CHAPTER 1. MACROS

1.5 Interactive Macros

WinEDT provides several macros that can be used to make your macros a little more user-friendly. The macros listed below fall into three types: getting data from the user (eithernumeric or string), prompting the user to make a choice at a certain key point in macro pro-cessing, or displaying the notorious Windows hourglass cursor (with an explanatory messagein the WinEDT message area). The particular macros are:

EnterLongReg(StrRegister: 0..9, "Prompt","Caption")

Prompts you to enter the value of the specified string register (%!0. . . %!9). Allows multi-line values.

EnterReg(StrRegister: 0..9, "Prompt","Caption")

Prompts you to enter the value of the specified 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 areused 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 forrepeat loop and such. . .

Prompt("Prompt",Type,Buttons: 0..3, "Macro 1","Macro 2")

Displays the dialog box with the specified prompt. Macro execution is resumed after the user closes thedialog box. ‘Type’ and ‘Buttons’ above can be any number in the range 0,1,2, or 3. These numbersalter the dialog boxes appearance and behavior in the following way: Types 0, 1, 2, or 3 tell the dialogbox to appear as either a Information, Confirmation, Warning, or Error box, respectively. Button values0, 1, 2, or 3 cause the dialog box to have OK/Cancel buttons (where clicking on Cancel terminatesmacro execution), an OK button, OK/Cancel buttons (where clicking on Cancel will invoke a specialuser macro), or Yes/No buttons.

StartWorking("Message")

Changes the Cursor to the Hour Glass form and displays the specified message in the last field of theStatus 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 more-or-less clear), all of these macros cause a dialog box to be displayed, allowing the user toenter a certain kind of data. If you’ve never done any Windows programming before, youmight feel a certain rush of power at the ability to create a dialog box with such ease.

Page 25: LaTeX - WinEdt Hacker's Guide

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 thesame thing (sticking a string in the register %!?), and the difference between EnterLongReg

and EnterReg also might not be immediately clear. The basic difference between themconcerns the form of the dialog box that gets created. If you use either GetLongString orEnterLongReg the dialog box that appears has a large multi-line edit box allowing the userto type in whole paragraphs of text. On the other hand, GetString and EnterReg only use asingle-line edit box, which (I suppose) implicitly tells the user to be concise. WinEdt doesn’tperform any length checking on the argument for either of the short entry commands, sonothing prevents the user from typing an entire paragraph into the single-line edit box ifthey want.

The following macro illustrates one possible use of the GetString command:

1 BeginGroup;2 GetString("What environment do you want to create?","Insert Environment");3 LetRegNum(9,%c); // Store current column number4 Mark(0);5 InsText("\begin{%!?}");6 NewLine;7 GotoCol(%!9);8 InsText(" "); NewLine;9 GotoCol(%!9);10 InsText("\end{%!?}");11 Goto(0);12 CMD("Next Bullet");13 EndGroup;

1.16 The Insert Environment macro

Line 1 begins a group so that the entire macro operation can be undone by a single undooperation. Line 2 contains the call to GetString that asks the user to type in the name ofthe environment that they want to insert. Line 3 stores the current column position of thecursor 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 environmentinside of an equation. Typically, this macro will be invoked when the user has typed onlythe 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 columnthat the Insert Environment macro was invoked from (and consequently without includinglines 3, 7, and 9 in the macro definition), the macro output would look like:

Page 26: LaTeX - WinEdt Hacker's Guide

26 CHAPTER 1. MACROS

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

\end{cases}

which is probably not what the user wanted. The Newline macro creates a new line andmoves the cursor beneath the f, the InsText(" ") macro inserts the box directly beneaththe x, and the second Newline macro creates a new line and moves the cursor directly beneaththe (assuming that WinEdt’s 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 thecorrect vertical alignment like so:

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

\end{cases}

1.6 Appendix

1 SetSel(0); SetSel(1);

2 // Check to see if we are at the beginning of a line. If so,

3 // invoke __APend.

4 IfNum(%c,1,'=',>

5 'Exe("%B\macros\AddPeriods\__APend.edt")',>

6 '');

7 GotoCol('(%c-1)'); GetSel(0,9);

8 IfStr('%!9','0','=',>

9 'LetRegNum(8,"%%!8+1");>

10 IfNum("%%!8","4","=",>

11 "SetSel(0);>

12 GotoCol(''%%%%c+1'');>

13 InsText(''%%%%!5'');>

14 GotoCol(''%%%%c-1'');>

15 LetRegNum(8,0);>

16 LetRegNum(7,''%%%%!7+1'')",>

17 "">

18 );>

19 Exe("%B\macros\AddPeriods\__APchew.edt")',>

20 ''>

21 );

22 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

23 IfStr('%!9','1','=',>

24 'LetRegNum(8,"%%!8+1");>

25 IfNum("%%!8","4","=",>

26 "SetSel(0);>

27 GotoCol(''%%%%c+1'');>

28 InsText(''%%%%!5'');>

29 GotoCol(''%%%%c-1'');>

30 LetRegNum(8,0);>

31 LetRegNum(7,''%%%%!7+1'')",>

Page 27: LaTeX - WinEdt Hacker's Guide

1.6. APPENDIX 27

32 "">

33 );>

34 Exe("%B\macros\AddPeriods\__APchew.edt")',>

35 ''>

36 );

37 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

38 IfStr('%!9','2','=',>

39 'LetRegNum(8,"%%!8+1");>

40 IfNum("%%!8","4","=",>

41 "SetSel(0);>

42 GotoCol(''%%%%c+1'');>

43 InsText(''%%%%!5'');>

44 GotoCol(''%%%%c-1'');>

45 LetRegNum(8,0);>

46 LetRegNum(7,''%%%%!7+1'')",>

47 "">

48 );>

49 Exe("%B\macros\AddPeriods\__APchew.edt")',>

50 ''>

51 );

52 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

53 IfStr('%!9','3','=',>

54 'LetRegNum(8,"%%!8+1");>

55 IfNum("%%!8","4","=",>

56 "SetSel(0);>

57 GotoCol(''%%%%c+1'');>

58 InsText(''%%%%!5'');>

59 GotoCol(''%%%%c-1'');>

60 LetRegNum(8,0);>

61 LetRegNum(7,''%%%%!7+1'')",>

62 "">

63 );>

64 Exe("%B\macros\AddPeriods\__APchew.edt")',>

65 ''>

66 );

67 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

68 IfStr('%!9','4','=',>

69 'LetRegNum(8,"%%!8+1");>

70 IfNum("%%!8","4","=",>

71 "SetSel(0);>

72 GotoCol(''%%%%c+1'');>

73 InsText(''%%%%!5'');>

74 GotoCol(''%%%%c-1'');>

75 LetRegNum(8,0);>

76 LetRegNum(7,''%%%%!7+1'')",>

77 "">

78 );>

79 Exe("%B\macros\AddPeriods\__APchew.edt")',>

80 ''>

81 );

82 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

83 IfStr('%!9','5','=',>

84 'LetRegNum(8,"%%!8+1");>

85 IfNum("%%!8","4","=",>

86 "SetSel(0);>

87 GotoCol(''%%%%c+1'');>

88 InsText(''%%%%!5'');>

89 GotoCol(''%%%%c-1'');>

90 LetRegNum(8,0);>

91 LetRegNum(7,''%%%%!7+1'')",>

92 "">

93 );>

94 Exe("%B\macros\AddPeriods\__APchew.edt")',>

95 ''>

Page 28: LaTeX - WinEdt Hacker's Guide

28 CHAPTER 1. MACROS

96 );

97 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

98 IfStr('%!9','6','=',>

99 'LetRegNum(8,"%%!8+1");>

100 IfNum("%%!8","4","=",>

101 "SetSel(0);>

102 GotoCol(''%%%%c+1'');>

103 InsText(''%%%%!5'');>

104 GotoCol(''%%%%c-1'');>

105 LetRegNum(8,0);>

106 LetRegNum(7,''%%%%!7+1'')",>

107 "">

108 );>

109 Exe("%B\macros\AddPeriods\__APchew.edt")',>

110 ''>

111 );

112 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

113 IfStr('%!9','7','=',>

114 'LetRegNum(8,"%%!8+1");>

115 IfNum("%%!8","4","=",>

116 "SetSel(0);>

117 GotoCol(''%%%%c+1'');>

118 InsText(''%%%%!5'');>

119 GotoCol(''%%%%c-1'');>

120 LetRegNum(8,0);>

121 LetRegNum(7,''%%%%!7+1'')",>

122 "">

123 );>

124 Exe("%B\macros\AddPeriods\__APchew.edt")',>

125 ''>

126 );

127 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

128 IfStr('%!9','8','=',>

129 'LetRegNum(8,"%%!8+1");>

130 IfNum("%%!8","4","=",>

131 "SetSel(0);>

132 GotoCol(''%%%%c+1'');>

133 InsText(''%%%%!5'');>

134 GotoCol(''%%%%c-1'');>

135 LetRegNum(8,0);>

136 LetRegNum(7,''%%%%!7+1'')",>

137 "">

138 );>

139 Exe("%B\macros\AddPeriods\__APchew.edt")',>

140 ''>

141 );

142 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

143 IfStr('%!9','9','=',>

144 'LetRegNum(8,"%%!8+1");>

145 IfNum("%%!8","4","=",>

146 "SetSel(0);>

147 GotoCol(''%%%%c+1'');>

148 InsText(''%%%%!5'');>

149 GotoCol(''%%%%c-1'');>

150 LetRegNum(8,0);>

151 LetRegNum(7,''%%%%!7+1'')",>

152 "">

153 );>

154 Exe("%B\macros\AddPeriods\__APchew.edt")',>

155 'LetRegNum(6,1)'>

156 );

157 IfNum(%!6,1,'=','Exe("%B\macros\AddPeriods\__APend.edt")','');

Page 29: LaTeX - WinEdt Hacker's Guide

Chapter 2

Syntax Highlighting

Syntax Highlighting is another one of the powerful features of WinEdt. Certain parts ofyour text can be highlighted, that means formatted visually in a different color or font.This allows to have your document structured in an easy to spot way. In addition, SyntaxHighlighting can help you to avoid typo’s. The behaviour of the Syntax Highlighting featureis dependent on the mode of your document. Of course, you can customize the highlightingcompletely. 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 currentstate of WinEdt’s customization. All customizations are stored in the file winedt.ini1. Usethe menu entry Options Save Settings As... make a backup copy of your current winedt.iniunder another name. If you want, you can then revert to your previous state by renamingthis file 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 SyntaxHighlighting) via an human-readable format. You can access this feature by clicking thesecondary mouse button in the dialog. Now, the context menu offers you the entries Extract...,Append... and Load From....

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

1If you haven’t specified an alternative ini-file when calling WinEdt.

29

Page 30: LaTeX - WinEdt Hacker's Guide

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 valuesare negative, and you want to spot them immediately. A good way to achieve this is to usea different 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 negativevalues, you decide to mark important positive values with an explicit plus sign in front ofthem. Again, you want this plus sign to be in an other color than black, this time red. Thisis nice and also easy, and would be done using a syntax element what WinEdt calls a FilterSet.

2.1.2 Switches

You look now at your partly colored text. It looks good, but you’d wish that also the valuesitself would be colored, not only minus and plus. From what you know now, you could tellWinEdt to color all ‘1’s green, all ‘2’s green, and so on. It would work, and you could evengroup the numbers together, using only one of WinEdt’s Filter Sets. But no, you aren’tsatisfied with that, you want the negative numbers blue and the important positive numberswith a plus before it in red. You have now entered a new dimension of highlighting, thedimension 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 minussign is followed by a number, then you want to have both in blue. You don’t want numberswithout minus or plus to be colored, nor do you want a blue hyphen or such. The conditionitself is specified 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” toanother look depending on the condition, and the order of the characters to highlight doesn’tmatter; they only need to match some criteria (such as “being a number” in our example)3.

To impress and flatter your boss, you want now to have his name, Miller, in bold font.You don’t want to have all uppercase ‘M’s, all ‘i’s, ‘l’s, ‘e’s and ‘r’s in bold, just this specificorder that forms the word “Miller”. This is a so called Reserved Word, and of course youcan 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 thesethree syntax elements.

2How this is done is explained later in this chapter.3Often the criterion is “be any character”.

Page 31: LaTeX - WinEdt Hacker's Guide

2.2. FILTER SETS 31

2.2 Filter Sets

As we have seen, Filter Sets form the basic syntax element in WinEdt’s Syntax Highlighting.They are used in the other two highlighting syntax elements, the Switches and the ReservedWords. 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 first tab page),you’ll see that there are a lot of predefined Filter Sets. This is the list on the left of thisdialog. Browse through the entries and check how these look, but do not delete or modifyany of these predefined 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 FilterSet (it is not restricted to one word, use whatever you want). This name is not to be confusedwith the definition of the Filter Set!

Immediately below the list of Filter Sets there is a field which is called “Definition”.You specify the criteria for the Filter Set selected above here. Please see section 2.2.2 forinformation about these Set Expressions.

In the middle column in this dialog there are two fields which are “Filters”, “Before:”and “After:”. If your Filter Set is dependent on another Filter Set, you specify this here. Toextend our introductory example, you could want to have a Filter Set which is “+-”. Thisis either a plus “Before” a minus or a minus “After” a plus. To use a Filter Set in this listbox it has to be defined first. Although you could write directly in this box (say, a “+”), thisalone is not functioning without a matching Filter Set entry on its own.

The checkboxes for the filters can specify further restrictions:

• if the option “Before:” is checked then the beginning of line is not an admissibleposition for a character to belong to the filter,

• if the option “After:” is checked then the end of line is not an admissible position fora character to belong to the filter.

Below the “Filters” field is “Options”, where you can enable a Filter Set for highlightingof certain modes. You don’t have to enable highlighting for a Filter Set in order to use itelsewhere! 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 determineshighlighting 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 specified to determine highlighting of the currently selected filter set inside

Switches and Reserved Words. This does not mean that when two or more Filter Sets compete, the one

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

Page 32: LaTeX - WinEdt Hacker's Guide

32 CHAPTER 2. SYNTAX HIGHLIGHTING

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

The “Sample” field 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 onlyapply in your document if it matches the enabled mode definition.

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

2.2.2 Set Expressions

You use Set Expressions to specify the “Definition” field in the Filter Set dialog. There arefour predefined sets: Numeric, Alpha, Upper and Lower. These sets are language sensitive,that means their definition is dependent on the Language Settings in Windows’ ControlPanel.

To define 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 predefined set or a [sequence of characters and intervals].[] is also allowed and means the empty set.

operators: ~ (not),+ (union),- (difference),* (intersection)

Page 33: LaTeX - WinEdt Hacker's Guide

2.3. SWITCHES 33

Examples:

Character:"a" the letter a,"b" the letter b,#32 the ASCII code 32.

Interval:a..z the lowercase letters a, b, c . . . z.

Set:Numeric the numbers 0 to 9 (a predefined set),["ab"] the letters a and b,["a","b"] also the letters a and b,["+-*/^<>=(){}&#[]"] Math stuff (from the default WinEdt entry),[] the empty set.

Operators:~[] not empty, that means All,Alpha+Numeric union of the predefined sets Alpha and Numeric,

thus specifying all letters and all numbers,Alpha-Lower all letters minus the lowercase ones, giving the uppercase ones

(which happens to have its own predefined set, Upper),SetA*SetB 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 defining Set Expressions. We will come to some morecomplicated definitions in later, concrete examples. Making up not-too-easy examples forFilter Sets only is hard. Since a good and sensible Switch usually requires a good and sensibleFilter Set too, we will give its both definitions in the section about Switches.

If you are not sure about the correct syntax of a Filter Set’s definition: don’t hesitateto experiment. You cannot do much wrong as long as you do not modify WinEdt’s defaultentries. Enable the Filter Set you are working on and give it an easy to spot color. If youthink it is right, you can again switch it off and use it in e. g. the Reserved Words tab page(remember, you don’t 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 aclearly defined condition, and are ended on another condition. Unless in Filter Sets, you don’tdefine the part of the text to highlight, you define which condition “switches” highlightingon instead.

Page 34: LaTeX - WinEdt Hacker's Guide

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 complicatedalgorithm WinEdt has to use, enabling Global Switches can be slow, especially for longerdocuments. By default, Global Switches are only enabled for TEX documents. You can setthe settings for other modes via the menu Options Preferences Defaults. Here is a “DisableGlobal Switches” checkbox. Global Switches for the current document can be enabled ordisabled in Project Document Settings Options (accessible also from the Mode Field in thestatus line). In the examples it is assumed that you have turned on Global Switches, butyou will not always need it. If highlighting over more than one line doesn’t work, check yoursetting.

2.3.2 The “Switches” Dialog

To define or modify a Switch, you use the second tab page in Options Highlighting. As inthe tab page for Filter Sets, there are already some entries, which give an idea how such anentry looks. If you use WinEdt to write TEX or LATEX documents, you will recognize someof these Switches.

As in the other dialogs for Syntax Highlighting(and almost every dialog in WinEdt), amouse click with the secondary button (which is usually the right one) pops up a contextmenu with commands for manipulating entries, such as Inserting a new one.

In the dialog for defining Switches, only the middle column differs from that of the “FilterSets” dialog. Since you should know a little about Filter Sets when playing with Switches,I’m 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 fields which are “Filters”. These say“Begin:” and “End:” here. As you can imagine, you tell WinEdt what Filter Set begins orends a Switch here. To select such a Filter Set from the list, it has to be defined before.

To understand what the checkboxes in front of the “Begin:” and “End:” fields do, wefirst must explain how the “Definition” field comes into play.

The “Begin:” Filter and “Definition”

To take up our example in the introduction of this chapter, assume we want to specify aSwitch for marking all negative numbers.

There are basically two different possibilities to make such a combination of a Filter Setand a Switch work.

In a first case, you only need to give the “minus” Filter Set in the “Begin:” field, providedyou have set up the Filter Set. The field “Definition” can stay empty. Since highlightingstarts according to the “Begin:” field, the minus and the following number will be highlighted.

The second possibility is to specify a “-” (without the quote signs) in the “Definition”field, and Numeric in the “Begin:” field (with the checkbox not checked). Since Numeric is a

Page 35: LaTeX - WinEdt Hacker's Guide

2.3. SWITCHES 35

predefined set, you don’t even have to create a new Filter Set. As already said, highlightingstarts according to the “Begin:” field. In this case, we have Numeric there, so the numbersin our document will be highlighted. But, and this is the crucial point, the minus will not behighlighted! You have to decide whether this is acceptable. You could, of course, set up andenable a Filter Set with “minus” in addition. While this is practicable, it is usually betterto think about other ways.

� Now, there seems to be a third way of setting up this Switch. This would be to make “-” the“Begin:” specifier, and to set Numeric as the “Definition”. Good idea, but . . . With Filter Sets, you

were allowed to have (predefined) sets in the “Definition” field. This, however, is not possible with Switches.WinEdt treats text in the “Definition” field in the Switches dialog verbatim! Specifying Numeric here wouldexpect the word “Numeric” after the “minus” sign.

Let’s sum up what this “Begin:” checkbox does:

“Begin:” unchecked: Definition + Filter Set – The Switch starts if the charactersspecified in the “Definition” field (taken verbatim) precede the syntax elements asspecified by the Filter Set in the “Begin:” field. The characters in the “Definition”field 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:” field matches and is followed by the “Definition”, which is taken verbatim.Here, “Definition” is highlighted, since it comes after the Filter Set which begins theSwitch.

In the “Options” section of this dialog there is a checkbox named “BOLN” (Beginning OfLine). If this box is checked, then the whole Switch only applies if it starts at the beginningof a line.

Ending a Switch

After setting up a condition which begins a Switch, you now need another condition whichend this Switch. This is achieved by the “End:” field in the “Filters” section. Also, aSwitch has a “Scope” in which it is highlighted. Text outside the scope of a Switch is nothighlighted; this is the second condition which ends a Switch.

As you see, the listbox for “End:” gives the list of all defined Filter Sets. The Switchis ended when the “End:” Filter Set applies. The checkbox before the “End:” field tellswhether the occurrence of this Filter Set is part of the Switch, that means whether it ishighlighted or not.

Now, what is the scope of a Switch? The “Scope” field in the “Options” section can havea number from “0” to “4”. The meaning of these numbers is:

0 The Switch ends with the first non-alpha character. This is meant for TEX control se-quences.

1 The Switch ends at the end of line. This is useful for one-line comments in programminglanguages.

Page 36: LaTeX - WinEdt Hacker's Guide

36 CHAPTER 2. SYNTAX HIGHLIGHTING

2 The Switch ends at the hard return (not used).

3 The Switch ends at the first empty line. This can be used for TEX Math sequences ($...$).

4 The Switch ends with the specified “End:” Filter Set. Take care, as this is potentiallyslow in large documents.

Priority

Switches can be nested. The default settings of nested switches are combined if the switcheshave 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 entriesin 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 thathere are (at least) two ways to achieve this. We begin with the first possibility, which onlyneeds a Filter Set to begin the Switch.

The Filter Set with which our Switch begins is simply a “minus” sign, followed by anumber. We know already that there is a predefined set called Numeric which providesexactly this. Thus, the Filter Set with the name “-Numeric” is:

Name:-NumericDefinition:["-"]Before:0After:1NumericEnabled:0Priority:0Color:1040

You can see, the “Definition” of the Filter Set is a minus, in a syntax that follows the rulesfrom section 2.2.2, “Set Expressions”. The “Before:” field is not checked (the ‘0’) and empty.The “After:” field contains the (predefined) set Numeric and is checked, so that a minusending a line does not get highlighted (without this, in addition to Numeric, the end of theline would be valid). The Filter Set itself is not enabled, since we only use it indirectly inthe Switch. Priority is zero, the color is the standard color, but this does not come to effectsince the Filter Set is not enabled.

Okay. We have all what we need to begin the Switch. But how do we switch it off? Thehighlighting should stay in effect for all digits in the negative number, but not for text orother non-numeric characters. Therefore, a good “End:” condition is “not numeric”. Butbefore we come to set this Filter Set up, let’s think a little: a number, if it is not an integer,

Page 37: LaTeX - WinEdt Hacker's Guide

2.3. SWITCHES 37

can also have a decimal point. If we would simply say: “switch off on all but numbers”, thedecimal point would switch highlighting off too. Since we do not want this, we must alsoallow the decimal point. We can count the decimal point as numeric in this case, but ofcourse it is not included in the predefined set Numeric. Thus the Filter Set with the nameNot Numeric is:

Name:Not NumericDefinition:~Numeric-["."]Before:0After:0Enabled:0Priority:0Color:1040

We remember: the tilde (~) is the negation symbol in the Set Expression syntax. The“Definition” reads as follows: we want “not numeric”, which leaves all other characters inthe ASCII table except the numbers from ‘0’ to ‘9’. From this remaining set of characterswe subtract also the minus sign.5 Thus, the Filter Set specifies all characters except thenumbers 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 1Definition:Begin:1-NumericEnd:0Not NumericEnabled:1*Priority:2Color:3082Case Sensitive:0BOLN:0Scope:1

As said before, this switch does not need a “Definition”, since all is done with Filter Sets.

The “Begin:” field is checked (the ‘1’). This means, we remember, that WinEdt expectsthe sequence Filter Set + Definition. As our “Definition” is empty, it would not matterwhether this field is checked or not; the Filter Set alone does the work. But in contrast topossibility Two, let us have this field checked.

The “End:” field is not checked, since we do not want the Filter Set after our NegativeNumber 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 specific modes, just enter the nameshere (multiple entries divided by semicolons).

Priority is ‘2’, that means the Switch can be overridden by Filter Sets, Switches andReserved Words with higher priority values. The color is set to 3082, which happens to be

5Of course, you can specify this Filter Set in other ways, as long as it is logically correct and follows thesyntax for Set Expressions.

Page 38: LaTeX - WinEdt Hacker's Guide

38 CHAPTER 2. SYNTAX HIGHLIGHTING

bright green. The Switch is not case sensitive (why should it?) and it does not need to startat the beginning of the line (but it can). The scope of the Switch is ‘1’, that means it isswitched off at the end of the line if it is not already switched off before.

Now, we have set up our first highlighting scheme!

2.4 Reserved Words

Reserved Words are the third syntax element in WinEdt’s Syntax Highlighting algorithm.They are sequences of characters given explicitly, and like Switches, their activation can becontrolled by certain conditions, the Filter Sets.

Reserved Words are mostly used to get highlighting of keywords of programming lan-guages. Given WinEdt’s TEX background (a programming language to typeset texts), it isnot surprising that most of the entries in the default setup of WinEdt’s Reserved Wordsdialog 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 theword “Miller” highlighted in an ordinary text. If this example doesn’t convince you, thinkabout 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 youto have the name spelled correctly, and highlighting helps you with this. Only the correctspelling will be highlighted. (Of course, WinEdt can help you also with Active Strings, spellchecking or word completion.)

2.4.1 The “Reserved Words” Dialog

The “Reserved Words” Dialog does not look very complicated. In the left column, there aretwo fields, called “Reserved Words” and “Words”. The upper one lists groups of ReservedWords that build a unit, e. g. all keywords for the programming language “C”. In the list-boxbelow you give the words itself, e. g. “while” and “volatile” for the language “C”. To getback to our example, “Miller” could be one word (given one per line in the “Words” field)in the group “Complicated Names” (given in the “Reserved Words” field).

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 field “Reserved Words”.

The field “Filters” lets you specify whether a Filter Set needs to come “Before:” or“After:” the Reserved Word. The checkboxes here define whether the beginning of line (the“Before:” checkbox) or the end of line (the “After:” checkbox) is not an admissible positionfor the Reserved Word. That means, if you check the “Before:” field, a Reserved Word willnot be highlighted if it starts immediately at the beginning of the line.

Reserved Words can be enabled for certain modes. The priority can be specified todetermine highlighting of the currently selected group of Reserved Words inside Switches.

Page 39: LaTeX - WinEdt Hacker's Guide

2.4. RESERVED WORDS 39

The “Case Sensitive” checkbox tells whether the words given should be treated case sensitiveor case insensitive.

About speed, the WinEdt online help has to say this (in TEX, every command starts witha backslash): “It makes a difference to specify a TEX command by its first letter and use ‘\’as a Filter Set or to define all TEX Control Sequences under ‘\CS’. The second method isless efficient!” (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 usedin the introductory text file to WinEdt. This group of Reserved Words is called “Special”:

Name:SpecialBefore:0~AlphaAfter:0~AlphaEnabled:1Priority:4Color:1027Case Sensitive:1

TeXLaTeXWinEdtBibTeXDVIWINMiKTeXYAPemTeX

Both “Before:” and “After:” fields are not checked, so the Reserved Words in this groupcan start at the beginning of the line and can end at the end of the line. The definition~Alpha (“not Alpha”) ensures that the words are not highlighted if they are part of anotherword. This group is enabled, the empty field here tells that highlighting is in effect in allmodes. Priority is “4”, so all highlighting with a lower priority is overridden. These wordsare highlighted with a certain color.

Case Sensitive:1 tells WinEdt to take care to highlight only words which match theentries 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:” field does, you will haveno problem.

“I get incorrect highlighting!”

Sort your keywords in decreasing order (WinEdt has a “Sort Lines” function). If you do notdo this, you get wrong highlighting with words that begin with the same letter(s). Sorting

Page 40: LaTeX - WinEdt Hacker's Guide

40 CHAPTER 2. SYNTAX HIGHLIGHTING

the words in decreasing order makes sure that longer words become before shorter ones whenhaving the first 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 noticethat 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 wordsin decreasing order, WinEdt would highlight only the letters ‘p’, ‘a’ and ‘r’ of part. When applying itsalgorithm, WinEdt goes through the list of Reserved Words and sees that the pattern \par matches theword “\part” perfectly (see it as a stencil), and highlights it. This looks like “\part”. WinEdt does not gofurther down the list (which can be rather long, and usually is) for speed reasons, so it does not see that thestencil \part would match even better.

If, however, you have sorted the words in decreasing order, then \part is found first, and correctlyapplied. WinEdt would not need to go further down the list of Reserved Words, since there will be only\par, which does not fit the stencil because of the missing “t”.

There is another way to get correct highlighting in this case, and this has a pleasing side-effect. To behonest, this second way was ‘invented’ in the first place to get the side-effect. So let’s see what the side-effectis. In TEX or LATEX you can define functions yourself. You could now define a function called \parent. Sincethis is neither standard TEX or LATEX 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, youremember) 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 fit exactly in writing (while it leniently overlooks all non-alphabetic characters after the word). Our \parent function does not fit exactly in writing, and thus is nothighlighted. Great.

Let’s get back to the “\part” example from the beginning: here too, \par does not fit “\part” exactlyanymore. 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 find an exact match, and only \part matches “\part”.