;;; assistant.el --- guiding users through Emacs setup
-;; Copyright (C) 2004 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
;; Author: Lars Magne Ingebrigtsen <larsi@gnus.org>
;; Keywords: util
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;; Commentary:
(require 'widget)
(require 'wid-edit)
+(autoload 'gnus-error "gnus-util")
+(autoload 'netrc-get "netrc")
+(autoload 'netrc-machine "netrc")
+(autoload 'netrc-parse "netrc")
+
(defvar assistant-readers
'(("variable" assistant-variable-reader)
("validate" assistant-sexp-reader)
("next" assistant-list-reader)
("text" assistant-text-reader)))
-(defface assistant-field-face '((t (:bold t)))
+(defface assistant-field '((t (:bold t)))
"Face used for editable fields."
:group 'gnus-article-emphasis)
+;; backward-compatibility alias
+(put 'assistant-field-face 'face-alias 'assistant-field)
;;; Internal variables
(pop ast))
(car ast)))
+(defun assistant-node-name (node)
+ (assistant-get node "node"))
+
(defun assistant-previous-node-text (node)
(format "<< Go back to %s" node))
(setcar (nthcdr 3 elem) value)))))
(defun assistant-render-text (text node)
+ (unless (and text node)
+ (gnus-error
+ 5
+ "The assistant was asked to render invalid text or node data"))
(dolist (elem text)
(if (stringp elem)
;; Ordinary text
(variable (cadr elem))
(type (assistant-get-variable node variable 'type)))
(cond
- ((and (consp type)
- (eq (car type) :radio))
- (push
+ ((eq (car-safe type) :radio)
+ (push
(apply
#'widget-create
'radio-button-choice
"node")))
(cadr type))
assistant-widgets))
+ ((eq (car-safe type) :set)
+ (push
+ (apply
+ #'widget-create
+ 'set
+ :assistant-variable variable
+ :assistant-node node
+ :value (assistant-get-variable node variable nil t)
+ :notify (lambda (widget &rest ignore)
+ (assistant-set-variable
+ (widget-get widget :assistant-node)
+ (widget-get widget :assistant-variable)
+ (widget-value widget))
+ (assistant-render-node
+ (assistant-get
+ (widget-get widget :assistant-node)
+ "node")))
+ (cadr type))
+ assistant-widgets))
(t
(push
(widget-create
'editable-field
- :value-face 'assistant-field-face
+ :value-face 'assistant-field
:assistant-variable variable
(assistant-get-variable node variable))
assistant-widgets)
(add-text-properties start (point)
(list
'bold t
- 'face 'assistant-field-face
+ 'face 'assistant-field
'not-read-only t))))))))
(defun assistant-render-node (node-name)
(inhibit-read-only t)
(previous assistant-current-node)
(buffer-read-only nil))
+ (unless node
+ (gnus-error 5 "The node for %s could not be found" node-name))
(set (make-local-variable 'assistant-widgets) nil)
(assistant-set-defaults node)
(if (equal (assistant-get node "type") "interstitial")
- (assistant-render-node (assistant-find-next-node node-name))
+ (assistant-render-node (nth 0 (assistant-find-next-nodes node-name)))
(setq assistant-current-node node-name)
(when previous
(push previous assistant-previous-nodes))
(assistant-set-defaults (assistant-find-node node) 'force)
(assistant-render-node node)))
"Reset")
- (insert " ")
- (assistant-node-button 'next (assistant-find-next-node))
(insert "\n")
+ (dolist (nnode (assistant-find-next-nodes))
+ (assistant-node-button 'next nnode)
+ (insert "\n"))
+
(goto-char (point-min))
(assistant-make-read-only))))
(error "%s" result))))
(assistant-set node "save" t)))
-(defun assistant-find-next-node (&optional node)
+;; (defun assistant-find-next-node (&optional node)
+;; (let* ((node (assistant-find-node (or node assistant-current-node)))
+;; (node-name (assistant-node-name node))
+;; (nexts (assistant-get-list node "next"))
+;; next elem applicable)
+
+;; (while (setq elem (pop nexts))
+;; (when (assistant-eval (car (cadr elem)))
+;; (setq applicable (cons elem applicable))))
+
+;; ;; return the first thing we can
+;; (cadr (cadr (pop applicable)))))
+
+(defun assistant-find-next-nodes (&optional node)
(let* ((node (assistant-find-node (or node assistant-current-node)))
(nexts (assistant-get-list node "next"))
- next elem)
- (while (and (setq elem (cadr (pop nexts)))
- (not next))
- (when (setq next (assistant-eval (car elem)))
- (setq next (or (cadr elem) next))))
- next))
+ next elem applicable return)
+
+ (while (setq elem (pop nexts))
+ (when (assistant-eval (car (cadr elem)))
+ (setq applicable (cons elem applicable))))
+
+ ;; return the first thing we can
+
+ (while (setq elem (pop applicable))
+ (push (cadr (cadr elem)) return))
+
+ return))
(defun assistant-get-all-variables ()
(let ((variables nil))
(let ((bindings nil))
(dolist (variable (assistant-get-all-variables))
(setq variable (cadr variable))
- (push (list (car variable) (if (eq (nth 3 variable) 'default)
- nil
- (nth 3 variable)))
+ (push (list (car variable)
+ (if (eq (nth 3 variable) 'default)
+ nil
+ (if (listp (nth 3 variable))
+ `(list ,@(nth 3 variable))
+ (nth 3 variable))))
bindings))
(eval
`(let ,bindings