Очистка и проверка файла при сохранении.
Как-то я сделал для одного хорошего человека лисп, который чистит и проверяет файл на ошибки в момент сохранения. Поскольку прямого запрета на публикацию не было, воспользуюсь этим
В общем виде задача стоит так: при сохранении файла необходимо очистить его от мусора (аналог _.purge) и проверить на ошибки (аналог _.audit).
Понятно, что переопределить команду проще всего. Но этого недостаточно: во-первых, надо переопределять и английскую, и русскую версии команды, что уже вносит сумятицу. Во-вторых, достаточно пользователю ввести вместо _save команду с точкой: _.save , и переопределение накрывается медным тазом.
Значит, от переопределения отказываемся. Остаются реакторы.
Но какие? Общение в ветке http://adn-cis.org/forum/index.php?topic=109.0 дало определенное количество информации: можно использовать командные реакторы, а можно - реакторы базы чертежа.
Поскольку проверка и очистка файла достаточно длительные процессы, я решил использовать только командные реакторы - и проще с ними, и опыта побольше, и информацию по ним найти не проблема.
Сначала сделаем некоторые глобальные вещи:
1 2 3 | (vl-load-com) (setq *lispru-adoc* (vla-get-activedocument (vlax-get-acad-object))) |
В результате гарантированно загружено ActiveX-расширение и определена глобальная переменная - указатель на текущий документ.
Теперь определим собственные реакции AutoCAD'a на команды:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | (if *vlr-cmd* (progn (setq *vlr-cmd* nil) (vlr-remove-all :vlr-command-reactor) ) ;_ end of progn ) ;_ end of if (if (not *vlr-cmd*) (setq *vlr-cmd* (vlr-command-reactor "lena-command-reactor" '( (:vlr-commandwillstart . _lispru-vlr-command-start) (:vlr-commandended . _lispru-vlr-command-end) (:vlr-commandcancelled . _lispru-vlr-command-cancel) (:vlr-commandfailed . _lispru-vlr-command-fail) ) ) ;_ end of VLR-Command-Reactor ) ;_ end of setq ) ;_ end of if |
Что происходит здесь: проверяется наличие глобальной переменной *vlr-cmd*. Если она не пуста, то, выходит, обработчик реакторов уже был загружен. Мораль: удалить реактор (откровенно говоря, тут я поступил внагляк: просто удаляю все командные реакторы, не разбираясь - кто прав кто виноват).
После этого уже определяем сам реактор - на начало команды, на окончание команды, на отмену команды и на случай, если выполнение команды вызвало ошибку.
Осталась сущая мелочь: написать собственно реакторы.
1 2 3 4 5 6 7 8 9 10 11 | (defun _lispru-vlr-command-start (react cmd) (setq cmd (strcase (car cmd) t)) (cond ((member cmd '("qsave" "save" "saveas")) (_lispru-vlr-command-start-save) ) ((= cmd "audit") (setq *lispru-audit-sysvar* (_lispru-error-sysvar-save-by-list '(("dimpost" . "")))) ) ) ;_ end of cond ) ;_ end of defun |
Эта функция обрабатывает событие начала команды. cmd - собственно имя вызываемой команды. Что самое интересное, оно показывается в "оригинальном" варианте, напрочь игнорируя локализацию AutoCAD'a. Если команда "save", "qsave", "saveas" - то срабатывает функция _lispru-vlr-command-start-save; если команда "audit" - то (мы ж не знаем, в каких версиях будет работать лисп!) приходится учитывать варианты обработки системной переменной dimpost (код функции _lispru-error-sysvar-save-by-list доступен по ссылке).
Так, а что должно быть сделано при сохранении файла? Правильно, проверка и очистка!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | (defun _lispru-vlr-command-start-save (/ hive lst) (vlax-for gr (vla-get-groups *lispru-adoc*) (if (= (vla-get-count gr) 0) (vl-catch-all-apply (function (lambda () (vla-delete gr) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of if ) ;_ end of vlax-for (repeat 3 (vla-purgeall *lispru-adoc*)) (vlax-for item (vla-get-registeredapplications *lispru-adoc*) (vl-catch-all-apply (function (lambda () (vla-delete item) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply ) ;_ end of vlax-for (_lispru-dwg-audit) ) ;_ end of defun |
Тут в принципе все понятно: сначала пробуем удалить описания пустых групп, потом очистка графического мусора, потом - зарегистрированные приложения. И под конец - проверка файла:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | (defun _lispru-dwg-audit (/ sysvars) (setq sysvars (_lispru-error-sysvar-save-by-list '(("cmdecho" . 0) ("nomutt" . 1) ("menuecho" . 0) ("dimpost" . "")) ) ;_ end of _lispru-error-sysvar-save-by-list ) ;_ end of setq (vl-catch-all-apply (function (lambda () (vla-auditinfo *lispru-adoc* :vlax-true) ) ;_ end of lambda ) ;_ end of function ) ;_ end of vl-catch-all-apply (_lispru-error-sysvar-restore-by-list sysvars) ) ;_ end of defun |
Аналогичным образом расписываем реакции на отмену команды, на ее завершение, на ее ошибку.
Весь код можно скачать здесь.
Учитывая код в http://autolisp.ru/2014/03/24/clear-dwg-at-opening/ , здесь можно нарисовать более интересный вариант
Например, внутри функции _lispru-vlr-command-start-save дать вызов (_kpblc-autostart-purge 511) и голову себе не морочить