Подтвердить что ты не робот

Как определить, установлен ли пакет в elisp?

Я хочу настроить среду, пока конкретный пакет установлен правильно. Как проверить, установлен ли какой-либо пакет в elisp? Что-то вроде этого?:

(if (require 'ecb)
    (progn (setq ....))
  (message "ECB not installed!"))
4b9b3361

Ответ 1

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 подавляются.

Ответ 2

(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") )

Ответ 3

Почему бы не использовать "featurep"?

(featurep FEATURE &optional SUBFEATURE)

Возвращает t, если FEATURE присутствует в этом Emacs.

(if (featurep 'ecb)
   (message "ECB is there!"))

Ответ 4

Самый простой ответ - использовать 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))))

Ответ 5

Для людей, интересующихся, как проверить, установлен ли пакет package.el, используйте package-installed-p.

Ответ 6

Четыре года поздно по этому вопросу, но... вот простой макрос, который сделает это за вас.

(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))