Changes from arch/CVS synchronization
[gnus] / lisp / assistant.el
index feb8d65..0ba3dbe 100644 (file)
   '(("variable" assistant-variable-reader)
     ("validate" assistant-sexp-reader)
     ("result" assistant-list-reader)
-    ("next" assistant-list-reader)))
+    ("next" assistant-list-reader)
+    ("text" assistant-text-reader)))
+
+(defface assistant-field-face '((t (:bold t)))
+  "Face used for editable fields."
+  :group 'gnus-article-emphasis)
 
 ;;; Internal variables
 
 (defvar assistant-data nil)
 (defvar assistant-current-node nil)
 (defvar assistant-previous-node nil)
+(defvar assistant-widgets nil)
 
 (defun assistant-parse-buffer ()
   (let (results command value)
            results))
     (assistant-segment (nreverse results))))
 
+(defun assistant-text-reader (text)
+  (with-temp-buffer
+    (insert text)
+    (goto-char (point-min))
+    (let ((start (point))
+         (sections nil))
+      (while (re-search-forward "@\\([^{]+\\){\\([^}]+\\)}" nil t)
+       (push (buffer-substring start (match-beginning 0))
+             sections)
+       (push (list (match-string 1) (match-string 2))
+             sections)
+       (setq start (point)))
+      (push (buffer-substring start (point-max))
+           sections)
+      (nreverse sections))))
+
 ;; Segment the raw assistant data into a list of nodes.
 (defun assistant-segment (list)
   (let ((ast nil)
        (push elem result)))
     (nreverse result)))
 
+;;;###autoload
 (defun assistant (file)
   "Assist setting up Emacs based on FILE."
   (interactive "fAssistant file name: ")
       (setcar (nthcdr 3 variable)
              (eval (nth 2 variable))))))
 
+(defun assistant-get-variable (node variable)
+  (let ((variables (assistant-get-list node "variable"))
+       (result nil))
+    (while (and (setq elem (pop variables))
+               (not result))
+      (setq elem (cadr elem))
+      (when (eq (intern variable) (car elem))
+       (setq result (format "%s" (nth 3 elem)))))
+    result))
+    
+(defun assistant-set-variable (node variable value)
+  (let ((variables (assistant-get-list node "variable")))
+    (while (setq elem (pop variables))
+      (setq elem (cadr elem))
+      (when (eq (intern variable) (car elem))
+       (setcar (nthcdr 3 elem) value)))))
+    
+(defun assistant-render-text (text node)
+  (dolist (elem text)
+    (if (stringp elem)
+       (insert elem)
+      (push 
+       (widget-create
+       'editable-field
+       :value-face 'assistant-field-face
+       :assistant-variable (cadr elem)
+       (assistant-get-variable node (cadr elem)))
+       assistant-widgets))))
+
 (defun assistant-render-node (node-name)
   (let ((node (assistant-find-node node-name)))
+    (set (make-local-variable 'assistant-widgets) nil)
     (assistant-set-defaults node)
     (setq assistant-current-node node-name)
     (erase-buffer)
     (insert (cadar assistant-data) "\n\n")
     (insert node-name "\n\n")
-    (insert (assistant-get node "text") "\n\n")
+    (assistant-render-text (assistant-get node "text") node)
+    (insert "\n\n")
     (when assistant-previous-node
       (assistant-node-button 'previous assistant-previous-node))
     (assistant-node-button 'next (assistant-find-next-node))
               (let* ((node (widget-get widget :assistant-node))
                      (type (widget-get widget :assistant-type)))
                 (when (eq type 'next)
+                  (assistant-get-widget-values)
                   (assistant-validate))
                 (if (null node)
                     (assistant-finish)
       (when 
          (cond
           ((eq type :number)
-           (not (numberp value)))
+           (string-match "[^0-9]" value))
           (t
            nil))
        (error "%s is not of type %s: %s"
               (car variable) type value)))))
 
+(defun assistant-get-widget-values ()
+  (let ((node (assistant-find-node assistant-current-node)))
+    (dolist (widget assistant-widgets)
+      (assistant-set-variable
+       node (widget-get widget :assistant-variable)
+       (widget-value widget)))))
+
 (defun assistant-validate ()
   (let* ((node (assistant-find-node assistant-current-node))
         (validation (assistant-get node "validate"))
             (nreverse results))))
 
 (provide 'assistant)
+
+;;; arch-tag: 0404bfa2-9226-4611-8d3f-335c2416175b
+;;; assistant.el ends here