I've just started messing around with LISP programming, and came up with the following routine. I put this code together by browsing through the online developer documentation, and it illustrates several questions that arose along the way. The command works exactly like the built-in AutoCAD offset command, except that the resulting objects reside on the current layer, instead of the layer of the source object.

I decided that the easiest way to implement the function would be to have it use AutoCAD's default offset command, rather than by creating entities directly via entmake or vla commands, so that I didn't have to worry about how to handle offsetting different types of entities.

The code works, but a bunch of what I did seems really clunky to me, mostly because I seemed to be having typing issues. Having the getdist function return either a real or a string seemed to cause issues. It seemed like there should be an easier way of going about things. (Is there a sprintf sort of functionality in AutoLISP?) I used a global variable to remember the offset distance between successive executions of the function, but is that how I should have done it? The routine also does no error-checking or handling. How should it handle a failure of the offset command (for example, if the selected item cannot be offset)? What else should I have done different?

(defun C:OFS (/ prev prm dist e p edata clayer)
  (setvar "cmdecho" 0)
  (setq clayer (getvar "clayer"))
  (princ "\nOffset Object\n")
  (if (= 'STR (type *ZYZ_OFF*))
    (setq prev *ZYZ_OFF*)
    (if	(= 'REAL (type *ZYZ_OFF*))
      (setq prev (rtos *ZYZ_OFF*))
      (setq prev "")
  (setq prm (strcat "Distance to offset or Through <" prev ">:"))
  (initget 68 "Through")
  (setq dist (getdist prm))
  (if (/= dist nil)
    (setq *ZYZ_OFF* dist)
  (if (/= *ZYZ_OFF* nil)
      (if (= 'REAL (type *ZYZ_OFF*))
	(setq prm "\nSelect side to offset:")
	(setq prm "\nSelect through point:")
      (while (setq e (entsel "\nSelect entity to offset:"))
	(redraw (car e) 3)
	(if (setq p (getpoint prm))
	    (command "_.offset" *ZYZ_OFF* e p "")
	    (setq edata (entget (entlast)))
	    (setq edata
		   (subst (cons 8 clayer) (assoc 8 edata) edata)
	    (entmod edata)