В зашифрованных буферах поместите точку в самый важный файл этого каталога

14

90% времени, когда я захожу в каталог в Emacs, первое, что я делаю, это перемещаю указатель на определенный файл и открываю его. Часто файл, который мне нужно открыть, очень предсказуем. Например:

  • Если .texв этом каталоге есть файлы, я обычно иду прямо к master.tex.
  • В корне проектов Android это обычно AndroidManifest.xml.
  • В каталоге, где я разрабатываю пакет emacs, это почти всегда основной исходный файл пакета. Это обычно, но не всегда, единственный .elфайл в этом каталоге.

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

Это будет очень удобно (так как я могу открыть их, просто нажав RET), но все равно даст гибкость при посещении других файлов.

Malabarba
источник

Ответы:

16

Написать пользовательскую функцию для dired-initial-position-hook. В этой функции вы можете использовать различные функции для поиска файлов и, в конечном итоге, вызывать dired-goto-fileточку перемещения в «лучший» файл:

(defun my-dired-goto-important-file ()
  "Go to an important file in the current dired buffer."
  (unless (bound-and-true-p save-place)
    (let ((candidates '("master.tex" "AndroidManifest.xml"))
          candidate)
      (while (and candidates
                  (not (dired-goto-file (expand-file-name (pop candidates)))))
        nil))))

(add-hook 'dired-initial-position-hook #'my-dired-goto-important-file)

Далее я объясню конкретные аспекты этой функции и выделю потенциальные расширения.

Переход к файлам

dired-goto-fileвозвращает, nilесли файл не существует в текущем буфере Dired, поэтому безопасно вызывать без предварительной проверки. Однако dired-goto-fileтребует абсолютного имени файла (это ошибки по относительным именам), следовательно expand-file-name.

Поиск файлов

Dired не предоставляет простой API для поиска файлов. Как правило, вы можете перебирать все файлы так же, как вы перебираете все строки в буфере:

(let (files)
  (goto-char (point-min))
  (while (not (eobp))
    (let ((filename (dired-get-filename nil 'no-error)))
      (when filename
        (push filename files)))
    (forward-line 1))
  ;; Now `files' is a list of files, which you can search for patterns
  ;; …
  )

Однако удобнее использовать функции маркировки. Просто позаботьтесь о том, чтобы использовать «необычные» маркеры персонажей, чтобы не потерять существующие интерактивные метки:

(unwind-protect
    (when (dired-mark-files-regexp (rx ".tex" string-end) ?t)
      (dired-goto-file (expand-file-name "master.tex")))
  (dired-unmark-all-files ?t))

Режим сохранения места

Вы также должны быть осторожны с режимом сохранения места, если вы его включили. В буферах Dired в режиме сохранения места не запоминается значение точки, как в других режимах, а включается последняя точка имени файла. Он восстанавливает это имя файла так же, как мы делаем: он подключается dired-initial-position-hookи вызывает dired-goto-file(на самом деле, это то, откуда я украл этот код :)).

Если наш хук предшествует сохранению, режим сохранения места безоговорочно перезапишет нашу позицию. Однако, если он предшествует нашей ловушке (как в случае, когда после установки этой ловушки активируется Save Place), наша функция фактически перезаписывает Save Place, что нежелательно. Однако, как и в любом буфере, Save Place устанавливает для локальной переменной save-placeзначение, отличное от nil, поэтому мы можем просто проверить это и только действовать, Save Place не восстанавливает имя файла.

Если вы предпочитаете, чтобы «Место сохранения» было «незакрепленным», снимите флажок save-placeи убедитесь, что наш хук запускается после « Сохранить место», сначала включив режим «Сохранить место» , а затем вызвав значение add-hookс ненулевым значением для его APPENDаргумента.

lunaryorn
источник
Отличный ответ. Вы можете определить bound-and-true-p. :-)
Малабарба
@Malabarba bound-and-true-p- это встроенный макрос из bindings.el.
lunaryorn
Дорогой бог, я не чувствую себя хуже, факт, который я не знал, или факт, который я даже не проверял.
Малабарба
@Malabarba Не берите в голову, мне потребовался год (буквально), чтобы обнаружить существование этой функции.
lunaryorn
Да, это замечательная функция, о которой я до сих пор никогда не слышал!
sanityinc