使用defcustom创建可自定义的值时,如何验证用户的条目?

时间:2012-09-13 20:26:17

标签: emacs elisp

我正在编写一个正在演变成包的elisp文件,因此我将其一些变量转换为defcustom语句并记录它们。其中一些defcustom变量是相关的,我想验证通过Customize系统输入的值,以确保关系成立。

以下是我所拥有的一个例子:

(defcustom widget-canonical-names '("my_widget" . "widget_assembly 8911_j4")
  "Documentation"
  :type '(alist :key-type (string :tag "Widget's short name")
                :value-type (string :tag "Full widget name"))
  :risky nil
  :group 'widgets)
(defcustom widget-colors '("my_widget" . "brown")
  "Documentation"
  :type '(alist :key-type (string :tag "Widget's short name")
                :value-type (color :tag "color of the widget"))
  :risky nil
  :group 'widgets)
(defcustom widget-paths '("my_widget" . "~/widgets")
  "Documentation"
  :type '(alist :key-type (string :tag "Widget's short name")
                :value-type (directory :tag "support files for widget"))
  :risky nil
  :group 'widgets)

因此有小部件并且它们具有各种设置,并且我需要能够通过仅知道小部件的短名称来访问小部件的任意设置。我想制作某种验证功能(不幸的是,谷歌搜索“emacs defcustom validate”没有帮助),如果用户在widget-pathswidget-colors中输入了一个小部件名称,不在widget-canonical-names列表中,他们会得到“你确定吗?”警告并注意输入不匹配的名字。我可以将这样的验证功能附加到我的defcustom吗?如果是这样,那是什么语法?

当然,理想的做法是让用户输入一次短名称,但我无法弄清楚如何从'复合类型'elisp文档中做到这一点。所以对我的问题更好的回答会告诉我如何安排defcustom来设置类似于这个Python字典的数据结构:

customized_widgets = {
    "my_widget": { "canonical_name": "widget_assembly 8911_j4",
                   "widget_color": "brown",
                   "widget_path": "~/widgets",
                 },
    "another_widget": { "canonical_name" : "widget_obsolete 11.0",
                        "widget_color": "blue",
                        "widget_path": "~/blue_widgets",
                      },
     }

那么:我怎样才能获得我想要的行为,根据用于访问设置的数据对设置进行分组,或者验证功能在用户输入不一致数据时向用户发出警告?

1 个答案:

答案 0 :(得分:5)

这将定义与Python结构最接近的Emacs,其中dicts表示为alists,内部dict的固定键表示为符号。

(defcustom my-customized-widgets ()
  "My widget customization alist"
  :type '(alist
          :tag "Widgets"
          :key-type (string :tag "Short name")
          :value-type
          (set
           :format "%v"
           :entry-format "%b %v"
           (cons :format "%v"
                 (const :format "" widget-canonical-name)
                 (string :tag "CName"))
           (cons :format "%v"
                 (const :format "" widget-color)
                 (color :tag "Color"))
           (cons :format "%v"
                 (const :format "" widget-path)
                 (directory :tag " Path"))))
  :group 'widgets)