Я хочу настроить среду, пока конкретный пакет установлен правильно. Как проверить, установлен ли какой-либо пакет в elisp? Что-то вроде этого?:
(if (require 'ecb)
(progn (setq ....))
(message "ECB not installed!"))
Я хочу настроить среду, пока конкретный пакет установлен правильно. Как проверить, установлен ли какой-либо пакет в elisp? Что-то вроде этого?:
(if (require 'ecb)
(progn (setq ....))
(message "ECB not installed!"))
tripleee answer - удобный пример обработки ошибок, но ненужный в этом случае.
(when (require 'some-library nil 'noerror)
do-things)
То, что 'noerror
может быть любым значением, отличным от nil, но, конечно, более описательным. Я часто вижу, что используется :noerror
, но я понятия не имею, есть ли какое-то конкретное преимущество в использовании аргумента ключевого слова над символом (комментарии, кто-нибудь? Мне очень интересно знать).
require - это встроенная функция в
C source code
.(требуется FEATURE и дополнительный FILENAME NOERROR)
Если функция FEATURE не загружена, загрузите ее из FILENAME.
Если FEATURE не является членом спискаfeatures
, то функция не загружается; поэтому загрузите файл FILENAME.
Если FILENAME опущено, имя файла FEATURE используется как имя файла,
иload
будет пытаться загрузить это имя, добавленное суффиксом.elc
или.el
, в этом порядке. Имя без прилагаемого суффикса не будет использоваться.
См.get-load-suffixes
для полного списка суффиксов.
Если дополнительный третий аргумент NOERROR не равен нулю,
затем верните нуль, если файл не найден, а не сигнализирует об ошибке.
Обычно возвращаемое значение - FEATURE.
Нормальные сообщения при запуске и окончании загрузки FILENAME подавляются.
(require)
выдает ошибку, если она терпит неудачу. Это действительно должно быть все, что вам нужно.
Если вы хотите настроить поведение ECB только тогда, когда оно доступно, в первую очередь обратите внимание на добавление материала в ecb-hook
- это обычный способ настройки пакета Emacs условно.
Если никакой крючок недоступен или вы не хотите его вручную качать по какой-то причине, попробуйте что-то вроде
(eval-after-load 'ecb '(setq ecb-be-more-like-better-yes-p t))
Если вы действительно хотите перевернуть это вручную, вы можете заблокировать ошибку из неудавшегося require
следующим образом:
(condition-case nil
(progn
(require 'ecb)
(setq ecb-be-more-like-better-yes-p t) )
(file-error (message "ECB not available; not configuring") ))
Обратите внимание, что condition-case
будет захватывать любые file-error
изнутри progn
, чтобы вы не делали никаких других операций с файлами внутри. В конечном итоге вы можете поместить только require
внутри a condition-case
и использовать это как условие для вашей исходной формы if
, но это уже выходит из-под контроля...
(if (condition-case nil (require 'ecb) (error nil))
(setq ecb-be-more-like-better-yes-p t)
(message "ECB not available; not configuring") )
Почему бы не использовать "featurep"?
(featurep FEATURE &optional SUBFEATURE)
Возвращает t, если FEATURE присутствует в этом Emacs.
(if (featurep 'ecb)
(message "ECB is there!"))
Самый простой ответ - использовать require
и eval-after-load
, как указано в других ответах.
Однако это не всегда удобно, например, в функции, вызываемой крючком режима, который хочет активировать другой второстепенный режим, но только если пакет для него установлен. В этом случае featurep
имеет значение.
Пакеты Emacs все чаще используют автозагрузку для улучшения времени запуска. Если вы проверяете наличие пакета с помощью require
, то вы носите стоимость загрузки файла (ов). Если вы используете пакеты ELPA/MELPA/Marmalade (доступны по умолчанию с версии 24), тогда многие пакеты могут быть доступны в еще не загруженном состоянии, но пакет foo
с автозагрузками предоставит функцию foo-autoloads
. Я написал функцию, которая полезна для проверки того, доступен ли пакет с точки зрения уже загружаемого или настроенного на автозагрузку.
(defun autofeaturep (feature) "For a feature symbol 'foo, return a result equivalent to: (or (featurep 'foo-autoloads) (featurep 'foo)) Does not support subfeatures." (catch 'result (let ((feature-name (symbol-name feature))) (unless (string-match "-autoloads$" feature-name) (let ((feature-autoloads (intern-soft (concat feature-name "-autoloads")))) (when (and feature-autoloads (featurep feature-autoloads)) (throw 'result t)))) (featurep feature))))
Для людей, интересующихся, как проверить, установлен ли пакет package.el, используйте package-installed-p
.
Четыре года поздно по этому вопросу, но... вот простой макрос, который сделает это за вас.
(defmacro when-feature-loaded (feature &rest body)
"Executes BODY if and only if FEATURE is loaded."
(declare (indent defun))
`(when (featurep ,module)
@,body))
Например:
(when-feature-loaded 'foo
(message "foo is loaded!"))
Здесь другая версия с аргументом "else", если вам тоже нужно обработать.
(defmacro if-feature-loaded (module then-form else-form)
"Executes THEN-FORM if and only if MODULE is already loaded, otherwise executes ELSE-FORM."
(declare (indent 2))
`(if (featurep ,module)
,then-form
,else-form))