浏览代码

Ignore and warn about invalid overrides

Now ido-ubiquitous checks the override lists for invalid or corrupt
overrides and disables them while issuing a warning. Previously invalid
overrides could cause ido-ubiquitous to throw errors, thereby completely
disabling all completion or even hanging emacs completely.

Fixes #82.
Ryan C. Thompson 10 年之前
父节点
当前提交
eb120aad55
共有 1 个文件被更改,包括 65 次插入29 次删除
  1. 65 29
      ido-ubiquitous.el

+ 65 - 29
ido-ubiquitous.el

@@ -421,21 +421,28 @@ See `ido-ubiquitous-command-overrides' for valid override types."
   "Set the override property on FUNC to OVERRIDE and set up advice to apply the override."
   "Set the override property on FUNC to OVERRIDE and set up advice to apply the override."
   (setq func (ido-ubiquitous--as-symbol func)
   (setq func (ido-ubiquitous--as-symbol func)
         override (ido-ubiquitous--as-symbol override))
         override (ido-ubiquitous--as-symbol override))
-  (put func 'ido-ubiquitous-override override)
-  (when override
-    (let ((docstring
-           (format "Override ido-ubiquitous behavior in %s if its `ido-ubiquitous-override' property is non-nil." func)))
-      (eval
-       `(defadvice ,func (around ido-ubiquitous-override activate)
-          ,docstring
-          (let* ((func ',func)
-                 (override (get func 'ido-ubiquitous-override)))
-            (when override
-              (ido-ubiquitous--debug-message
-               "Using override `%s' for function `%s'"
-               override func))
-            (ido-ubiquitous-with-override override
-              ad-do-it)))))))
+  (if (memq override '(disable enable enable-old nil))
+      (progn
+        (put func 'ido-ubiquitous-override override)
+        (when override
+          (let ((docstring
+                 (format "Override ido-ubiquitous behavior in %s if its `ido-ubiquitous-override' property is non-nil." func)))
+            (eval
+             `(defadvice ,func (around ido-ubiquitous-override activate)
+                ,docstring
+                (let* ((func ',func)
+                       (override (get func 'ido-ubiquitous-override)))
+                  (when override
+                    (ido-ubiquitous--debug-message
+                     "Using override `%s' for function `%s'"
+                     override func))
+                  (ido-ubiquitous-with-override override
+                    ad-do-it)))))))
+    (display-warning
+     'ido-ubiquitous
+     (format "Ignoring invalid override action `%s' for function `%s' found in `ido-ubiquitous-function-overrides'."
+             override func)
+     :warning)))
 
 
 (defun ido-ubiquitous-set-function-overrides (sym newval)
 (defun ido-ubiquitous-set-function-overrides (sym newval)
   "Custom setter function for `ido-ubiquitous-function-overrides'.
   "Custom setter function for `ido-ubiquitous-function-overrides'.
@@ -454,8 +461,16 @@ each function to apply the appropriate override."
                                (ido-ubiquitous--as-string func))))
                                (ido-ubiquitous--as-string func))))
   (set-default sym newval)
   (set-default sym newval)
   ;; set new overrides
   ;; set new overrides
-  (cl-loop for (action _match-type func) in (eval sym)
-           do (ido-ubiquitous-apply-function-override func action)))
+  (cl-loop for override in (eval sym)
+           for (action match-type func) = override
+           if (eq match-type 'exact)
+           do (ido-ubiquitous-apply-function-override func action)
+           else
+           do (display-warning
+               'ido-ubiquitous
+               (format
+                "Ignoring invalid function override match-type `%s' for function `%s'; only match-type `exact' is supported in `ido-ubiquitous-function-overrides'."
+                match-type func))))
 
 
 (defcustom ido-ubiquitous-function-overrides ido-ubiquitous-default-function-overrides
 (defcustom ido-ubiquitous-function-overrides ido-ubiquitous-default-function-overrides
   "List of function override specifications for ido-ubiquitous
   "List of function override specifications for ido-ubiquitous
@@ -760,15 +775,24 @@ future sessions."
 (defun ido-ubiquitous-spec-match (spec symbol)
 (defun ido-ubiquitous-spec-match (spec symbol)
   "Returns t if SPEC matches SYMBOL (which should be a function name).
   "Returns t if SPEC matches SYMBOL (which should be a function name).
 
 
-See `ido-ubiquitous-command-overrides'."
-  (when (and symbol (symbolp symbol))
-    (cl-destructuring-bind (type text) spec
-      (let ((matcher (cdr (assoc type ido-ubiquitous-spec-matchers)))
-            (text (ido-ubiquitous--as-string text))
-            (symname (ido-ubiquitous--as-string symbol)))
-        (when (null matcher)
-          (error "ido-ubiquitous: Unknown match spec type \"%s\". See `ido-ubiquitous-spec-matchers' for valid types." type))
-        (funcall matcher text symname)))))
+See `ido-ubiquitous-command-overrides'. If the match spec is
+invalid or any other error occurs, the error is demoted to a
+warning and the function returns nil."
+  (condition-case err
+      (when (and symbol (symbolp symbol))
+        (cl-destructuring-bind (type text) spec
+          (let ((matcher (cdr (assoc type ido-ubiquitous-spec-matchers)))
+                (text (ido-ubiquitous--as-string text))
+                (symname (ido-ubiquitous--as-string symbol)))
+            (if matcher
+                (funcall matcher text symname)
+              ;; If the matcher is invalid, issue a warning and return
+              ;; nil.
+              (error "Unknown match spec type \"%s\". See `ido-ubiquitous-spec-matchers' for valid types." type)
+              nil))))
+    (error
+     (display-warning 'ido-ubiquitous "Error during ido-ubiquitous spec matching: %S" err)
+     nil)))
 
 
 (defun ido-ubiquitous-get-command-override (cmd)
 (defun ido-ubiquitous-get-command-override (cmd)
   "Return the override associated with the command CMD.
   "Return the override associated with the command CMD.
@@ -776,10 +800,22 @@ See `ido-ubiquitous-command-overrides'."
 If there is no override set for CMD in
 If there is no override set for CMD in
 `ido-ubiquitous-command-overrides', return nil."
 `ido-ubiquitous-command-overrides', return nil."
   (when (and cmd (symbolp cmd))
   (when (and cmd (symbolp cmd))
-    (cl-loop for (action . spec) in ido-ubiquitous-command-overrides
-             when (memq action '(disable enable enable-old nil))
-             when (ido-ubiquitous-spec-match spec cmd)
+    (cl-loop for override in ido-ubiquitous-command-overrides
+             for (action . spec) = override
+             for valid-action = (and (memq action '(disable enable enable-old nil))
+                                     (assoc (car spec) ido-ubiquitous-spec-matchers))
+             unless valid-action
+             do (progn
+                  (display-warning
+                   'ido-ubiquitous
+                   (format "Removing invalid override `%S' from `ido-ubiquitous-command-overrides'"
+                           (cons action spec) action)
+                   :warning)
+                  (setq ido-ubiquitous-command-overrides
+                        (remove override ido-ubiquitous-command-overrides)))
+             when (and valid-action (ido-ubiquitous-spec-match spec cmd))
              return action
              return action
+
              finally return nil)))
              finally return nil)))
 
 
 ;;; Workaround for https://github.com/DarwinAwardWinner/ido-ubiquitous/issues/24
 ;;; Workaround for https://github.com/DarwinAwardWinner/ido-ubiquitous/issues/24