Я действительно не знаю, что вы пытаетесь сделать с этим, но вот несколько заметок.
Ваш метод в порядке. В моей книге хорош любой способ взломать собственное решение проблемы.
@ Том прав, что вам не нужно этого делать, потому что проблема уже решена для вас системой помощи. т.е. C-h f
Но это не так интересно. Допустим, вы действительно хотите автоматическое, более элегантное решение. Вы хотите функцию - locate-feature
с этой подписью:
(defun locate-feature (feature)
"Return file-name as string where `feature' was provided"
...)
Метод 1 load-history
подход
Я просто опишу шаги, которые я предпринял, чтобы решить эту проблему:
У вас уже есть самая важная часть - найдите переменную с необходимой вам информацией.
Я сразу замечаю, что в этой переменной много данных. Если я вставлю его в буфер одной строкой, Emacs будет недоволен, потому что он плохо работает с длинными строками. Я знаю, что пакет prett-print сможет красиво отформатировать эти данные. Поэтому я открываю свой *scratch*
буфер и запускаю
M-: (вставить (история загрузки pp-в-строку))
Теперь я вижу структуру данных, с которой я имею дело. Вроде бы (в псевдокоде):
((file-name
((defun|t|provide . symbol)|symbol)*)
...)
Теперь я просто пишу функцию
(eval-when-compile (require 'cl))
(defun locate-feature (feature)
"Return file name as string where `feature' was provided"
(interactive "Sfeature: ")
(dolist (file-info load-history)
(mapc (lambda (element)
(when (and (consp element)
(eq (car element) 'provide)
(eq (cdr element) feature))
(when (called-interactively-p 'any)
(message "%s defined in %s" feature (car file-info)))
(return (car file-info))))
(cdr file-info))))
Код здесь довольно прост. Спросите Emacs о функциях, которые вы не понимаете.
Способ 2, помощь, подход
Метод первый работает для функций. Но что, если я хочу знать, где-нибудь
Доступная функция определена? Не только особенности.
C-h f уже говорит мне об этом, но я хочу, чтобы имя файла в строке, а не весь подробный текст справки. Я хочу это:
(defun locate-function (func)
"Return file-name as string where `func' was defined or will be autoloaded"
...)
Вот и мы.
C-h f - моя отправная точка, но я действительно хочу прочитать код, который определяет describe-function
. Я делаю это:
C-h k C-h f C-x o вкладка введите
Теперь я нахожусь в help-fns.el
по определению describe-function
. Я хочу работать только с этим определением функции. Итак, сужение по порядку:
C-x n d
У меня есть догадка, что интересная команда будет иметь в своем названии "find" или "locate", поэтому я использую occur
для поиска интересных строк:
M-s o найти \ | найти
Нет совпадений. Хммм. Не много строк в этом defun. describe-function-1
, кажется, делает настоящую работу, поэтому мы попробуем это.
Я могу посетить определение describe-function-1
через C-h f . Но у меня уже есть файл открыт. imenu
доступно сейчас:
C-x n w M-x имя desc * 1 вкладка введите
Сузить и искать снова:
C-x n d M-s o up enter
Я вижу find-lisp-object-file-name
, что выглядит многообещающе.
После прочтения C-hf find-lisp-object-file-name Я придумываю:
(defun locate-function (func)
"Return file-name as string where `func' was defined or will be autoloaded"
(interactive "Ccommand: ")
(let ((res (find-lisp-object-file-name func (symbol-function func))))
(when (called-interactively-p 'any)
(message "%s defined in %s" func res))
res))
А теперь иди повеселись, изучая Emacs.