Interacting with the User
So far, our programs have been working with values defined in advance in the code. But a truly useful program needs to interact with the user: asking where to place an object, what dimension to use, what name to assign. AutoLISP provides a family of functions dedicated to this purpose: the get* functions.
The General Principle
All get* functions follow the same pattern:
- They display a prompt message in the command line
- They wait for the user to provide a value (click, keyboard input, etc.)
- They return the entered value in the appropriate type
(setq point (getpoint "\nClick a point: "))
(setq radius (getreal "\nCircle radius: "))
Convention: always start your prompt message with
\nso it appears on a new line in the command line. Without this\n, the message runs into the previous text and becomes hard to read.
Collecting Points
getpoint — a point in the drawing
getpoint asks the user to click a point or enter coordinates. It returns a list of three real numbers (X Y Z):
(setq point (getpoint "\nInsertion point: "))
;; The user clicks → (125.0 80.5 0.0)
(car point) ; → 125.0 (X coordinate)
(cadr point) ; → 80.5 (Y coordinate)
(caddr point) ; → 0.0 (Z coordinate)
getpoint accepts an optional base point. When provided, AutoCAD draws a rubber-band line between this base point and the cursor, helping the user visualize the direction:
(setq point1 (getpoint "\nFirst point: "))
(setq point2 (getpoint point1 "\nSecond point: "))
getcorner — a rectangle corner
getcorner is similar to getpoint, but it draws a rubber-band rectangle between the base point and the cursor. It is ideal for defining a rectangular area:
(setq corner1 (getpoint "\nFirst corner: "))
(setq corner2 (getcorner corner1 "\nOpposite corner: "))
Note: unlike
getpoint, the base point is mandatory forgetcorner.
Collecting Numeric Values
getint — an integer
(setq count (getint "\nNumber of copies: "))
;; The user types 5 → 5
getint only accepts integers. If the user types 3.5 or abc, AutoCAD asks them to try again.
getreal — a real number
(setq height (getreal "\nText height: "))
;; The user types 2.5 → 2.5
getdist — a distance
getdist is the most versatile function for obtaining a distance value. The user can either type a value or click two points in the drawing — AutoCAD then calculates the distance between them:
(setq length (getdist "\nLength: "))
;; The user types 50.0 → 50.0
;; OR clicks two points → distance between them
With a base point, the user only needs to click a single point:
(setq point1 (getpoint "\nStart point: "))
(setq length (getdist point1 "\nLength: "))
;; The user clicks a second point → distance is calculated
Best practice:
getdistalways returns the value in the drawing's internal units, regardless of the display format (architectural, decimal, etc.). It is the recommended function for requesting dimensions, rather thangetreal.
getangle — an angle
getangle prompts for an angle. The user can type a value or click two points to define the direction. The angle is always returned in radians, regardless of the AUNITS system variable:
(setq angle (getangle "\nRotation angle: "))
;; The user types 45 (degrees) → 0.785398 (radians)
With a base point:
(setq base-point (getpoint "\nBase point: "))
(setq angle (getangle base-point "\nAngle: "))
getorient — an absolute angle
getorient works like getangle, but it ignores the ANGBASE (base angle) and ANGDIR (angle direction) system variables. The returned angle is always measured from east, in the counterclockwise direction. Use getorient when you need an absolute angle, independent of the user's configuration.
(setq orientation (getorient "\nOrientation: "))
When to choose
getangleorgetorient? Usegetanglewhen you want a relative angle (a rotation, an angular offset). Usegetorientwhen you want an absolute direction (the orientation of text, a block).
Collecting Text
getstring — a string of characters
(setq name (getstring "\nLayer name: "))
;; The user types "Construction" → "Construction"
By default, getstring stops at the first space. If you need to accept spaces (for example, for a full name), pass T as the first argument:
(setq description (getstring T "\nDescription: "))
;; The user can type "Load-bearing wall level 2" → "Load-bearing wall level 2"
Without the T, typing "Load-bearing wall" would be truncated to "Load-bearing".
Collecting a Keyword
getkword — a choice among options
getkword lets you offer a menu of choices to the user. First define the options with initget, then call getkword:
(initget "Yes No")
(setq answer (getkword "\nConfirm? [Yes/No]: "))
;; The user types "Yes", "Y", "No" or "N"
Keywords are case-insensitive. AutoLISP also accepts abbreviations: the uppercase letters in the initget string define the minimum prefix. For example, "Yes No" accepts Y for Yes and N for No.
To control abbreviations more precisely:
(initget "Red Green Blue")
(setq color (getkword "\nColor? [Red/Green/Blue]: "))
;; "R" → "Red", "G" → "Green", "B" → "Blue"
If the user types a word that does not match any keyword, AutoCAD displays an error message and asks for input again.
Controlling Input with initget
The initget function lets you restrict what the user can enter. It is called before the get* function and affects only the next call.
Control Bits
initget accepts an integer (or a combination of bits) that enables different restrictions:
| Bit | Value | Effect |
|---|---|---|
| 1 | 1 | Disallows empty input (pressing Enter without typing anything) |
| 2 | 2 | Disallows a value of zero |
| 4 | 4 | Disallows negative values |
| 8 | 8 | Does not check drawing limits (even if LIMCHECK is enabled) |
| 32 | 32 | Displays coordinates with a dash instead of a comma in 2D |
| 64 | 64 | Ignores the Z coordinate (returns a 2D point) |
| 128 | 128 | Allows arbitrary input (returns the string as-is) |
Bits are combined by addition:
;; Disallow empty (1) + zero (2) + negative (4) = 7
(initget 7)
(setq radius (getreal "\nRadius (positive non-zero value): "))
;; Disallow empty input
(initget 1)
(setq point (getpoint "\nRequired point: "))
Combining Bits and Keywords
initget can receive both bits and keywords:
(initget 7 "Diameter")
(setq value (getreal "\nRadius or [Diameter]: "))
Here, the user can either type a positive non-zero number or type D (or Diameter) to choose the diameter option. When a keyword is entered, getreal returns the keyword as a string instead of a number — so you need to test the result.
Handling Keywords in get* Functions
When initget defines keywords, numeric get* functions (getreal, getint, getdist, etc.) and geometric ones (getpoint, getcorner, etc.) can return either their normal type or a string (the keyword). You must therefore test the type of the returned value:
(defun c:my-circle (/ center value radius)
(setq center (getpoint "\nCircle center: "))
(initget 7 "Diameter")
(setq value (getdist center "\nRadius or [Diameter]: "))
(if (= (type value) 'STR)
;; The user typed "Diameter"
(progn
(initget 7)
(setq radius (/ (getdist center "\nDiameter: ") 2.0))
)
;; The user entered a number → it's the radius
(setq radius value)
)
(command "_CIRCLE" center radius)
(princ)
)
Default Values
The get* functions do not natively handle default values, but it is easy to implement. The idea: do not disallow empty input (no bit 1 in initget), and test whether the result is nil:
(defun c:custom-text (/ height)
;; No bit 1 → empty input is allowed
(initget 6) ; Disallow zero and negative, but allow empty
(setq height (getreal "\nText height <2.5>: "))
;; If the user pressed Enter without typing anything
(if (not height)
(setq height 2.5)
)
(princ (strcat "\nChosen height: " (rtos height)))
(princ)
)
AutoCAD convention: the default value is displayed in angle brackets
< >in the prompt message. This is a convention that all AutoCAD users are familiar with.
Complete Example: Drawing an Interactive Rectangle
Here is a program that puts into practice all the functions covered in this chapter:
(defun c:interactive-rectangle (/ corner1 mode width height corner2 corner3 corner4)
;; Ask for the first corner
(initget 1)
(setq corner1 (getpoint "\nFirst corner: "))
;; Ask for the input mode
(initget "Dimensions Corner")
(setq mode (getkword "\nMode? [Dimensions/Opposite corner] <Opposite corner>: "))
(if (not mode)
(setq mode "Corner")
)
(if (= mode "Dimensions")
;; Dimensions mode: ask for width and height
(progn
(initget 7)
(setq width (getdist corner1 "\nWidth: "))
(initget 7)
(setq height (getdist corner1 "\nHeight: "))
(setq corner2 (list (+ (car corner1) width) (cadr corner1)))
(setq corner3 (list (+ (car corner1) width) (+ (cadr corner1) height)))
(setq corner4 (list (car corner1) (+ (cadr corner1) height)))
)
;; Opposite corner mode: ask for the diagonal corner
(progn
(setq corner3 (getcorner corner1 "\nOpposite corner: "))
(setq corner2 (list (car corner3) (cadr corner1)))
(setq corner4 (list (car corner1) (cadr corner3)))
)
)
;; Draw the rectangle
(command "_LINE" corner1 corner2 corner3 corner4 "_Close")
(princ (strcat "\nRectangle drawn — "
"Width: " (rtos (distance corner1 corner2))
", Height: " (rtos (distance corner2 corner3))
))
(princ)
)
This program illustrates several concepts:
getpointfor the first corner, withinitget 1to make it mandatorygetkwordto offer a mode choice, with a default valuegetdistfor the dimensions, with the base point for the rubber-band linegetcornerfor the opposite corner, with the rubber-band rectangle
Summary
| Function | Returns | Usage |
|---|---|---|
getpoint |
List (X Y Z) | Click or enter a point |
getcorner |
List (X Y Z) | Click a corner (rubber-band rectangle) |
getint |
Integer | Enter an integer |
getreal |
Real | Enter a real number |
getdist |
Real | Enter or click a distance |
getangle |
Real (radians) | Enter or click a relative angle |
getorient |
Real (radians) | Enter or click an absolute angle |
getstring |
String | Enter text |
getkword |
String | Choose among keywords |
initget |
nil | Configure the next get* function |
In the next chapter, we will use these inputs to interact with the AutoCAD drawing: creating lines, circles, and modifying existing entities.
Need an AutoCAD (AutoLISP, ObjectARX, .NET, VBA) development? Contact me for a free quote.