Managing Configuration Files in AutoLISP
Monday, March 16, 2026When developing an AutoLISP program, you often need to store configuration settings: an output directory, a unit of measurement, a naming prefix, etc.
The first instinct is to reach for a classic text format like .ini:
[general]
unit=cm
output-directory=C:\Output
But this requires writing a parser to read sections, keys, and values. It's doable, but tedious.
Leveraging AutoLISP Syntax
AutoLISP is a dialect of Lisp, and in Lisp, code and data share the same syntax: lists. So you can write a configuration file directly as an association list and load it with the built-in read function.
Here is an example configuration file Config.cfg:
(
("unit" . "cm")
("output-directory" . "C:\\Output")
)
This is a list of dotted pairs. Each pair associates a key (a string) with a value. It's the equivalent of a dictionary in Python or a Dictionary<string, string> in .NET.
Loading the Configuration
The load-configuration function opens the file, reads all lines, concatenates them, then uses read to convert the text into an AutoLISP list:
;;; Loads a configuration from a file (association list).
;;; path : path to the configuration file
;;; Returns the association list, or nil on error
(defun load-configuration (path / file content line configuration)
(setq file (open path "r"))
(if file
(progn
(setq content "")
(while (setq line (read-line file))
(setq content (strcat content line))
)
(close file)
(setq configuration (read content))
configuration
)
(progn
(princ (strcat "\nError: unable to open file " path))
nil
)
)
)
The magic happens at the (read content) line: AutoLISP's read function parses the text and rebuilds the data structure. No need to write a parser — the language handles it.
Reading and Modifying Values
Once the configuration is loaded into a global variable *CONFIG*, you can read a value with assoc and modify it with subst.
Naming convention: in AutoLISP, any variable not declared after the
/in the argument list is global. To clearly distinguish global variables from local ones, a naming convention is used. Here, the asterisks around*CONFIG*immediately signal that it is a global variable. This notation is inspired by*error*, the well-known AutoLISP global function used to install a custom error handler. You can also use the$prefix, for example$config. The important thing is to choose a convention and stick with it.
;;; Returns the value associated with a key in the configuration
(defun get-configuration-value (key)
(cdr (assoc key *CONFIG*))
)
;;; Modifies or adds a value in the configuration
(defun set-configuration-value (key value / old)
(setq old (assoc key *CONFIG*))
(if old
(setq *CONFIG* (subst (cons key value) old *CONFIG*))
(setq *CONFIG* (cons (cons key value) *CONFIG*))
)
)
The get-configuration-value function uses assoc to find the pair matching the key, then cdr to extract the value.
The set-configuration-value function handles two cases:
- If the key already exists,
substreplaces the old pair with the new one. - Otherwise,
consadds the new pair at the head of the list.
Usage Example
(defun C:TESTCONFIG ()
(setq *CONFIG* (load-configuration "C:\\Temp\\Config.cfg"))
(if *CONFIG*
(progn
(princ (strcat "\nUnit: " (get-configuration-value "unit")))
(princ (strcat "\nOutput directory: " (get-configuration-value "output-directory")))
)
(princ "\nFailed to load configuration.")
)
(princ)
)
Result in the AutoCAD console:
Unit: cm
Output directory: C:\Output
Saving the Configuration
You can also write a function to save the modified configuration:
;;; Saves the configuration to a file
;;; path : path to the configuration file
;;; Returns T on success, nil otherwise
(defun save-configuration (path / file pair)
(setq file (open path "w"))
(if file
(progn
(write-line "(" file)
(foreach pair *CONFIG*
(write-line
(strcat " (\"" (car pair) "\" . \"" (cdr pair) "\")")
file
)
)
(write-line ")" file)
(close file)
T
)
(progn
(princ (strcat "\nError: unable to write to file " path))
nil
)
)
)
Each pair is written on a separate line to keep the file readable.
Conclusion
By using AutoLISP's native syntax as a data format, you get a simple and effective configuration system without having to write a parser. The read function does all the heavy lifting.
Need an AutoCAD (AutoLISP, ObjectARX, .NET, VBA) development? Contact me for a free quote.