;;; SPIS_RUN_SETS.lsp
;;; SPISRUNSETS — запускает сборку комплекта дисциплин из AutoCAD.
;;;
;;; Команда НЕ создаёт файлы сама: операции с документами (создать,
;;; открыть, сохранить) из LISP блокируют AutoCAD — проверено на
;;; AutoCAD 2020: vla-Open, _.OPEN и _.SAVEAS внутри LISP вешают сессию.
;;;
;;; Поэтому команда запускает ВНЕШНИЙ Python-скрипт, который работает
;;; с AutoCAD через COM. AutoCAD остаётся свободен.
;;;
;;; Что создаётся (схема согласована):
;;; ЭТР = АР + СС + ВК + ОВ
;;; СС = АР + ВК + ОВ + ЭТР
;;; ВК = АР + СС + ОВ + ЭТР
;;; ОВ = АР + СС + ВК + ЭТР
;;; АР — основа, сама ничего не подключает
;;;
;;; ЗАПУСК идёт через run_sets_launcher.py: он создаёт bat-файл в
;;; OEM-кодировке (cp866) и стартует сборку скрыто. AutoLISP так не
;;; умеет — (open ... "w") пишет в системной кодировке, и русские
;;; пути в bat бьются.
(vl-load-com)
;; Папка с инструментами СПИС (пути всегда с обратным слэшем).
(defun srs:tools-dir (/ f r)
(cond
;; 1) файл найден в путях поддержки
((setq f (findfile "SPIS_RUN_SETS.lsp"))
(vl-string-translate "/" "\\" (vl-filename-directory f)))
;; 2) папка, запомненная загрузчиком SPIS_TOOLS / командой SPISSETDIR
((and (setq r (vl-catch-all-apply 'vl-registry-read
(list "HKEY_CURRENT_USER\\Software\\GENPRO\\SPIS" "ToolsDir")))
(not (vl-catch-all-error-p r)) r (> (strlen r) 0))
(vl-string-translate "/" "\\" r))
;; 3) глобальная переменная, выставленная загрузчиком
((and *SPIS-DIR* (> (strlen *SPIS-DIR*) 0))
(vl-string-translate "/" "\\" *SPIS-DIR*))
;; 4) загрузчик рядом
((setq f (findfile "SPIS_TOOLS.lsp"))
(vl-string-translate "/" "\\" (vl-filename-directory f)))
;; 5) аварийный вариант
(T "G:\\Мой диск\\lisp-code\\SPIS")
)
)
;; Интерпретатор Python: берём из локального окружения рядом со скриптами.
;; Предпочитаем pythonw.exe — он не создаёт консольного окна.
(defun srs:python (/ tools local)
(setq tools (srs:tools-dir))
(setq local (strcat (vl-string-right-trim "\\/" tools) "\\.venv\\Scripts\\pythonw.exe"))
(if (findfile local)
local
(progn
(setq local (strcat (vl-string-right-trim "\\/" tools) "\\.venv\\Scripts\\python.exe"))
(if (findfile local) local "python")
)
)
)
(defun srs:norm (p)
(vl-string-right-trim "\\" (vl-string-translate "/" "\\" p))
)
(defun srs:split (str sep / pos res)
(setq res nil)
(while (setq pos (vl-string-search sep str))
(setq res (cons (substr str 1 pos) res)
str (substr str (+ pos 1 (strlen sep))))
)
(reverse (cons str res))
)
;; Корпус для имён файлов дисциплин.
;; "АР К9.dwg" -> "К9" (корпус в имени файла)
;; "АР.dwg" в "Ларус" -> "Ларус" (имя файла без корпуса — берём папку)
(defun srs:corpus (root / dir files base parts parent)
(setq dir (srs:norm (strcat (srs:norm root) "\\АР")))
(if (vl-file-directory-p dir)
(setq files (vl-directory-files dir "*.dwg" 1))
)
(if files
(progn
(setq base (vl-filename-base (car files)))
(setq parts (srs:split base " "))
(if (> (length parts) 1)
;; имя из нескольких слов: корпус — последнее слово
(last parts)
;; имя из одного слова: значит корпус в названии папки
(progn
(setq parent (vl-filename-base (srs:norm root)))
(if (or (not parent) (= parent "")) base parent)
)
)
)
nil
)
)
;; Основная команда -------------------------------------------------
(defun c:SPISRUNSETS (/ root corpus tools launcher vpython shell cmd real-res)
(setq root (srs:norm (getstring T "\nКорень проекта (папки АР, ЭТР, СС, ВК, ОВ): ")))
(cond
((not (vl-file-directory-p root))
(prompt (strcat "\nПапка не найдена: " root))
)
((not (setq corpus (srs:corpus root)))
(prompt "\nВ папке АР нет файлов DWG — не определить корпус.")
)
(T
(setq tools (srs:tools-dir))
(setq launcher (strcat tools "/run_sets_launcher.py"))
(cond
((not (findfile launcher))
(prompt (strcat "\nНе найден файл запуска: " launcher))
(prompt "\nОн должен лежать рядом с этим LISP-файлом.")
)
(T
(prompt (strcat "\nКорень: " root))
(prompt (strcat "\nКорпус: " corpus))
(prompt "\nСхема: каждый раздел = АР + смежные дисциплины")
(initget "Yes No")
(cond
((/= (getkword "\nСоздать комплект? [Yes/No] <No>: ") "Yes")
(prompt "\nОтменено. Ничего не изменено.")
)
(T
(setq vpython (srs:python))
;; Диагностика: пути
(prompt (strcat "\n[отладка] python: " vpython))
(prompt (strcat "\n[отладка] скрипт: " launcher))
(prompt (strcat "\n[отладка] root: " root))
(prompt (strcat "\n[отладка] corpus: " corpus))
;; Запуск через WScript.Shell.Run — startapp в AutoCAD 2020
;; не работает (возвращает NIL даже для cmd.exe).
(setq shell (vl-catch-all-apply 'vlax-create-object (list "WScript.Shell")))
(if (vl-catch-all-error-p shell)
(prompt (strcat "\n[отладка] WScript.Shell: ошибка " (vl-catch-all-error-message shell)))
(progn
(prompt "\n[отладка] WScript.Shell: объект создан")
(setq cmd (strcat "\"" vpython "\" \"" launcher "\" \""
root "\" \"" corpus "\""))
(prompt (strcat "\n[отладка] команда: " cmd))
(setq real-res (vl-catch-all-apply 'vlax-invoke
(list shell "Run" cmd 0 0)))
(if (vl-catch-all-error-p real-res)
(prompt (strcat "\n[отладка] ошибка Run: " (vl-catch-all-error-message real-res)))
(prompt (strcat "\n[отладка] Run: OK, код=" (vl-princ-to-string real-res)))
)
(vlax-release-object shell)
)
)
(prompt "\n=== Запущено в фоне ===")
(prompt (strcat "\nХод выполнения: " (getenv "TEMP") "\\spis_sets_log.txt"))
(prompt "\nAutoCAD свободен — сборка идёт отдельно.")
(prompt "\nКогда файлы появятся, выполните SPISATTACHSETS в СПИС.")
)
)
)
)
)
)
(princ)
)
(prompt "\nSPIS_RUN_SETS загружен. Команда: SPISRUNSETS")
(princ)