#emacs #elisp #dired
#emacs #elisp #dired
Вопрос:
У меня есть пользовательская функция, которая получает имена файлов с пометкой dired (т. Е. Имена каждого отмеченного файла), если отмечено более одного, или если только один, он получает имя файла в точке. Проблема возникает всякий раз, когда курсор находится на ничейной территории, потому dired-mark
что (или я, потому что я пилот) переусердствовал с повторением и перемещает курсор на пустую строку в конце буфера, где нет файла. В этой ситуации ошибка заключается в следующем:
Debugger entered--Lisp error: (error "No file on this line")
signal(error ("No file on this line"))
error("No file on this line")
dired-get-file-for-visit()
(file-directory-p (dired-get-file-for-visit))
(if (file-directory-p (dired-get-file-for-visit)) nil (let ((lawlist-filename (if (or (re-search-backward "^*" nil t) (re-search-forward "^*" nil t)) (dired-get-marked-files) (dired-get-file-for-visit)))) (wl-draft-mailto) (attach-multiple-files lawlist-filename)))
(lambda nil (interactive) (if (file-directory-p (dired-get-file-for-visit)) nil (let ((lawlist-filename (if (or (re-search-backward "^*" nil t) (re-search-forward "^*" nil t)) (dired-get-marked-files) (dired-get-file-for-visit)))) (wl-draft-mailto) (attach-multiple-files lawlist-filename))))()
funcall-interactively((lambda nil (interactive) (if (file-directory-p (dired-get-file-for-visit)) nil (let ((lawlist-filename (if (or (re-search-backward "^*" nil t) (re-search-forward "^*" nil t)) (dired-get-marked-files) (dired-get-file-for-visit)))) (wl-draft-mailto) (attach-multiple-files lawlist-filename)))))
call-interactively((lambda nil (interactive) (if (file-directory-p (dired-get-file-for-visit)) nil (let ((lawlist-filename (if (or (re-search-backward "^*" nil t) (re-search-forward "^*" nil t)) (dired-get-marked-files) (dired-get-file-for-visit)))) (wl-draft-mailto) (attach-multiple-files lawlist-filename)))) nil nil)
command-execute((lambda nil (interactive) (if (file-directory-p (dired-get-file-for-visit)) nil (let ((lawlist-filename (if (or (re-search-backward "^*" nil t) (re-search-forward "^*" nil t)) (dired-get-marked-files) (dired-get-file-for-visit)))) (wl-draft-mailto) (attach-multiple-files lawlist-filename)))))
Мне нравится возможность удерживать dired-mark
клавишу нажатой для повторения, но я бы хотел, чтобы она останавливалась на последней строке с файлом в буфере dired-mode. Любые идеи о том, как достичь этой цели, были бы высоко оценены. Перемещение мимо этой точки, выполнение теста, а затем возврат к предыдущей точке, по-видимому, не является очень эффективным средством обработки этого. Возможно, было бы лучше завершить буфер dired в конце последней строки файлом, чтобы не было пустой строки — т. Е., если в конце буфера режима dired нет пустой строки, то dired-mark
туда нельзя перейти (так что это было бы хорошо?).
РЕДАКТИРОВАТЬ: сообщение отладчика было обновлено с полным обратным отслеживанием. Ниже приведена пользовательская функция, которая может быть, как предполагает @Drew, основной причиной сообщения об ошибке, которое я получаю:
;; E-mail attachments using Wanderlust.
(define-key dired-mode-map (kbd "C-c e") (lambda () (interactive)
;; if hovering over a directory, then do nothing
(unless (file-directory-p (dired-get-file-for-visit))
(let ((lawlist-filename
(if (or (re-search-backward "^*" nil t)
(re-search-forward "^*" nil t))
(dired-get-marked-files)
(dired-get-file-for-visit))))
(wl-draft-mailto)
(attach-multiple-files lawlist-filename)))))
(defun attach-multiple-files (amp;optional lawlist-filename)
"Either (dired-get-marked-files) or (dired-get-file-for-visit) when exiting recursive edit."
(interactive)
(let* (
new-dir
(beg (point))
(dir "/Users/HOME/.0.data"))
(goto-char (point-min))
(when (and (re-search-forward "username@hostname.com" nil t) (not (re-search-forward "username@hostname.comn" nil t)))
(goto-char (point-max))
(newline 2))
(catch 'done
(while t
(goto-char (point-max))
(let* (
(multi-attach-variable t)
(next-file
(if lawlist-filename
lawlist-filename
(dired-read-file-name
(if new-dir
new-dir
dir)))) )
(setq new-dir
(cond
((and next-file (stringp next-file))
(file-name-directory next-file))
((and next-file (listp next-file))
(file-name-directory (car next-file)))))
(cond
((stringp next-file)
(mime-edit-insert-file next-file t))
((listp next-file)
(mapcar (lambda (x) (mime-edit-insert-file x t)) next-file)))
(setq lawlist-filename nil)
(if (not (lawlist-y-or-n-p "Attach another? "))
(progn
(goto-char beg)
(throw 'done nil))))))))
Комментарии:
1. 1. Откуда у вас это сообщение об ошибке? Я не вижу этого с
emacs -Q
или где-либо вdired-mark
.dired-repeat-over-lines
возвращает nil при перемещении в eob. Сообщение о том, что в строке без файла есть определенные действия. Чтобы избежать этого, проверьте, находится ли точка в строке с файлом. 2. Почему вы хотите остановиться перед eob — это просто для того, чтобы избежать сообщения об ошибке? (3. Не имеет прямого отношения, но может представлять интерес: с помощью клавиш DiredC-n
,C-p
,down
иup
оберните от конца / начала до начала / конца. Вы могли бы сделать аналогично дляm
, если хотите.)2. @Drew — спасибо — я обновил вопрос с помощью пользовательской функции, которая может (как вы предположили) отвечать за ошибку (а не
dired-mark
).). Нет особой причины останавливаться перед eob, за исключением того, чтобы избежать сообщения об ошибке. Время от времени мне нравится заглядывать в Dired в поисках отличных идей — я позаимствовал вашу необычную подсветку буфера dired-mode — это отличная библиотека.3. @Drew — Спасибо, что помогли мне разобраться в проблеме. Пользовательская функция, которую я использовал, была одной из моих ранних попыток получить имена файлов в режиме dired. В других моих пользовательских библиотеках я уже переключился на метод, используемый
dired-do-create-files
. Итак, моя пользовательская функция, о которой идет речь в этом потоке, должна включать тот же метод. Я опубликовал ответ, который решит проблему. Как всегда, мы высоко ценим вашу помощь! Без вашей помощи я, вероятно, закончил бы тем, что попытался переписать что-то в режиме dired без необходимости.
Ответ №1:
Попробуйте defadvice
включить dired-mark
, чтобы избежать попадания на нейтральную полосу:
(defadvice dired-mark (after stop-at-last-file activate)
(when (eobp)
(previous-line 1)))
Функция «двигаться вперед после пометки» встроена в dired-mark
(на самом деле, если вы хотите разобраться в этом, в dired-repeat-over-lines
), поэтому этот совет проверяет, поместил ли он вас в эту пустую строку, и перемещает вас назад, если да. Ваш последний абзац предполагает, что вы, возможно, не очень заинтересованы в этой опции, но мне кажется, что это менее хлопотно, чем изменение внутренних элементов dired.
Комментарии:
1. Спасибо за идею — я подумаю об этом еще немного в контексте моей пользовательской функции и сообщу об этом.
Ответ №2:
Предыдущий ответ (17 октября 2014): Следующие 3 строки кода остановят функцию, если курсор не находится в файле или каталоге, и если ничего не было отмечено:
(when (null (dired-get-marked-files))
(let ((debug-on-quit nil))
(signal 'quit `("You are not on a line containing a valid file or directory."))))
Пересмотренный ответ (20 января 2015 г.): Функция dired-insert-directory
может быть изменена для удаления завершающих новых строк и / или пробелов в конце буфера следующим образом:
(goto-char (point-max))
(let ((trailing-whitespace newlines (abs (skip-chars-backward "srnt"))))
(when (> trailing-whitespace newlines 0)
(delete-char trailing-whitespace newlines)))