【问题标题】:How to determine whether a package is installed in elisp?如何判断一个包是否安装在elisp中?
【发布时间】:2011-10-17 07:03:42
【问题描述】:

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

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

【问题讨论】:

    标签: emacs elisp


    【解决方案1】:

    tripleee 的回答是错误处理的一个方便示例,但在这种情况下是不必要的。

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

    'noerror 可以是任何非零值,但当然,这种方式更具描述性。我也经常看到:noerror 也被使用,但我不知道在符号上使用关键字参数是否有什么特别的优势(cmets,有人吗?我很想知道)。

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

    (需要 FEATURE &optional FILENAME NOERROR)

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

    【讨论】:

    • 对于它的价值,检查只是看是否定义了'noerror,所以任何非零值都可以工作。我自己一直在使用t
    • 这不适用于AUCTeX,因为不能要求AUCTeX。您需要将package-installed-p 用于AUCTeX
    • auctex 确实有点不寻常。看起来你可以在加载auctex 之后测试tex-site。例如(load "auctex" :noerror) (when (require 'tex-site nil :noerror) ...)
    【解决方案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 会从progn 中捕获任何file-error,因此您要确保不要在其中执行任何其他文件操作。最终,您可能只想将 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") )
    

    【讨论】:

    • eval-after-load 似乎没有加载包。于是我改成了下面的答案:(when (...))
    • 是的,eval-after-load 的目的是指定在加载指定包时执行的延迟操作。当您为不涉及加载 ecb 的任务启动 Emacs 时,这对于避免不必要的设置很有用(批量字节编译是一个常年的例子)。
    【解决方案3】:

    为什么不使用“featurep”?

    (featurep FEATURE &optional SUBFEATURE)
    

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

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

    【讨论】:

    • 这仅适用于已加载的功能(因此与此特定问题不太相关)。
    【解决方案4】:

    对于想知道如何检查是否安装了 package.el 包的人,请使用package-installed-p

    【讨论】:

      【解决方案5】:

      这个问题晚了四年,但是...这里有一个简单的宏可以为你做这件事。

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

      【讨论】:

        【解决方案6】:

        最简单的答案是使用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))))
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-28
          • 1970-01-01
          • 2012-07-09
          • 1970-01-01
          • 1970-01-01
          • 2012-06-25
          相关资源
          最近更新 更多