Функция для отображения полного пути к текущему файлу в мини-буфере

98

Мне нужно получить полный путь к файлу, который я редактирую с помощью emacs.

  • Есть ли для этого функция?
  • Если нет, то какой была бы функция elisp для этого?
  • Как я могу скопировать результат (путь) в буфер обмена, чтобы использовать его повторно?

Я использую Mac OS X и Aqumacs.

(setq filepath (get-fullpath-current-file)) ???
(copy-to-clipboard 'filepath) ???

ДОБАВЛЕНО

(defun показать-имя-файла ()
  «Показать полный путь к файлу в минибуфере».
  (интерактивный)
  (сообщение (имя-файла-буфера))
  (kill-new (имя-файла-файла-буфера))
)
(глобальный-набор-ключ "\ C-cz" 'имя-шоу-файла)

Объединив два полученных ответа, я смог получить то, что хочу. Спасибо за ответы. И еще несколько вопросов.

  • Что для (имя-файла)?
  • Могу ли я скопировать имя пути в буфер обмена системы (ОС), а не список уничтожений, чтобы я мог использовать информацию с другими приложениями?
просек
источник

Ответы:

92

Это встроенная функция, buffer-file-nameкоторая дает вам полный путь к вашему файлу.

Лучше всего, чтобы в окне emacs всегда отображалось имя вашей системы и полный путь к буферу, который вы редактируете в данный момент:

(setq frame-title-format
      (list (format "%s %%S: %%j " (system-name))
        '(buffer-file-name "%f" (dired-directory dired-directory "%b"))))

Вы также можете сделать что-то вроде этого:

(defun show-file-name ()
  "Show the full path file name in the minibuffer."
  (interactive)
  (message (buffer-file-name)))

(global-set-key [C-f1] 'show-file-name) ; Or any other key you want
Жером Радикс
источник
8
В emacs 24 buffer-file-nameесть переменная
barracel
6
... но еще и функция
филс
17
Если это функция, то почему она не появляется M-x?
asmeurer
9
asmeurer - потому что это не интерактивно
Бен Фицджеральд
2
@Talespin_Kit Да, конечно. Elisp - это «lisp-2» в отличие от «lisp-1», что означает, что существует два независимых пространства имен (переменные и функции). Таким образом, каждый символ имеет «функциональный слот» и «слот значения», и доступ к слоту зависит от контекста. На практике существует множество примеров (например, любое второстепенное имя режима будет одновременно функцией и переменной). Вот почему вам также нужно использовать подобные функции funcallдля вызова функции, которая хранится как значение переменной foo, потому что, если бы вы использовали, (foo)вы бы использовали слот функции, fooа не слот значения.
phils
74

Чтобы позаимствовать из ответа Жерома Радикса, если вы просто хотите быстро увидеть путь к файлу текущего буфера, вы можете это сделать M-: buffer-file-name.

Либо введите (buffer-file-name)где-нибудь буфер и запустите C-x C-eзакрывающую скобку (это будет работать в любом режиме, а не только в режиме lisp).

Asmeurer
источник
3
Спасибо, я думал, что buffer-file-nameэто функция, но она не отображается M-x, а отображается M-:как emacs eval, там я могу запустить команду благодаря вашему ответу :)
PeterZD
6
Да, M-xвыполняет только интерактивные функции, тогда как M-:выполняет любую функцию elisp.
asmeurer
41

Мой трюк - сделать что-то C-x C-fвроде открытия файла, он предварительно заполнит минибуф текущим путем C-gк файлу, чтобы выйти. Быстрее, чем M-: buffer-file-nameлюбые другие методы, но намного уродливее.

Жюльен Палар
источник
Я тоже так делаю. Это не такой хардкорный emacs-y, но если все, что меня волнует, это путь к текущему файлу, он работает.
andrunix
Если вы открываете файл, скажем, A, а затем переходите к другому файлу, скажем, B, например, используя некоторые функции перехода к определению плагина, этот метод показывает путь к A, а не к B! Таким образом, этот ответ не всегда предлагает то, о чем просит OP.
Абхишек Ананд
4
Cx Cv покажет вам не только текущий путь, но и имя текущего файла
kuzzooroo
@kuzzooroo, который подходит для пользователей не в режиме ido (имя отображается в Cx Cf, если вы используете режим ido).
Julien Palard
16

Прямая реализация того, что вы хотите:

(defun copy-full-path-to-kill-ring ()
  "copy buffer's full path to kill ring"
  (interactive)
  (when buffer-file-name
    (kill-new (file-truename buffer-file-name))))

Тем не менее, я считаю невероятно полезным иметь возможность получить полный путь к тому, что находится в минибуфере, и вот что я использую:

(define-key minibuffer-local-completion-map "\C-r" 'resolve-sym-link)
(defun resolve-sym-link ()
  "Try to resolve symbolic links into true paths."
  (interactive)
  (beginning-of-line)
  (let* ((file (buffer-substring (point)
                                 (save-excursion (end-of-line) (point))))
         (file-dir (file-name-directory file))
         (file-true-dir (file-truename file-dir))
         (file-name (file-name-nondirectory file)))
    (delete-region (point) (save-excursion (end-of-line) (point)))
    (insert (concat file-true-dir file-name))))

А затем, если я хочу, чтобы это было в буфере обмена, я просто убиваю строку ( C-a C-k). Но мы могли бы легко скопировать истинное имя в буфер обмена в приведенной выше команде, просто изменив последнюю строку на:

(insert (kill-new (concat file-true-dir file-name)))))

Новая часть - это вызов, 'kill-newкоторый помещает строку в список уничтожения.

Трей Джексон
источник
Не могли бы вы рассказать, как использовать эти настройки? А что означает "\ Cr"?
модельер
Неважно. Я понял. Я думаю, что это полезно, когда я нахожусь в режиме ido и указываю на файл, тогда я просто нажимаю Cr, чтобы получить полный путь к этому файлу. Действительно полезно. Однако я до сих пор не знаю, зачем использовать \ C вместо C.
моделист
11

Нет необходимости в дополнительных функциях, просто

M-! pwd
спасибо
источник
Хотя это может работать, оно не будет работать в системах Windows и не учитывает тот факт, что текущий рабочий каталог emacs может отличаться от каталога файла текущего буфера. Вы можете убедиться в этом сами, посетив файл C-x C-f, запустив M-! pwd, затем M-x cdвыбрав другой каталог, а затем M-! pwdснова запустив .
josaphatv
3

У меня уже давно используется следующий код. Он копирует полный путь к файлу в список уничтожений, когда я нажимаю среднюю кнопку мыши на имени буфера в строке режима. Он копирует только имя буфера в список уничтожений, когда я нажимаю shift-mouse-2 на имени буфера в строке режима.

(defun copy-buffer-file-name (event &optional bufName)
  "Copy buffer file name to kill ring.
If no file is associated with buffer just get buffer name.
"
  (interactive "eP")
  (save-selected-window
    (message "bufName: %S" bufName)
    (select-window (posn-window (event-start event)))
    (let ((name (or (unless bufName (buffer-file-name)) (buffer-name))))
      (message "Saved file name \"%s\" in killring." name)
      (kill-new name)
      name)))

(define-key mode-line-buffer-identification-keymap [mode-line mouse-2] 'copy-buffer-file-name)
(define-key mode-line-buffer-identification-keymap [mode-line S-mouse-2] '(lambda (e) (interactive "e") (copy-buffer-file-name e 't)))
Тобиас
источник
3

C-x C-d, также вызываемый через M-x list-directory, покажет вам каталог для вашего текущего файла, и вам нужно только нажать клавишу «Enter», чтобы очистить минибуфер. Дополнительная информация доступна здесь .

MLev
источник
мой любимый ответ, простой, быстрый и легкий!
ticktock
2

C-x C-b показывает список буферов и путь к файлу для каждого буфера, где это применимо.

Дэвид
источник
2

C-u C-x C-b перечисляет буферы, посещающие в данный момент файлы.

мемплекс
источник
1

Могу ли я скопировать имя пути в буфер обмена системы (ОС), а не список уничтожений, чтобы я мог использовать информацию с другими приложениями?

Вы можете использовать что-то вроде xclip (Linux), pbcopy (Mac), putclip (Cygwin).

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

(shell-command (format "echo '%s' | c" buffer-file-name))

Я считаю это более надежным и настраиваемым, чем использование поддержки буфера обмена Emacs. Например, моя cкоманда копирует ввод во все 3 буфера обмена в Linux (основной, дополнительный, буфер обмена), поэтому я могу вставить его с помощью Ctrl-V или среднего щелчка.

Барри Келли
источник
Это должно работать, но не для меня. (Ubuntu 14.04.1.) А именно, date | xclipи xclip fileоба работают, как заявлено (сохраняя дату или содержимое файла в качестве основного), если они введены в оболочке. Но если я наберу любую из этих команд после M-! в emacs (и нажмите return) ничего не происходит; курсор остается в минибуфере, как будто ожидая ввода дополнительных данных; и если я прервусь, чтобы восстановить контроль, в первичном хранилище ничего не сохранится.
Сильвио Леви
Хорошо, ваша идея отлично работает с xsel вместо xclip: (shell-command (format "echo '%s' | xsel -i" buffer-file-name))- и когда она превращена в интерактивную команду (как предложено в ответе @JeromeRadix, получившем наибольшее количество голосов выше), это БОЛЬШАЯ ВЫИГРЫША! Спасибо!
Сильвио Леви
0

Самый простой способ и был бы

(buffer-name)<(C-x)(C-e)> for the file name to appear in the echo area

(buffer-name)<(C-u)(C-x)(C-e)> would print the location <here>

Заимствуя у Трея Джексона, я придумал следующее:

(defun buffer-kill-path ()
  "copy buffer's full path to kill ring"
  (interactive)
  (kill-new (buffer-file-name)))

Вы можете найти больше информации на сайте

DJJ
источник