]> code.delx.au - gnu-emacs/blobdiff - lisp/wid-edit.el
* emacs-lisp/package.el (package-untar-buffer): Handle problematic tarfile content...
[gnu-emacs] / lisp / wid-edit.el
index c9008d092d4f5ed9b5e88ce205fea26a0bdfae6b..9c5c6462bcc2295cd6c95205722f181e5a51f962 100644 (file)
@@ -1,6 +1,6 @@
-;;; wid-edit.el --- Functions for creating and using widgets -*-byte-compile-dynamic: t;-*-
+;;; wid-edit.el --- Functions for creating and using widgets -*-byte-compile-dynamic: t; lexical-binding:t -*-
 ;;
 ;;
-;; Copyright (C) 1996-1997, 1999-2011  Free Software Foundation, Inc.
+;; Copyright (C) 1996-1997, 1999-2012  Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
@@ -295,10 +295,10 @@ minibuffer."
             (error "Canceled"))
           value))))
 
             (error "Canceled"))
           value))))
 
-(defun widget-remove-if (predictate list)
+(defun widget-remove-if (predicate list)
   (let (result (tail list))
     (while tail
   (let (result (tail list))
     (while tail
-      (or (funcall predictate (car tail))
+      (or (funcall predicate (car tail))
          (setq result (cons (car tail) result)))
       (setq tail (cdr tail)))
     (nreverse result)))
          (setq result (cons (car tail) result)))
       (setq tail (cdr tail)))
     (nreverse result)))
@@ -414,7 +414,7 @@ the :notify function can't know the new value.")
     (overlay-put overlay 'follow-link follow-link)
     (overlay-put overlay 'help-echo help-echo)))
 
     (overlay-put overlay 'follow-link follow-link)
     (overlay-put overlay 'help-echo help-echo)))
 
-(defun widget-mouse-help (window overlay point)
+(defun widget-mouse-help (_window overlay _point)
   "Help-echo callback for widgets whose :help-echo is a function."
   (with-current-buffer (overlay-buffer overlay)
     (let* ((widget (widget-at (overlay-start overlay)))
   "Help-echo callback for widgets whose :help-echo is a function."
   (with-current-buffer (overlay-buffer overlay)
     (let* ((widget (widget-at (overlay-start overlay)))
@@ -466,7 +466,7 @@ the :notify function can't know the new value.")
       (overlay-put overlay 'modification-hooks '(widget-overlay-inactive))
       (widget-put widget :inactive overlay))))
 
       (overlay-put overlay 'modification-hooks '(widget-overlay-inactive))
       (widget-put widget :inactive overlay))))
 
-(defun widget-overlay-inactive (&rest junk)
+(defun widget-overlay-inactive (&rest _junk)
   "Ignoring the arguments, signal an error."
   (unless inhibit-read-only
     (error "The widget here is not active")))
   "Ignoring the arguments, signal an error."
   (unless inhibit-read-only
     (error "The widget here is not active")))
@@ -577,7 +577,7 @@ This is only meaningful for radio buttons or checkboxes in a list."
   "Map FUNCTION over the buttons in BUFFER.
 FUNCTION is called with the arguments WIDGET and MAPARG.
 
   "Map FUNCTION over the buttons in BUFFER.
 FUNCTION is called with the arguments WIDGET and MAPARG.
 
-If FUNCTION returns non-nil, the walk is cancelled.
+If FUNCTION returns non-nil, the walk is canceled.
 
 The arguments MAPARG, and BUFFER default to nil and (current-buffer),
 respectively."
 
 The arguments MAPARG, and BUFFER default to nil and (current-buffer),
 respectively."
@@ -648,7 +648,7 @@ extension (xpm, xbm, gif, jpg, or png) located in
 This exists as a variable so it can be set locally in certain
 buffers.")
 
 This exists as a variable so it can be set locally in certain
 buffers.")
 
-(defun widget-image-insert (widget tag image &optional down inactive)
+(defun widget-image-insert (widget tag image &optional _down _inactive)
   "In WIDGET, insert the text TAG or, if supported, IMAGE.
 IMAGE should either be an image or an image file name sans extension
 \(xpm, xbm, gif, jpg, or png) located in `widget-image-directory'.
   "In WIDGET, insert the text TAG or, if supported, IMAGE.
 IMAGE should either be an image or an image file name sans extension
 \(xpm, xbm, gif, jpg, or png) located in `widget-image-directory'.
@@ -1141,12 +1141,6 @@ the field."
        (kill-region (point) end)
       (call-interactively 'kill-line))))
 
        (kill-region (point) end)
       (call-interactively 'kill-line))))
 
-(defcustom widget-complete-field (lookup-key global-map "\M-\t")
-  "Default function to call for completion inside fields."
-  :options '(ispell-complete-word complete-tag lisp-complete-symbol)
-  :type 'function
-  :group 'widgets)
-
 (defun widget-narrow-to-field ()
   "Narrow to field."
   (interactive)
 (defun widget-narrow-to-field ()
   "Narrow to field."
   (interactive)
@@ -1161,10 +1155,25 @@ the field."
   "Complete content of editable field from point.
 When not inside a field, signal an error."
   (interactive)
   "Complete content of editable field from point.
 When not inside a field, signal an error."
   (interactive)
+  (let ((data (widget-completions-at-point)))
+    (cond
+     ((functionp data) (funcall data))
+     ((consp data)
+      (let ((completion-extra-properties (nth 3 data)))
+        (completion-in-region (nth 0 data) (nth 1 data) (nth 2 data)
+                              (plist-get completion-extra-properties
+                                         :predicate))))
+     (t
+      (error "Not in an editable field")))))
+;; We may want to use widget completion in buffers where the major mode
+;; hasn't added widget-completions-at-point to completion-at-point-functions,
+;; so it's not really obsolete (yet).
+;; (make-obsolete 'widget-complete 'completion-at-point "24.1")
+
+(defun widget-completions-at-point ()
   (let ((field (widget-field-find (point))))
   (let ((field (widget-field-find (point))))
-    (if field
-       (widget-apply field :complete)
-      (error "Not in an editable field"))))
+    (when field
+      (widget-apply field :completions-function))))
 
 ;;; Setting up the buffer.
 
 
 ;;; Setting up the buffer.
 
@@ -1307,7 +1316,7 @@ Unlike (get-char-property POS 'field), this works with empty fields too."
   (add-hook 'before-change-functions 'widget-before-change nil t)
   (add-hook 'after-change-functions 'widget-after-change nil t))
 
   (add-hook 'before-change-functions 'widget-before-change nil t)
   (add-hook 'after-change-functions 'widget-after-change nil t))
 
-(defun widget-after-change (from to old)
+(defun widget-after-change (from to _old)
   "Adjust field size and text properties."
   (let ((field (widget-field-find from))
        (other (widget-field-find to)))
   "Adjust field size and text properties."
   (let ((field (widget-field-find from))
        (other (widget-field-find to)))
@@ -1431,11 +1440,11 @@ The value of the :type attribute should be an unconverted widget type."
 
 (define-widget 'default nil
   "Basic widget other widgets are derived from."
 
 (define-widget 'default nil
   "Basic widget other widgets are derived from."
-  :value-to-internal (lambda (widget value) value)
-  :value-to-external (lambda (widget value) value)
+  :value-to-internal (lambda (_widget value) value)
+  :value-to-external (lambda (_widget value) value)
   :button-prefix 'widget-button-prefix
   :button-suffix 'widget-button-suffix
   :button-prefix 'widget-button-prefix
   :button-suffix 'widget-button-suffix
-  :complete 'widget-default-complete
+  :completions-function #'widget-default-completions
   :create 'widget-default-create
   :indent nil
   :offset 0
   :create 'widget-default-create
   :indent nil
   :offset 0
@@ -1461,13 +1470,20 @@ The value of the :type attribute should be an unconverted widget type."
 
 (defvar widget--completing-widget)
 
 
 (defvar widget--completing-widget)
 
-(defun widget-default-complete (widget)
-  "Call the value of the :complete-function property of WIDGET.
-If that does not exist, call the value of `widget-complete-field'.
-During this call, `widget--completing-widget' is bound to WIDGET."
-  (let ((widget--completing-widget widget))
-    (call-interactively (or (widget-get widget :complete-function)
-                           widget-complete-field))))
+(defun widget-default-completions (widget)
+  "Return completion data, like `completion-at-point-functions' would."
+  (let ((completions (widget-get widget :completions)))
+    (if completions
+        (list (widget-field-start widget)
+              (max (point) (widget-field-text-end widget))
+              completions)
+      (if (widget-get widget :complete)
+          (lambda () (widget-apply widget :complete))
+        (if (widget-get widget :complete-function)
+            (lambda ()
+              (let ((widget--completing-widget widget))
+                (call-interactively
+                 (widget-get widget :complete-function)))))))))
 
 (defun widget-default-create (widget)
   "Create WIDGET at point in the current buffer."
 
 (defun widget-default-create (widget)
   "Create WIDGET at point in the current buffer."
@@ -1544,7 +1560,7 @@ During this call, `widget--completing-widget' is bound to WIDGET."
      (widget-put widget :to to)))
   (widget-clear-undo))
 
      (widget-put widget :to to)))
   (widget-clear-undo))
 
-(defun widget-default-format-handler (widget escape)
+(defun widget-default-format-handler (_widget escape)
   (error "Unknown escape `%c'" escape))
 
 (defun widget-default-button-face-get (widget)
   (error "Unknown escape `%c'" escape))
 
 (defun widget-default-button-face-get (widget)
@@ -1652,16 +1668,16 @@ During this call, `widget--completing-widget' is bound to WIDGET."
     (when parent
       (widget-apply parent :notify widget event))))
 
     (when parent
       (widget-apply parent :notify widget event))))
 
-(defun widget-default-notify (widget child &optional event)
+(defun widget-default-notify (widget _child &optional event)
   "Pass notification to parent."
   (widget-default-action widget event))
 
   "Pass notification to parent."
   (widget-default-action widget event))
 
-(defun widget-default-prompt-value (widget prompt value unbound)
+(defun widget-default-prompt-value (_widget prompt _value _unbound)
   "Read an arbitrary value."
   (eval-minibuffer prompt))
 
 (defun widget-docstring (widget)
   "Read an arbitrary value."
   (eval-minibuffer prompt))
 
 (defun widget-docstring (widget)
-  "Return the documentation string specificied by WIDGET, or nil if none.
+  "Return the documentation string specified by WIDGET, or nil if none.
 If WIDGET has a `:doc' property, that specifies the documentation string.
 Otherwise, try the `:documentation-property' property.  If this
 is a function, call it with the widget's value as an argument; if
 If WIDGET has a `:doc' property, that specifies the documentation string.
 Otherwise, try the `:documentation-property' property.  If this
 is a function, call it with the widget's value as an argument; if
@@ -1704,14 +1720,14 @@ as the argument to `documentation-property'."
   ;; Match if the value is the same.
   (equal (widget-get widget :value) value))
 
   ;; Match if the value is the same.
   (equal (widget-get widget :value) value))
 
-(defun widget-item-match-inline (widget values)
+(defun widget-item-match-inline (widget vals)
   ;; Match if the value is the same.
   (let ((value (widget-get widget :value)))
     (and (listp value)
   ;; Match if the value is the same.
   (let ((value (widget-get widget :value)))
     (and (listp value)
-        (<= (length value) (length values))
-        (let ((head (widget-sublist values 0 (length value))))
+        (<= (length value) (length vals))
+        (let ((head (widget-sublist vals 0 (length value))))
           (and (equal head value)
           (and (equal head value)
-               (cons head (widget-sublist values (length value))))))))
+               (cons head (widget-sublist vals (length value))))))))
 
 (defun widget-sublist (list start &optional end)
   "Return the sublist of LIST from START to END.
 
 (defun widget-sublist (list start &optional end)
   "Return the sublist of LIST from START to END.
@@ -1796,7 +1812,7 @@ If END is omitted, it defaults to the length of LIST."
   "A link to an info file."
   :action 'widget-info-link-action)
 
   "A link to an info file."
   :action 'widget-info-link-action)
 
-(defun widget-info-link-action (widget &optional event)
+(defun widget-info-link-action (widget &optional _event)
   "Open the info node specified by WIDGET."
   (info (widget-value widget)))
 
   "Open the info node specified by WIDGET."
   (info (widget-value widget)))
 
@@ -1806,7 +1822,7 @@ If END is omitted, it defaults to the length of LIST."
   "A link to an www page."
   :action 'widget-url-link-action)
 
   "A link to an www page."
   :action 'widget-url-link-action)
 
-(defun widget-url-link-action (widget &optional event)
+(defun widget-url-link-action (widget &optional _event)
   "Open the URL specified by WIDGET."
   (browse-url (widget-value widget)))
 
   "Open the URL specified by WIDGET."
   (browse-url (widget-value widget)))
 
@@ -1816,7 +1832,7 @@ If END is omitted, it defaults to the length of LIST."
   "A link to an Emacs function."
   :action 'widget-function-link-action)
 
   "A link to an Emacs function."
   :action 'widget-function-link-action)
 
-(defun widget-function-link-action (widget &optional event)
+(defun widget-function-link-action (widget &optional _event)
   "Show the function specified by WIDGET."
   (describe-function (widget-value widget)))
 
   "Show the function specified by WIDGET."
   (describe-function (widget-value widget)))
 
@@ -1826,7 +1842,7 @@ If END is omitted, it defaults to the length of LIST."
   "A link to an Emacs variable."
   :action 'widget-variable-link-action)
 
   "A link to an Emacs variable."
   :action 'widget-variable-link-action)
 
-(defun widget-variable-link-action (widget &optional event)
+(defun widget-variable-link-action (widget &optional _event)
   "Show the variable specified by WIDGET."
   (describe-variable (widget-value widget)))
 
   "Show the variable specified by WIDGET."
   (describe-variable (widget-value widget)))
 
@@ -1836,7 +1852,7 @@ If END is omitted, it defaults to the length of LIST."
   "A link to a file."
   :action 'widget-file-link-action)
 
   "A link to a file."
   :action 'widget-file-link-action)
 
-(defun widget-file-link-action (widget &optional event)
+(defun widget-file-link-action (widget &optional _event)
   "Find the file specified by WIDGET."
   (find-file (widget-value widget)))
 
   "Find the file specified by WIDGET."
   (find-file (widget-value widget)))
 
@@ -1846,7 +1862,7 @@ If END is omitted, it defaults to the length of LIST."
   "A link to an Emacs Lisp library file."
   :action 'widget-emacs-library-link-action)
 
   "A link to an Emacs Lisp library file."
   :action 'widget-emacs-library-link-action)
 
-(defun widget-emacs-library-link-action (widget &optional event)
+(defun widget-emacs-library-link-action (widget &optional _event)
   "Find the Emacs library file specified by WIDGET."
   (find-file (locate-library (widget-value widget))))
 
   "Find the Emacs library file specified by WIDGET."
   (find-file (locate-library (widget-value widget))))
 
@@ -1856,7 +1872,7 @@ If END is omitted, it defaults to the length of LIST."
   "A link to Commentary in an Emacs Lisp library file."
   :action 'widget-emacs-commentary-link-action)
 
   "A link to Commentary in an Emacs Lisp library file."
   :action 'widget-emacs-commentary-link-action)
 
-(defun widget-emacs-commentary-link-action (widget &optional event)
+(defun widget-emacs-commentary-link-action (widget &optional _event)
   "Find the Commentary section of the Emacs file specified by WIDGET."
   (finder-commentary (widget-value widget)))
 
   "Find the Commentary section of the Emacs file specified by WIDGET."
   (finder-commentary (widget-value widget)))
 
@@ -1887,7 +1903,7 @@ by some other text in the `:format' string (if specified)."
 (defvar widget-field-history nil
   "History of field minibuffer edits.")
 
 (defvar widget-field-history nil
   "History of field minibuffer edits.")
 
-(defun widget-field-prompt-internal (widget prompt initial history)
+(defun widget-field-prompt-internal (_widget prompt initial history)
   "Read string for WIDGET prompting with PROMPT.
 INITIAL is the initial input and HISTORY is a symbol containing
 the earlier input."
   "Read string for WIDGET prompting with PROMPT.
 INITIAL is the initial input and HISTORY is a symbol containing
 the earlier input."
@@ -1907,7 +1923,7 @@ the earlier input."
 
 (defvar widget-edit-functions nil)
 
 
 (defvar widget-edit-functions nil)
 
-(defun widget-field-action (widget &optional event)
+(defun widget-field-action (widget &optional _event)
   "Move to next field."
   (widget-forward 1)
   (run-hook-with-args 'widget-edit-functions widget))
   "Move to next field."
   (widget-forward 1)
   (run-hook-with-args 'widget-edit-functions widget))
@@ -1922,8 +1938,7 @@ the earlier input."
   "Set an editable text field WIDGET to VALUE"
   (let ((from (widget-field-start widget))
        (to (widget-field-text-end widget))
   "Set an editable text field WIDGET to VALUE"
   (let ((from (widget-field-start widget))
        (to (widget-field-text-end widget))
-       (buffer (widget-field-buffer widget))
-       (size (widget-get widget :size)))
+       (buffer (widget-field-buffer widget)))
     (when (and from to (buffer-live-p buffer))
       (with-current-buffer buffer
        (goto-char from)
     (when (and from to (buffer-live-p buffer))
       (with-current-buffer buffer
        (goto-char from)
@@ -1962,10 +1977,14 @@ the earlier input."
     (when (overlayp overlay)
       (delete-overlay overlay))))
 
     (when (overlayp overlay)
       (delete-overlay overlay))))
 
-(defun widget-field-value-get (widget)
-  "Return current text in editing field."
+(defun widget-field-value-get (widget &optional no-truncate)
+  "Return current text in editing field.
+Normally, trailing spaces within the editing field are truncated.
+But if NO-TRUNCATE is non-nil, include them."
   (let ((from (widget-field-start widget))
   (let ((from (widget-field-start widget))
-       (to (widget-field-text-end widget))
+       (to   (if no-truncate
+                 (widget-field-end widget)
+               (widget-field-text-end widget)))
        (buffer (widget-field-buffer widget))
        (secret (widget-get widget :secret))
        (old (current-buffer)))
        (buffer (widget-field-buffer widget))
        (secret (widget-get widget :secret))
        (old (current-buffer)))
@@ -1983,7 +2002,7 @@ the earlier input."
            result))
       (widget-get widget :value))))
 
            result))
       (widget-get widget :value))))
 
-(defun widget-field-match (widget value)
+(defun widget-field-match (_widget value)
   ;; Match any string.
   (stringp value))
 
   ;; Match any string.
   (stringp value))
 
@@ -2054,7 +2073,7 @@ when he invoked the menu."
   :type 'boolean
   :group 'widgets)
 
   :type 'boolean
   :group 'widgets)
 
-(defun widget-choice-mouse-down-action (widget &optional event)
+(defun widget-choice-mouse-down-action (widget &optional _event)
   ;; Return non-nil if we need a menu.
   (let ((args (widget-get widget :args))
        (old (widget-get widget :choice)))
   ;; Return non-nil if we need a menu.
   (let ((args (widget-get widget :args))
        (old (widget-get widget :choice)))
@@ -2138,14 +2157,14 @@ when he invoked the menu."
            found (widget-apply current :match value)))
     found))
 
            found (widget-apply current :match value)))
     found))
 
-(defun widget-choice-match-inline (widget values)
+(defun widget-choice-match-inline (widget vals)
   ;; Matches if one of the choices matches.
   (let ((args (widget-get widget :args))
        current found)
     (while (and args (null found))
       (setq current (car args)
            args (cdr args)
   ;; Matches if one of the choices matches.
   (let ((args (widget-get widget :args))
        current found)
     (while (and args (null found))
       (setq current (car args)
            args (cdr args)
-           found (widget-match-inline current values)))
+           found (widget-match-inline current vals)))
     found))
 
 ;;; The `toggle' Widget.
     found))
 
 ;;; The `toggle' Widget.
@@ -2155,7 +2174,7 @@ when he invoked the menu."
   :format "%[%v%]\n"
   :value-create 'widget-toggle-value-create
   :action 'widget-toggle-action
   :format "%[%v%]\n"
   :value-create 'widget-toggle-value-create
   :action 'widget-toggle-action
-  :match (lambda (widget value) t)
+  :match (lambda (_widget _value) t)
   :on "on"
   :off "off")
 
   :on "on"
   :off "off")
 
@@ -2271,29 +2290,29 @@ If the item is checked, CHOSEN is a cons whose cdr is the value."
      (and button (widget-put widget :buttons (cons button buttons)))
      (and child (widget-put widget :children (cons child children))))))
 
      (and button (widget-put widget :buttons (cons button buttons)))
      (and child (widget-put widget :children (cons child children))))))
 
-(defun widget-checklist-match (widget values)
+(defun widget-checklist-match (widget vals)
   ;; All values must match a type in the checklist.
   ;; All values must match a type in the checklist.
-  (and (listp values)
-       (null (cdr (widget-checklist-match-inline widget values)))))
+  (and (listp vals)
+       (null (cdr (widget-checklist-match-inline widget vals)))))
 
 
-(defun widget-checklist-match-inline (widget values)
+(defun widget-checklist-match-inline (widget vals)
   ;; Find the values which match a type in the checklist.
   (let ((greedy (widget-get widget :greedy))
        (args (copy-sequence (widget-get widget :args)))
        found rest)
   ;; Find the values which match a type in the checklist.
   (let ((greedy (widget-get widget :greedy))
        (args (copy-sequence (widget-get widget :args)))
        found rest)
-    (while values
-      (let ((answer (widget-checklist-match-up args values)))
+    (while vals
+      (let ((answer (widget-checklist-match-up args vals)))
        (cond (answer
        (cond (answer
-              (let ((vals (widget-match-inline answer values)))
-                (setq found (append found (car vals))
-                      values (cdr vals)
+              (let ((vals2 (widget-match-inline answer vals)))
+                (setq found (append found (car vals2))
+                      vals (cdr vals2)
                       args (delq answer args))))
              (greedy
                       args (delq answer args))))
              (greedy
-              (setq rest (append rest (list (car values)))
-                    values (cdr values)))
+              (setq rest (append rest (list (car vals)))
+                    vals (cdr vals)))
              (t
              (t
-              (setq rest (append rest values)
-                    values nil)))))
+              (setq rest (append rest vals)
+                    vals nil)))))
     (cons found rest)))
 
 (defun widget-checklist-match-find (widget &optional vals)
     (cons found rest)))
 
 (defun widget-checklist-match-find (widget &optional vals)
@@ -2338,7 +2357,7 @@ Return an alist of (TYPE MATCH)."
     result))
 
 (defun widget-checklist-validate (widget)
     result))
 
 (defun widget-checklist-validate (widget)
-  ;; Ticked chilren must be valid.
+  ;; Ticked children must be valid.
   (let ((children (widget-get widget :children))
        child button found)
     (while (and children (not found))
   (let ((children (widget-get widget :children))
        child button found)
     (while (and children (not found))
@@ -2375,7 +2394,7 @@ Return an alist of (TYPE MATCH)."
   :off "( )"
   :off-glyph "radio0")
 
   :off "( )"
   :off-glyph "radio0")
 
-(defun widget-radio-button-notify (widget child &optional event)
+(defun widget-radio-button-notify (widget _child &optional event)
   ;; Tell daddy.
   (widget-apply (widget-get widget :parent) :action widget event))
 
   ;; Tell daddy.
   (widget-apply (widget-get widget :parent) :action widget event))
 
@@ -2544,7 +2563,7 @@ Return an alist of (TYPE MATCH)."
   :help-echo "Insert a new item into the list at this position."
   :action 'widget-insert-button-action)
 
   :help-echo "Insert a new item into the list at this position."
   :action 'widget-insert-button-action)
 
-(defun widget-insert-button-action (widget &optional event)
+(defun widget-insert-button-action (widget &optional _event)
   ;; Ask the parent to insert a new item.
   (widget-apply (widget-get widget :parent)
                :insert-before (widget-get widget :widget)))
   ;; Ask the parent to insert a new item.
   (widget-apply (widget-get widget :parent)
                :insert-before (widget-get widget :widget)))
@@ -2557,7 +2576,7 @@ Return an alist of (TYPE MATCH)."
   :help-echo "Delete this item from the list."
   :action 'widget-delete-button-action)
 
   :help-echo "Delete this item from the list."
   :action 'widget-delete-button-action)
 
-(defun widget-delete-button-action (widget &optional event)
+(defun widget-delete-button-action (widget &optional _event)
   ;; Ask the parent to insert a new item.
   (widget-apply (widget-get widget :parent)
                :delete-at (widget-get widget :widget)))
   ;; Ask the parent to insert a new item.
   (widget-apply (widget-get widget :parent)
                :delete-at (widget-get widget :widget)))
@@ -2780,10 +2799,10 @@ Return an alist of (TYPE MATCH)."
   ;; Get the default of the components.
   (mapcar 'widget-default-get (widget-get widget :args)))
 
   ;; Get the default of the components.
   (mapcar 'widget-default-get (widget-get widget :args)))
 
-(defun widget-group-match (widget values)
+(defun widget-group-match (widget vals)
   ;; Match if the components match.
   ;; Match if the components match.
-  (and (listp values)
-       (let ((match (widget-group-match-inline widget values)))
+  (and (listp vals)
+       (let ((match (widget-group-match-inline widget vals)))
         (and match (null (cdr match))))))
 
 (defun widget-group-match-inline (widget vals)
         (and match (null (cdr match))))))
 
 (defun widget-group-match-inline (widget vals)
@@ -2820,7 +2839,7 @@ The following properties have special meanings for this widget:
   :off "Show"
   :value-create 'widget-visibility-value-create
   :action 'widget-toggle-action
   :off "Show"
   :value-create 'widget-visibility-value-create
   :action 'widget-toggle-action
-  :match (lambda (widget value) t))
+  :match (lambda (_widget _value) t))
 
 (defalias 'widget-visibility-value-create 'widget-toggle-value-create)
 
 
 (defalias 'widget-visibility-value-create 'widget-toggle-value-create)
 
@@ -2834,7 +2853,7 @@ The following properties have special meanings for this widget:
   :help-echo "Describe this symbol"
   :action 'widget-documentation-link-action)
 
   :help-echo "Describe this symbol"
   :action 'widget-documentation-link-action)
 
-(defun widget-documentation-link-action (widget &optional event)
+(defun widget-documentation-link-action (widget &optional _event)
   "Display documentation for WIDGET's value.  Ignore optional argument EVENT."
   (let* ((string (widget-get widget :value))
         (symbol (intern string)))
   "Display documentation for WIDGET's value.  Ignore optional argument EVENT."
   (let* ((string (widget-get widget :value))
         (symbol (intern string)))
@@ -2888,15 +2907,7 @@ link for that string."
              (push (widget-convert-button widget-documentation-link-type
                                           begin end :value name)
                    buttons)))))
              (push (widget-convert-button widget-documentation-link-type
                                           begin end :value name)
                    buttons)))))
-      (widget-put widget :buttons buttons)))
-  (let ((indent (widget-get widget :indent)))
-    (when (and indent (not (zerop indent)))
-      (save-excursion
-       (save-restriction
-         (narrow-to-region from to)
-         (goto-char (point-min))
-         (while (search-forward "\n" nil t)
-           (insert-char ?\s indent)))))))
+      (widget-put widget :buttons buttons))))
 
 ;;; The `documentation-string' Widget.
 
 
 ;;; The `documentation-string' Widget.
 
@@ -2915,10 +2926,9 @@ link for that string."
        (start (point)))
     (if (string-match "\n" doc)
        (let ((before (substring doc 0 (match-beginning 0)))
        (start (point)))
     (if (string-match "\n" doc)
        (let ((before (substring doc 0 (match-beginning 0)))
-             (after (substring doc (match-beginning 0)))
-             button)
-         (when (and indent (not (zerop indent)))
-           (insert-char ?\s indent))
+             (after (substring doc (match-end 0)))
+             button end)
+         (widget-documentation-string-indent-to indent)
          (insert before ?\s)
          (widget-documentation-link-add widget start (point))
          (setq button
          (insert before ?\s)
          (widget-documentation-link-add widget start (point))
          (setq button
@@ -2931,19 +2941,36 @@ link for that string."
                 :action 'widget-parent-action
                 shown))
          (when shown
                 :action 'widget-parent-action
                 shown))
          (when shown
+           (insert ?\n)
            (setq start (point))
            (when (and indent (not (zerop indent)))
              (insert-char ?\s indent))
            (insert after)
            (setq start (point))
            (when (and indent (not (zerop indent)))
              (insert-char ?\s indent))
            (insert after)
-           (widget-documentation-link-add widget start (point)))
+           (setq end (point))
+           (widget-documentation-link-add widget start end)
+           ;; Indent the subsequent lines.
+           (when (and indent (> indent 0))
+             (save-excursion
+               (save-restriction
+                 (narrow-to-region start end)
+                 (goto-char (point-min))
+                 (while (search-forward "\n" nil t)
+                   (widget-documentation-string-indent-to indent))))))
          (widget-put widget :buttons (list button)))
          (widget-put widget :buttons (list button)))
-      (when (and indent (not (zerop indent)))
-       (insert-char ?\s indent))
+      (widget-documentation-string-indent-to indent)
       (insert doc)
       (widget-documentation-link-add widget start (point))))
   (insert ?\n))
 
       (insert doc)
       (widget-documentation-link-add widget start (point))))
   (insert ?\n))
 
-(defun widget-documentation-string-action (widget &rest ignore)
+(defun widget-documentation-string-indent-to (col)
+  (when (and (numberp col)
+            (> col 0))
+    (let ((opoint (point)))
+      (indent-to col)
+      (put-text-property opoint (point)
+                        'display `(space :align-to ,col)))))
+
+(defun widget-documentation-string-action (widget &rest _ignore)
   ;; Toggle documentation.
   (let ((parent (widget-get widget :parent)))
     (widget-put parent :documentation-shown
   ;; Toggle documentation.
   (let ((parent (widget-get widget :parent)))
     (widget-put parent :documentation-shown
@@ -2981,7 +3008,7 @@ Optional ARGS specifies additional keyword arguments for the
   :prompt-value 'widget-const-prompt-value
   :format "%t\n%d")
 
   :prompt-value 'widget-const-prompt-value
   :format "%t\n%d")
 
-(defun widget-const-prompt-value (widget prompt value unbound)
+(defun widget-const-prompt-value (widget _prompt _value _unbound)
   ;; Return the value of the const.
   (widget-value widget))
 
   ;; Return the value of the const.
   (widget-value widget))
 
@@ -3019,20 +3046,6 @@ as the value."
   :complete-function 'ispell-complete-word
   :prompt-history 'widget-string-prompt-value-history)
 
   :complete-function 'ispell-complete-word
   :prompt-history 'widget-string-prompt-value-history)
 
-(defun widget-string-complete ()
-  "Complete contents of string field.
-Completions are taken from the :completion-alist property of the
-widget.  If that isn't a list, it's evalled and expected to yield a list."
-  (interactive)
-  (let* ((widget widget--completing-widget)
-        (completion-ignore-case (widget-get widget :completion-ignore-case))
-        (alist (widget-get widget :completion-alist))
-        (_ (unless (listp alist)
-             (setq alist (eval alist)))))
-    (completion-in-region (widget-field-start widget)
-                          (max (point) (widget-field-text-end widget))
-                          alist)))
-
 (define-widget 'regexp 'string
   "A regular expression."
   :match 'widget-regexp-match
 (define-widget 'regexp 'string
   "A regular expression."
   :match 'widget-regexp-match
@@ -3041,7 +3054,7 @@ widget.  If that isn't a list, it's evalled and expected to yield a list."
   ;; :value-face 'widget-single-line-field
   :tag "Regexp")
 
   ;; :value-face 'widget-single-line-field
   :tag "Regexp")
 
-(defun widget-regexp-match (widget value)
+(defun widget-regexp-match (_widget value)
   ;; Match valid regexps.
   (and (stringp value)
        (condition-case nil
   ;; Match valid regexps.
   (and (stringp value)
        (condition-case nil
@@ -3060,21 +3073,13 @@ widget.  If that isn't a list, it's evalled and expected to yield a list."
 (define-widget 'file 'string
   "A file widget.
 It reads a file name from an editable text field."
 (define-widget 'file 'string
   "A file widget.
 It reads a file name from an editable text field."
-  :complete-function 'widget-file-complete
+  :completions #'completion-file-name-table
   :prompt-value 'widget-file-prompt-value
   :format "%{%t%}: %v"
   ;; Doesn't work well with terminating newline.
   ;; :value-face 'widget-single-line-field
   :tag "File")
 
   :prompt-value 'widget-file-prompt-value
   :format "%{%t%}: %v"
   ;; Doesn't work well with terminating newline.
   ;; :value-face 'widget-single-line-field
   :tag "File")
 
-(defun widget-file-complete ()
-  "Perform completion on file name preceding point."
-  (interactive)
-  (let ((widget widget--completing-widget))
-    (completion-in-region (widget-field-start widget)
-                         (max (point) (widget-field-text-end widget))
-                         'completion-file-name-table)))
-
 (defun widget-file-prompt-value (widget prompt value unbound)
   ;; Read file from minibuffer.
   (abbreviate-file-name
 (defun widget-file-prompt-value (widget prompt value unbound)
   ;; Read file from minibuffer.
   (abbreviate-file-name
@@ -3113,16 +3118,16 @@ It reads a directory name from an editable text field."
   :value nil
   :tag "Symbol"
   :format "%{%t%}: %v"
   :value nil
   :tag "Symbol"
   :format "%{%t%}: %v"
-  :match (lambda (widget value) (symbolp value))
-  :complete-function 'lisp-complete-symbol
+  :match (lambda (_widget value) (symbolp value))
+  :completions obarray
   :prompt-internal 'widget-symbol-prompt-internal
   :prompt-match 'symbolp
   :prompt-history 'widget-symbol-prompt-value-history
   :prompt-internal 'widget-symbol-prompt-internal
   :prompt-match 'symbolp
   :prompt-history 'widget-symbol-prompt-value-history
-  :value-to-internal (lambda (widget value)
+  :value-to-internal (lambda (_widget value)
                       (if (symbolp value)
                           (symbol-name value)
                         value))
                       (if (symbolp value)
                           (symbol-name value)
                         value))
-  :value-to-external (lambda (widget value)
+  :value-to-external (lambda (_widget value)
                       (if (stringp value)
                           (intern value)
                         value)))
                       (if (stringp value)
                           (intern value)
                         value)))
@@ -3142,9 +3147,8 @@ It reads a directory name from an editable text field."
 
 (define-widget 'function 'restricted-sexp
   "A Lisp function."
 
 (define-widget 'function 'restricted-sexp
   "A Lisp function."
-  :complete-function (lambda ()
-                      (interactive)
-                      (lisp-complete-symbol 'fboundp))
+  :completions (apply-partially #'completion-table-with-predicate
+                                obarray #'fboundp 'strict)
   :prompt-value 'widget-field-prompt-value
   :prompt-internal 'widget-symbol-prompt-internal
   :prompt-match 'fboundp
   :prompt-value 'widget-field-prompt-value
   :prompt-internal 'widget-symbol-prompt-internal
   :prompt-match 'fboundp
@@ -3166,9 +3170,8 @@ It reads a directory name from an editable text field."
   "A Lisp variable."
   :prompt-match 'boundp
   :prompt-history 'widget-variable-prompt-value-history
   "A Lisp variable."
   :prompt-match 'boundp
   :prompt-history 'widget-variable-prompt-value-history
-  :complete-function (lambda ()
-                      (interactive)
-                      (lisp-complete-symbol 'boundp))
+  :completions (apply-partially #'completion-table-with-predicate
+                                obarray #'boundp 'strict)
   :tag "Variable")
 
 (define-widget 'coding-system 'symbol
   :tag "Variable")
 
 (define-widget 'coding-system 'symbol
@@ -3179,9 +3182,8 @@ It reads a directory name from an editable text field."
   :prompt-history 'coding-system-value-history
   :prompt-value 'widget-coding-system-prompt-value
   :action 'widget-coding-system-action
   :prompt-history 'coding-system-value-history
   :prompt-value 'widget-coding-system-prompt-value
   :action 'widget-coding-system-action
-  :complete-function (lambda ()
-                      (interactive)
-                      (lisp-complete-symbol 'coding-system-p))
+  :completions (apply-partially #'completion-table-with-predicate
+                                obarray #'coding-system-p 'strict)
   :validate (lambda (widget)
              (unless (coding-system-p (widget-value widget))
                (widget-put widget :error (format "Invalid coding system: %S"
   :validate (lambda (widget)
              (unless (coding-system-p (widget-value widget))
                (widget-put widget :error (format "Invalid coding system: %S"
@@ -3190,7 +3192,7 @@ It reads a directory name from an editable text field."
   :value 'undecided
   :prompt-match 'coding-system-p)
 
   :value 'undecided
   :prompt-match 'coding-system-p)
 
-(defun widget-coding-system-prompt-value (widget prompt value unbound)
+(defun widget-coding-system-prompt-value (widget prompt value _unbound)
   "Read coding-system from minibuffer."
   (if (widget-get widget :base-only)
       (intern
   "Read coding-system from minibuffer."
   (if (widget-get widget :base-only)
       (intern
@@ -3280,7 +3282,7 @@ It reads a directory name from an editable text field."
        (key-description value))
     value))
 
        (key-description value))
     value))
 
-(defun widget-key-sequence-value-to-external (widget value)
+(defun widget-key-sequence-value-to-external (_widget value)
   (if (stringp value)
       (if (string-match "\\`[[:space:]]*\\'" value)
          widget-key-sequence-default-value
   (if (stringp value)
       (if (string-match "\\`[[:space:]]*\\'" value)
          widget-key-sequence-default-value
@@ -3294,13 +3296,13 @@ It reads a directory name from an editable text field."
   :format "%{%t%}: %v"
   :value nil
   :validate 'widget-sexp-validate
   :format "%{%t%}: %v"
   :value nil
   :validate 'widget-sexp-validate
-  :match (lambda (widget value) t)
+  :match (lambda (_widget _value) t)
   :value-to-internal 'widget-sexp-value-to-internal
   :value-to-internal 'widget-sexp-value-to-internal
-  :value-to-external (lambda (widget value) (read value))
+  :value-to-external (lambda (_widget value) (read value))
   :prompt-history 'widget-sexp-prompt-value-history
   :prompt-value 'widget-sexp-prompt-value)
 
   :prompt-history 'widget-sexp-prompt-value-history
   :prompt-value 'widget-sexp-prompt-value)
 
-(defun widget-sexp-value-to-internal (widget value)
+(defun widget-sexp-value-to-internal (_widget value)
   ;; Use pp for printer representation.
   (let ((pp (if (symbolp value)
                (prin1-to-string value)
   ;; Use pp for printer representation.
   (let ((pp (if (symbolp value)
                (prin1-to-string value)
@@ -3318,7 +3320,7 @@ It reads a directory name from an editable text field."
     (insert (widget-apply widget :value-get))
     (goto-char (point-min))
     (let (err)
     (insert (widget-apply widget :value-get))
     (goto-char (point-min))
     (let (err)
-      (condition-case data
+      (condition-case data ;Note: We get a spurious byte-compile warning here.
          (progn
            ;; Avoid a confusing end-of-file error.
            (skip-syntax-forward "\\s-")
          (progn
            ;; Avoid a confusing end-of-file error.
            (skip-syntax-forward "\\s-")
@@ -3407,15 +3409,16 @@ To use this type, you must define :match or :match-alternatives."
   :format "%{%t%}: %v\n"
   :valid-regexp "\\`.\\'"
   :error "This field should contain a single character"
   :format "%{%t%}: %v\n"
   :valid-regexp "\\`.\\'"
   :error "This field should contain a single character"
-  :value-to-internal (lambda (widget value)
+  :value-get (lambda (w) (widget-field-value-get w t))
+  :value-to-internal (lambda (_widget value)
                       (if (stringp value)
                           value
                         (char-to-string value)))
                       (if (stringp value)
                           value
                         (char-to-string value)))
-  :value-to-external (lambda (widget value)
+  :value-to-external (lambda (_widget value)
                       (if (stringp value)
                           (aref value 0)
                         value))
                       (if (stringp value)
                           (aref value 0)
                         value))
-  :match (lambda (widget value)
+  :match (lambda (_widget value)
           (characterp value)))
 
 (define-widget 'list 'group
           (characterp value)))
 
 (define-widget 'list 'group
@@ -3428,8 +3431,8 @@ To use this type, you must define :match or :match-alternatives."
   :tag "Vector"
   :format "%{%t%}:\n%v"
   :match 'widget-vector-match
   :tag "Vector"
   :format "%{%t%}:\n%v"
   :match 'widget-vector-match
-  :value-to-internal (lambda (widget value) (append value nil))
-  :value-to-external (lambda (widget value) (apply 'vector value)))
+  :value-to-internal (lambda (_widget value) (append value nil))
+  :value-to-external (lambda (_widget value) (apply 'vector value)))
 
 (defun widget-vector-match (widget value)
   (and (vectorp value)
 
 (defun widget-vector-match (widget value)
   (and (vectorp value)
@@ -3441,9 +3444,9 @@ To use this type, you must define :match or :match-alternatives."
   :tag "Cons-cell"
   :format "%{%t%}:\n%v"
   :match 'widget-cons-match
   :tag "Cons-cell"
   :format "%{%t%}:\n%v"
   :match 'widget-cons-match
-  :value-to-internal (lambda (widget value)
+  :value-to-internal (lambda (_widget value)
                       (list (car value) (cdr value)))
                       (list (car value) (cdr value)))
-  :value-to-external (lambda (widget value)
+  :value-to-external (lambda (_widget value)
                       (apply 'cons value)))
 
 (defun widget-cons-match (widget value)
                       (apply 'cons value)))
 
 (defun widget-cons-match (widget value)
@@ -3604,7 +3607,7 @@ example:
   :button-suffix 'widget-push-button-suffix
   :prompt-value 'widget-choice-prompt-value)
 
   :button-suffix 'widget-push-button-suffix
   :prompt-value 'widget-choice-prompt-value)
 
-(defun widget-choice-prompt-value (widget prompt value unbound)
+(defun widget-choice-prompt-value (widget prompt value _unbound)
   "Make a choice."
   (let ((args (widget-get widget :args))
        (completion-ignore-case (widget-get widget :case-fold))
   "Make a choice."
   (let ((args (widget-get widget :args))
        (completion-ignore-case (widget-get widget :case-fold))
@@ -3672,7 +3675,7 @@ example:
   :on "on (non-nil)"
   :off "off (nil)")
 
   :on "on (non-nil)"
   :off "off (nil)")
 
-(defun widget-boolean-prompt-value (widget prompt value unbound)
+(defun widget-boolean-prompt-value (_widget prompt _value _unbound)
   ;; Toggle a boolean.
   (y-or-n-p prompt))
 \f
   ;; Toggle a boolean.
   (y-or-n-p prompt))
 \f
@@ -3686,7 +3689,7 @@ example:
   :size 10
   :tag "Color"
   :value "black"
   :size 10
   :tag "Color"
   :value "black"
-  :complete 'widget-color-complete
+  :completions (or facemenu-color-alist (defined-colors))
   :sample-face-get 'widget-color-sample-face-get
   :notify 'widget-color-notify
   :action 'widget-color-action)
   :sample-face-get 'widget-color-sample-face-get
   :notify 'widget-color-notify
   :action 'widget-color-action)
@@ -3699,7 +3702,7 @@ example:
    :tag " Choose " :action 'widget-color--choose-action)
   (widget-insert " "))
 
    :tag " Choose " :action 'widget-color--choose-action)
   (widget-insert " "))
 
-(defun widget-color--choose-action (widget &optional event)
+(defun widget-color--choose-action (widget &optional _event)
   (list-colors-display
    nil nil
    `(lambda (color)
   (list-colors-display
    nil nil
    `(lambda (color)
@@ -3712,14 +3715,6 @@ example:
               (delete-window win)))
        (pop-to-buffer ,(current-buffer))))))
 
               (delete-window win)))
        (pop-to-buffer ,(current-buffer))))))
 
-(defun widget-color-complete (widget)
-  "Complete the color in WIDGET."
-  (require 'facemenu)                  ; for facemenu-color-alist
-  (completion-in-region (widget-field-start widget)
-                        (max (point) (widget-field-text-end widget))
-                        (or facemenu-color-alist
-                            (sort (defined-colors) 'string-lessp))))
-
 (defun widget-color-sample-face-get (widget)
   (let* ((value (condition-case nil
                    (widget-value widget)
 (defun widget-color-sample-face-get (widget)
   (let* ((value (condition-case nil
                    (widget-value widget)
@@ -3732,8 +3727,6 @@ example:
   "Prompt for a color."
   (let* ((tag (widget-apply widget :menu-tag-get))
         (prompt (concat tag ": "))
   "Prompt for a color."
   (let* ((tag (widget-apply widget :menu-tag-get))
         (prompt (concat tag ": "))
-        (value (widget-value widget))
-        (start (widget-field-start widget))
         (answer (facemenu-read-color prompt)))
     (unless (zerop (length answer))
       (widget-value-set widget answer)
         (answer (facemenu-read-color prompt)))
     (unless (zerop (length answer))
       (widget-value-set widget answer)