如何确定是否在elisp中安装了软件包?

时间:2011-10-17 07:03:42

标签: emacs elisp

我想在正确安装特定软件包的同时自定义环境。如何检查elisp中是否安装了某个软件包? 像这样的东西?:

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

6 个答案:

答案 0 :(得分:37)

tripleee的答案是错误处理的一个方便示例,但在此实例中是不必要的。

(when (require 'some-library nil 'noerror)
  do-things)

'noerror可以是任何非零值,但当然这种方式更具描述性。我经常看到使用:noerror,但我不知道在符号上使用关键字参数是否有任何特殊优势(评论,任何人?我很有兴趣知道)。

  

require是C source code中的内置函数。

     

(需要FEATURE和可选的FILENAME NOERROR)

     

如果未加载功能FEATURE,请从FILENAME加载   如果FEATURE不是列表features的成员,则为特征
  没装;所以加载文件FILENAME   如果省略FILENAME,则FEATURE的打印名称将用作文件名,
  并且load会尝试加载此名称,并附加后缀.elc
  .el,按此顺序排列。不使用没有附加后缀的名称   有关后缀的完整列表,请参阅get-load-suffixes   如果可选的第三个参数NOERROR是非零的,则   如果找不到文件,则返回nil,而不是发出错误信号   通常返回值为FEATURE   加载FILENAME的开始和结束时的正常消息被抑制。

答案 1 :(得分:8)

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

答案 2 :(得分:6)

为什么不使用“featurep”?

(featurep FEATURE &optional SUBFEATURE)

如果此Emacs中存在FEATURE,则返回t。

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

答案 3 :(得分:3)

对于想知道如何安装 package.el 软件包的人,请使用package-installed-p

答案 4 :(得分:1)

最简单的答案是使用其他答案中所述的requireeval-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 :(得分:0)

这个问题已经晚了四年,但是......这是一个简单的宏,可以为你做到这一点。

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