Очистка и проверка файла при сохранении.

Как-то я сделал для одного хорошего человека лисп, который чистит и проверяет файл на ошибки в момент сохранения. Поскольку прямого запрета на публикацию не было, воспользуюсь этим :)

В общем виде задача стоит так: при сохранении файла необходимо очистить его от мусора (аналог _.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

Аналогичным образом расписываем реакции на отмену команды, на ее завершение, на ее ошибку.

Весь код можно скачать здесь.



Комментарии

Есть 1 комментарий к “Очистка и проверка файла при сохранении.”
  1. Кулик Алексей aka kpblc пишет:

    Учитывая код в http://autolisp.ru/2014/03/24/clear-dwg-at-opening/ , здесь можно нарисовать более интересный вариант :)
    Например, внутри функции _lispru-vlr-command-start-save дать вызов (_kpblc-autostart-purge 511) и голову себе не морочить ;)

Поделитесь своим мнением


Я не робот.