Good AutoLISP Programming Techniques

When creating AutoLISP routines, the programmer should keep in mind not only correct syntax, but also a well-structured program that is easy to comprehend, forgiving of mistakes, easy to debug, and easy to edit.

Formatting

You can format manually while you type. But Visual LISP includes helpful formatting tools. They automatically insert tabs and spaces where needed to give you added clarity and help you track parentheses. You can either Format edit window or Format selection.

AutoLISP ignores spaces and carriage returns, so use them to make the routine more understandable to the programmer.

Unformatted routine:

(defun C:TRIANGLE ()
(setq PT1 (getpoint “Pick a Point: “)
PT2 (getpoint “Pick another point: “)
PT3 (list (car PT1) (cadr PT2)))
(command “line” PT1 PT2 PT3 “c”))

Formatted routine:

You can set the formatting options under Tools>Environment Options> Visual LISP Format Options.

Commenting

Comments help you and anyone else reading the file to understand the code. Use a semi-colon in front of any line to add comments to a file. Anything on a line to the right of a semi-colon is ignored.

  • At the beginning of the routine be sure to include a comment that states the filename, what the function does, the author, the date, and the version.
  • You may also want to break longer functions up into stages and explain what each stage does.
  • While just one semi-colon will do the job, some people prefer two or three for visibility. Visual LISP automatically adds three semicolons in front of any comment starting at a blank line that is not indented, two semicolons when the new line is indented and one when tabbed over to a column location or after a closing parenthesis.
  • To automatically add comments after a closing parenthesis on a separate line, check the “Insert form-closing comment” box in the dialog under Tools>Environment Options> Visual LISP Format Options.

Comment Block/Uncomment Block

To use these tools, simply select the lines you want to comment or uncomment and press the button. Comment Block adds semicolons at the start of the selected lines; Uncomment Block removes the semicolons.

For example, you may want to test just a portion of your routine in AutoCAD. You can highlight the undesired portion and comment it out with the click of a button. When you are ready to test this section as well, highlight it again and press the Uncomment Block tool.

Commenting Example

;;;This program draws a triangle based on the two
;;;endpoints of the hypotenuse.
;;;June 14, 2012

(defun C:TRIANGLE ()
(setq PT1 (getpoint “Pick a Point: “)
          PT2 (getpoint “Pick another point: “)
          PT3 (list
                         (car PT1)
                         (cadr PT2) )
                   ;end list
) ;end setq
(command “line” PT1 PT2 PT3 “c”)
) ;end defun

Naming

  • Use symbol names that make sense. Use a name that relates to the value such as, PT1, ReferencePoint, SCALE_FACTOR, etc.
  • Visual LISP will complete a function or symbol name if you type the first few letters and the press Ctrl + Spacebar. Repeat if you don’t come up with the right name at first.
  • Symbols are not case sensitive but capitalization can help you differentiate between symbols and functions when you are not in Visual LISP.
  • Remember, don’t use PI, T, or any function name such as ANGLE as a symbol name.
  • Give understandable file names for your LISP routines. For example, not DS.LSP but DATESTAMP.LSP.

Prompting

Use error control such as the (iniget) and (getkword) functions. Expect the unexpected input. Make the routine as easy to use as possible.

Write prompts that look like AutoCAD’s. This makes a smoother interface between your LISP routine and the main package. For example: “Choose a color: Red or [Blue/Yellow/Green]: ” Don’t forget that AutoCAD 2000 has a new prompt style.

Setting Local Variables

Another good clarity practice is to keep the track of the variables you use as symbols and make sure you do not leave them active in AutoCAD if they will impact another routine. This is called localizing the variables.

All variables in use in a session of AutoCAD are stored in the atom list. This also includes all the AutoLISP function names.

Explanation: the (defun) function options

A variable can be declared exclusive to a given function. These “local” variables are declared in the same parentheses as the argument list of the (defun):

(defun function_name ([arguments / local_variables])

The optional arguments are the variables that you will want permanently assigned in a drawing session. These may be symbol information that you will use in another AutoLISP routine. Or they are the ones you must supply for the function to work.

The optional local_variables set aside the name and value of local variables. They will not be added to the atom-list and will only be retained in memory while the function is executing.

  • Arguments and local variables are separated by a forward slash “/”.
  • Local variables remain in memory only while the routine is executing. This allows the use of longer and clearer variable names.
  • You may need to exit and restart AutoCAD to remove any existing variables.

Explanation: the (atoms-family) function

The (atoms-family) function returns a list of all the symbols currently defined, called the atom list. This way you can know what symbols have been defined in the drawing session.

(atoms-family format [symbol])

The format argument specifies whether the symbols will be returned as symbols or strings: 0 returns a list of symbols and 1 returns list of symbols converted to strings.

The optional symbol argument is used to check whether each symbol in the symbol list exists in the current editing session. If the symbol exists, the argument returns a symbol name; otherwise it returns nil.

Command: (atoms-family 1 ‘(“CAR”))
(“CAR”)

Example: Localized Variables

;;;MATRIX.LSP
;;;C:MATRIX – A function to create a rectangular array
;;; by total row and column distance.
(defun c:MATRIX ( / ROW-NUMBER COL-NUMBER STARTPT TOTAL-ROW
TOTAL-COL ROW-DIST COL-DIST SS1)
(command “graphscr”)
(initget (+ 1 2 4)
(setq ROW-NUMBER (getint “Number of rows (—): “))
(initget (+ 1 2 4)
(setq COL-NUMBER (getint “Number of columns (|||): “))
(setq STARTPT (getpoint “Starting point: “))
(initget (+ 1 2)
(setq TOTAL-ROW (getdist STARTPT “\nTotal row distance: “))
(initget (+ 1 2)
(setq TOTAL-COL (getdist STARTPT “\nTotal column distance: “))
(setq ROW-DIST (/ TOTAL-ROW (1- ROW-NUMBER)))
(setq COL-DIST (/ TOTAL-COL (1- COL-NUMBER)))
(setq SS1 (ssget))
(command “array” SS1 “” “r” ROW-NUMBER COL-NUMBER ROW-DIST COL-DIST) (princ)
); close defun