AutoLISP: The Complete Guide — Chapter 9 / 16

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:

  1. They display a prompt message in the command line
  2. They wait for the user to provide a value (click, keyboard input, etc.)
  3. 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 \n so 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 for getcorner.

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: getdist always 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 than getreal.

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 getangle or getorient? Use getangle when you want a relative angle (a rotation, an angular offset). Use getorient when 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:

  • getpoint for the first corner, with initget 1 to make it mandatory
  • getkword to offer a mode choice, with a default value
  • getdist for the dimensions, with the base point for the rubber-band line
  • getcorner for 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.


Helping hand Need an AutoCAD (AutoLISP, ObjectARX, .NET, VBA) development? Contact me for a free quote.