AutoCAD LISP系统变量设置与重置异常:PLINE执行前变量提前恢复
问题分析
你的核心问题是AutoCAD LISP中command函数的执行逻辑导致的:当你在command里使用PAUSE时,LISP只会暂停等待用户的单次输入(比如PLINE的起点),一旦用户完成这个输入,LISP就会继续执行后续代码(也就是varset),但此时PLINE命令还处于交互状态(用户还在绘制线段、还没结束命令),所以系统变量提前被重置,不符合你的预期。
另外你的代码还有个隐性bug:lis和var是varget函数内的局部变量,varset函数无法正确访问它们,这可能导致变量重置不完全。
解决方案
我们分两步修复问题:
1. 修复变量作用域问题
把需要跨函数访问的变量设为全局变量(用星号前缀标识,这是AutoCAD LISP的惯例),确保varset能正确读取之前保存的系统变量值:
(defun varget () (setq *lis* '("orthomode" "snapmode")) ; 定义全局变量保存系统变量名称 (setq *var* (mapcar 'getvar *lis*)) ; 保存原始系统变量值 (setq var1 '(1 1)) (setq no 0) (repeat (length *lis*) (setvar (nth no *lis*) (nth no var1)) (setq no (1+ no)) ) (princ) ) (defun varset () (setq no 0) (repeat (length *lis*) (setvar (nth no *lis*) (nth no *var*)) (setq no (1+ no)) ) (princ) )
2. 等待PLINE命令完全结束后再重置变量
不要在command调用里直接带PAUSE,而是先启动PLINE命令,然后通过循环等待cmdactive系统变量变为0(表示当前没有活跃命令),确保用户完全结束PLINE操作后再执行后续代码。同时我们用cond替代多个IF,让代码更简洁:
(defun C:wire () (progn (varget) (setq prevlayer (getvar "clayer")) ; 转大写避免用户输入小写导致匹配失败,添加换行让提示更友好 (setq P (strcase (getstring "\nAudio(A)/Video(V)/Comm(CO)/Coax(R)/Control(C)/(N)etwork/(P)ower:"))) (cond ((= P "V") (command "-LAYER" "M" "VIDEO" "C" "150" "" "") (command "PLINE") (while (not (zerop (getvar 'cmdactive))) (command pause) ) ) ((= P "A") (command "-LAYER" "M" "AUDIO" "C" "94" "" "") (command "PLINE") (while (not (zerop (getvar 'cmdactive))) (command pause) ) ) ((= P "CO") (command "-LAYER" "M" "COMM" "C" "206" "" "") (command "PLINE") (while (not (zerop (getvar 'cmdactive))) (command pause) ) ) ((= P "R") (command "-LAYER" "M" "COAX" "C" "44" "" "") (command "PLINE") (while (not (zerop (getvar 'cmdactive))) (command pause) ) ) ((= P "C") (command "-LAYER" "M" "CONTROL" "C" "10" "" "") (command "PLINE") (while (not (zerop (getvar 'cmdactive))) (command pause) ) ) ((= P "N") (command "-LAYER" "M" "NETWORK" "C" "210" "" "") (command "PLINE") (while (not (zerop (getvar 'cmdactive))) (command pause) ) ) ((= P "P") (command "-LAYER" "M" "POWER" "C" "7" "" "") (command "PLINE") (while (not (zerop (getvar 'cmdactive))) (command pause) ) ) ) (setvar "clayer" prevlayer) (varset) (princ) ) )
额外优化说明
- 用
strcase处理用户输入,避免因大小写导致的匹配失败 - 用
cond替代多个独立IF,代码结构更清晰易维护 - 给
getstring添加换行符,让命令行提示更易读
这样修改后,当你执行wire命令选择线路类型后,PLINE会正常运行直到你手动结束(按回车/空格确认),之后LISP才会执行图层恢复和系统变量重置,完全符合你的预期。
内容的提问来源于stack exchange,提问作者Perry Chapman




