
Last lesson, we began to learn about the Diesel macro language and started to learn to customize the status line. This lesson, we see how to use Diesel in menu macros and AutoLISP routines, and see just how complex Diesel can get.
To use Diesel code within a menu file, I must prefix the code with the $M= code. For example, Autodesk uses Diesel in the menu files it provides with AutoCAD to turn check marks on and off in the pull-down menus. For example, when I click on the Associative Dimensions item in the Options menu, AutoCAD turns off associative dimensions (actually, it sets the value of system variable DimAso to 0) and removes the check mark from in front of Associative Dimensions in the menu.
It is fairly trivial to display the check mark: simply prefix the word with the !. symbol. Turning the check mark on and off is tricky and requires the use of Diesel programming. The menu macro below shows how Autodesk programmers accomplished this:
[$(if,$(getvar,dimaso),!.)/vAssociative Dimensions]'_dimaso $M=$(-,1,$(getvar,dimaso))
(When I type this in, I make sure I type it as one long line of text; don't break the line, or else the macro won't work!) Before we step through the menu macro, bit by bit, keep this in mind: A menu macros have two parts: (1) the label, which is inside the square brackets; and (2) the macro code, which follows the square brackets.
[
The opening square bracket is the start of a macro label. That's
the word(s) I see when I use a pull-down menu. In this case, I
would see Associative Dimensions, with or without the check
mark.
$(if,
Here starts the "if" Diesel expression, which
tests the following expression. If the expression is true, then
apply the next expression. "True" in Diesel means
it has a value of 1; "false" means the value
is zero.
$(getvar,dimaso)
This is an embedded Diesel expression that gets the value of system
variable DimAso. This system variable has two possible
values, which has four different meanings, depending on who is
accessing the value:
Value of DimAso Meaning for AutoCAD Meaning for Diesel "if" Expression --------------- --------------------------- ---------------------------------- 1 (default) Use associative dimensions True 0 Use non-associative dims False
,!.
Recall that the comma separates expressions and values in a Diesel
statement. No spaces are allowed! The pair of characters
!. (called a metacharacter) are interpreted by AutoCAD's
menu system to mean, "display a check mark." I hope
you can see how the check mark is displayed by the above bit of
Diesel code: the "if" statement uses the !. metacharacter
to display the check mark whenever the value of DimAso is true.
When DimAso is false (equals 0), the Diesel "if"
statement prevents the !. metacharacter from being activated.
)
The final parenthesis ends the Diesel "if" expression.
/vAssociative Dimensions
The /v metacharacter is how AutoCAD menus display the underlined
character in pull-down menus. In this case, the "v"
in the word Associative is underlined. Recall that the
underlined character is the keyboard shortcut: I don't need to
pick Associative Dimensions with my mouse; I can press
the letter "v" if I am so inclined.
]
The closing square parenthesis ends the label section of the menu
macro. What follows is the actual menu macro:
'_dimaso
This is the only part of the menu macro that looks recognizable
to me. It's is the DimAso system variable. Recall that
all system variables can be typed at the Command: prompt like
a command name; the SetVar command is optional. DimAso
is prefixed by the ' (apostrophe) to make it a command transparent;
and it is further prefixed by the _ (underscore) to internationalize
the command name.
$M=
The $M= combination of characters is a special code to
alert the menu macro that a Diesel function is coming. Why here,
and not earlier inside the label? I dunno. My guess is that AutoCAD
treats the stuff inside the label section [inside the square brackets]
as plain text input. Text in the macro area (following the square
brackets) is treated as code and the $M= could have something
to do with storing data on the stack. (The "stack" is
a crude form of memory known as FIFO -- first in, first
out -- used by AutoCAD's menu programming system to remember jumps
between menus).
$(-,1,
This is the Diesel function that subtracts. In this case, it is
subtracting from 1, the value following (shown below).
$(getvar,dimaso)
Embedded inside the subtract function is Diesel's GetVar function
again. This time, however, after the value of DimAso is
gotten, it is subtracted from 1, then stored back into DimAso.
That makes me want to ask, "Where the heck is all that going
on?" It's true that there is no equivalent "$(setvar"
function in Diesel; the change in the value of DimAso happens
sort of automatically.
The effect of the code is as follows:
Value of DimAso Action of Macro New Value of Macro --------------- --------------- ------------------ 1 (default) 1-(DimAso) 0 0 1-(DimAso) 1
It toggles the DimAso variable.
)
Finally, the macro ends with the closing parenthesis.
Does your head hurt yet? The happy ending to this mind-numbing exercise is that you can reuse the code for all kinds of toggle situations. There are many toggle-type commands in AutoCAD. I can think of Grid, Snap, Ortho, TileMode, SplFrame ... In fact, simply go though the list of system variables: anyone that has a value of just 0 or 1 is a toggle. To reuse this code for other toggles, simply replace the parts shown on separate lines:
[$(if,$(getvar, ; Keep this code.
dimaso ; Replace with appropriate system variable
name.
),!.)/ ; Keep.
vAssociative Dimensions ; Replace with appropriate
shortcut key and label name.
]'_dimaso $M=$(-,1,$(getvar, ; Keep.
dimaso ; Replace with system variable name,
same as above.
)) ; Keep.
For example, here is the code reused for toggling the display of the grid:
[$(if,$(getvar,gridmode),!.)/GGrid Markings]'_gridmode $m=$(- ,1,$(getvar,gridmode))
The macro is one long line; dont split it into two lines in your menu file!
There are two ways to use Diesel expressions inside an AutoLISP routine: (1) with the SetVar function; or (2) the MenuCmd function. I don't know if there is a preference for either among the programming community; in either case, I am accessing Diesel in an indirect manner.
The setvar function is used in conjunction with the ModeMacro system variable. You'll recall from the previous Tailoring AutoCAD tutorial that the ModeMacro system variable is used to execute Diesel from the Command prompt. The same trick is used here.
To show how this works, I'll write an AutoLISP routine to displays the fillet radius on the status line -- using Diesel.
(defun frad ()
(setvar "modemacro" "Current fillet radius:
$(getvar,filletrad)")
)
The FilletRad system variable stores the current setting for the filleting radius.
To display more than one piece of information on the status line, I use the StrCat function to concatenate the two Diesel strings to the ModeMacro system variable in one piece. The following AutoLISP code displays the two chamfer distances at the status line:
(defun chab ()
(setvar "modemacro" (strcat "Chamfer
A: $(getvar,chamfera)" "Chamfer B: $(getvar,chamferb)"
) )
)
The second method uses the MenuCmd function, along with the M= menu macro construct, as follows:
(defun chab ()
(menucmd "M=Current fillet radius: $(getvar,filletrad)")
)
The M= should be familiar from the earlier discussion of using Diesel inside of menu macros.
Comments on this tutorial series? Tell me about it.