collegeCAD, good job! and congrats with your 'A'
I took the liberty of making a few suggestions to your code. It's still a schoolbook example (!), so I hope you have covered some of the stuff already. Maybe there are some things in it you can use, maybe not.
;;; "User Friendly Layer Setup"
;;; layersetup1.lsp
;;; By: Jon Nelson
;;; DFTG1352
;;; Thomas Longnecker
;;; Altered and commented by someone else
(defun c:layersetup ()
(setq cmd (getvar "CMDECHO"))
(setvar "cmdecho" 0)
;; Loading already loaded linetypes will result in
;; a prompt that will cause the routine to get stuck
;; in the LINETYPE command. This can be avoided by
;; setting the sysvar EXPERT to 3 before calling the
;; command.
;; Of course, with all changes in the users environment,
;; remember to reset it after you're done with it! The
;; same goes for CMDECHO above.
(setq expert (getvar "EXPERT"))
(setvar "EXPERT" 3)
(command "linetype" "load" "*" "acad.lin" "")
(setvar "EXPERT" expert)
(vl-load-com)
(setq n nil)
(setq tn t)
(while tn
;; For verifying symbol names in AutoLISP there is an
;; often overlooked function called SNVALID. Instead of
;; explaining here what it does, it'll be a good excercise
;; to look it up in the help reference. In short, it can be
;; used to verify layer names:
(setq layName (getstring t "\nPlease enter a new layer name or [Enter] to continue: "))
(if (snvalid layName)
(setq n (append (list layName) n))
(setq tn nil)
)
)
(foreach item n
;; You seem to be well aware of the INITGET function, but
;; are you also aware that other GETxxx functions can accept
;; keywords? Because the LAYER command can accept integers, why
;; not use GETINT to retrieve the color?
;; However, because GETINT accepts integers between –32,768 and
;; 32,767 we need to verify the input before proceeding, so we'll
;; use tn as a flag once again to allow for multiple tries.
(setq tn T)
(while tn
(initget 1 "Red Yellow Green Cyan Blue Magenta White")
(setq layColor (getint (strcat "\nPlease enter a STANDARD COLOR NAME for "
item
"'s layer: "
)
)
)
(if (or (= (type layColor) 'STR) (< 1 layColor 255))
(setq tn nil)
(princ "\nInvalid color. Try again")
)
)
;; The above code should take care of input that any
;; AutoCAD user is familiar with so I don't think there
;; is a need to inform of valid inputs
;; If you want to inform about available linetypes then
;; it's possible to use the linetypes that are actually
;; available on the machine. I've known people who thought it
;; might save resources to delete some of these linetypes they
;; never use anyway from the acad.lin file.
;; Of course, getting the linetype pseudo-appearances are a
;; little harder so we'll save that for another time :)
;; The DRAWBACK of this method is that it's really hard to convert
;; the names and use them in a initget! But as a compensation for
;; our own codes sake we'll build a list to verify input.
;; By the way, I don't see why you are having problems with
;; complex linetypes?
;; First, reset some variables (no local vars, remember? :)
(setq ltype nil ltypeInfo "" ltypeList nil)
;; Then run through the linetype table to pick up each name
;; of the actually available linetypes
(while (setq ltype (tblnext "LTYPE" (not ltype)))
(setq ltypeInfo (strcat ltypeInfo "\n" (cdr (assoc 2 ltype)))
ltypeList (cons (cdr (assoc 2 ltype)) ltypeList)
)
)
;; We'll use tn again as a flag to control a loop until a
;; valid input is bagged. I don't think throwing an alert in
;; the users face is attractive. Instead we can provide an
;; alert with the info if the user desires. In order to do this
;; we can utilize bit 128 of INITGET that allows any arbitrary
;; input (= linetype name) and still have a chance to catch
;; the users request for help ("?")
(setq tn T)
(while tn
(initget 128 "? Continuous")
(setq ltype (getkword (strcat "\n\nPlease enter a linetype for "
item
"'s layer or [?/Continuous]: "
)
)
)
(if (= ltype "?")
(alert (strcat "For linetypes, use one of the\nlisted lintetypes:\n" ltypeInfo))
;; Because linetypes are returned in uppercase by the
;; linetype table and the user could have used any
;; case he like, we'll convert his string to uppercase
;; before comparing it. Of course, if linetype is "Continuous"
;; then simply proceed
;; Also, because GETKWORD returns nil (and not "") on empty
;; response, we'll check for this.
(if (and ltype (or (= ltype "Continuous") (member (strcase ltype) ltypeList)))
(setq tn nil)
(princ "\nInvalid linetype name. Try again")
)
)
)
(command "LAYER" "MAKE" item "COLOR" layColor item "LTYPE" ltype item "")
)
(setq
current (getstring t "\nPlease enter which layer you would like to make current: ")
)
;; Just making sure that the layer name input here is
;; a valid one by looking it up in the layer table before
;; trying to set it active
(if (tblsearch "LAYER" current)
(command "layer" "s" current "")
(princ "\nNo such layer .. take a typing lesson!")
)
;; Reset environment to what it was
(setvar "cmdecho" cmd)
(princ)
)
(prompt "Enter LAYERSETUP to start")