Файл .emacs.desktop уничтожен пользовательской функцией

Я использую модуль рабочего стола Emacs для сохранения открытых буферов между сеансами. Однако я обнаружил, что при этом накапливается больше буферов, чем мне нужно, поэтому я написал небольшую функцию для очистки списка буферов непосредственно перед сохранением в файл на рабочем столе. Это работает, как и ожидалось, но по странным причинам .emacs.desktop иногда скремблируется, т. е. в начале он содержит часть другого буфера, затем предполагаемое содержимое, а затем результат другого буфера. Я не имею ни малейшего представления, почему это происходит. Вот выдержка из моего файла .emacs:

(defun kill-old-buffers ()
  "Kill buffers from end of buffer list (not used recently) until no more than 50 buffers are left. Remove temporary buffers first"
  (interactive)
  (let* (desktop-buffer (current-buffer))
   (dolist (buffer (buffer-list))
     (if (or (string-match "^\*" (buffer-name buffer)) (string-match "\.hpp$" (buffer-name buffer)))
         (kill-buffer buffer)
       )
     )

  (setq all-buffers (reverse (buffer-list)))
  (while (> (safe-length all-buffers) 50)
    (setq buffer (pop all-buffers))
    (if (not (string-equal (buffer-name buffer) (buffer-name (current-buffer))))
        (kill-buffer buffer)
      )
    )
  (switch-to-buffer desktop-buffer)
))

;; Kill old rarely-used buffers before saving
(add-hook 'desktop-save-hook
  '(lambda () (kill-old-buffers)))

Любая помощь будет оценена по достоинству.


person Martin    schedule 21.02.2011    source источник


Ответы (2)


Я не уверен, что ваша функция действительно является причиной вашей проблемы. Если это так, то причиной может быть неправильное использование let*, на которое указал Скоттфразер. Но вам вообще не нужны эти let*switch-to-buffer), потому что

  1. то, что вы пытаетесь сделать, лучше сделать с помощью Emacs, встроенного в save-excursion, и
  2. на самом деле вы никогда не переключаете буфер.

OTOH, вы должны были использовать let вместо setqs в нижней половине вашей функции, потому что setq в противном случае изменит переменную из охватывающей лексической области. В этом случае вы вполне могли перешагнуть через переменную buffer из функции, которая выполняет desktop-save-hook, что является еще одной потенциальной причиной вашей проблемы.

Но вам также не нужны эти let, потому что вы можете сделать второй цикл с другим dolist. Вы можете избавиться от тех первых 50 буферов, которые вы не хотите зацикливать, с помощью nthcdr.

Вот моя улучшенная версия kill-old-buffers:

(defun kill-old-buffers ()
  "Kill buffers from end of buffer list (not used recently) until
no more than 50 buffers are left. Remove temporary buffers first."
  (interactive)
  (save-excursion
    (dolist (buffer (buffer-list))
      (if (or (string-match "^\*" (buffer-name buffer))
              (string-match "\.hpp$" (buffer-name buffer)))
          (kill-buffer buffer)))

    (dolist (buffer (reverse (nthcdr 50 (buffer-list))))
      (unless (eq buffer (current-buffer))
        (kill-buffer buffer)))))
person Rörd    schedule 21.02.2011
comment
Большое спасибо. Lisp не является моим основным языком программирования, как вы уже могли догадаться ;-) Я заменил свою версию на вашу, но только время покажет, закончатся ли на этом мои случайные проблемы. Я сообщу, если это повторится через неделю или две. - person Martin; 23.02.2011
comment
Просто короткое обновление после трех недель работы с вашим решением: кажется, теперь оно работает без проблем, хотя я до сих пор не понимаю, что вызвало первоначальные проблемы. Большое спасибо еще раз. - person Martin; 17.03.2011

Это может не решить все ваши проблемы, но для начала вам нужен еще один набор скобок вокруг переменной в вашем операторе let*.

(let* ((desktop-buffer (current-buffer)))
person scottfrazer    schedule 21.02.2011