Подтвердить что ты не робот

В emacs, как мне сохранить, не запустив save hooks?

У меня есть разные вещи, установленные в моем 'before-save-hook. Например, я запускаю 'delete-trailing-whitespace. Это то, что я хочу почти во всех случаях.

Но иногда я работаю над файлами, которые совместно используются другими людьми, и в файле уже есть куча конечных пробелов. Если я сохраню файл, я получу большой разброс, который будет довольно запутанным, так как мои изменения будут похоронены в десятках или сотнях бессмысленных изменений. Да, каждый может просто сказать своему инструменту diff, чтобы не показывать изменения пробелов, но это то, что каждый должен делать каждый раз, когда они смотрят на diff. Я бы предпочел даже не менять пробелы.

Есть ли что-нибудь, что я могу сделать, чтобы сохранить файл без изменения пробелов, не запустив новый экземпляр Emacs без файла init.el или с измененным init.el, у которого нет крюка?

4b9b3361

Ответ 1

Основываясь на обсуждении комментария с @Stefan, вот два возможных (непроверенных) решения:

Используйте let:

(defun save-buffer-without-dtw ()
  (interactive)
  (let ((b (current-buffer)))   ; memorize the buffer
    (with-temp-buffer ; new temp buffer to bind the global value of before-save-hook
      (let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook))) 
        (with-current-buffer b  ; go back to the current buffer, before-save-hook is now buffer-local
          (let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
            (save-buffer)))))))

Используйте unwind-protect:

(defun save-buffer-without-dtw ()
  (interactive)
  (let ((restore-global
         (memq 'delete-trailing-whitespace (default-value before-save-hook)))
        (restore-local
         (and (local-variable-p 'before-save-hook)
              (memq 'delete-trailing-whitespace before-save-hook))))
    (unwind-protect
         (progn
           (when restore-global
             (remove-hook 'before-save-hook 'delete-trailing-whitespace))
           (when restore-local
             (remove-hook 'before-save-hook 'delete-trailing-whitespace t))
           (save-buffer))
      (when restore-global
        (add-hook 'before-save-hook 'delete-trailing-whitespace))
      (when restore-local
        (add-hook 'before-save-hook 'delete-trailing-whitespace nil t)))))

Проблема со вторым решением заключается в том, что порядок функций в before-save-hook может измениться.

Ответ 2

Более простое решение, с которым я столкнулся, заключается в том, что у моего fundamental-mode нет установленных крючков, потому что я хочу, чтобы он был как можно более простым. Таким образом, если я хочу сохранить файл без запуска перехватчиков, я временно переключаюсь на fundamental-mode.

Ответ 3

Здесь другое решение:

(defvar my-inhibit-dtw nil)
(defun my-delete-trailing-whitespace ()
  (unless my-inhibit-dtw (delete-trailing-whitespace)))
(add-hook 'before-save-hook 'my-delete-trailing-whitespace)

а потом

(defun my-inhibit-dtw ()
  (interactive)
  (set (make-local-variable 'my-inhibit-dtw) t))

так что вы можете Mx my-inhibit-dtw RET в буферах, где вы не хотите обрезать пробелы.

Ответ 4

Нам нужно удалить 'delete-trailing-whitespace из before-save-hook, сохранить буфер, а затем добавить его обратно.

Этот код сделает это, но удалит его и добавит, если он там начнется.

;; save the buffer, removing and readding the 'delete-trailing-whitespace function
;; to 'before-save-hook if it there
(defun save-buffer-no-delete-trailing-whitespace ()
  (interactive)
  (let ((normally-should-delete-trailing-whitespace (memq 'delete-trailing-whitespace before-save-hook)))
    (when normally-should-delete-trailing-whitespace
      (remove-hook 'before-save-hook 'delete-trailing-whitespace))
    (save-buffer)
    (when normally-should-delete-trailing-whitespace
      (add-hook 'before-save-hook 'delete-trailing-whitespace))))
(global-set-key (kbd "C-c C-s") 'save-buffer-no-delete-trailing-whitespace)

Он также привязывает команду к (kbd C-c C-s) для удобства.