#+TITLE: Capturing user input with the widget library
#+DATE: 2018-05-23 12:00:00 UTC
#+DESCRIPTION: Exploration into capturing user data using emacs widget library
#+FILETAGS: emacs:widgets:draft
#+CATEGORY: emacs
#+SLUG: emacs-user-input-via-widgets
#+BEGIN_COMMENT
.. title: Capturing user input with the widget library
.. slug: emacs-user-input-via-widgets
.. date: 2018-05-23 12:00:00 UTC
.. tags: emacs, widgets, draft
.. category: emacs
.. description: Exploration into capturing user data using emacs widget library
.. type: text
#+END_COMMENT

After writting a emacs plugin I had need to take a lot of optional user input.
Seems the options are emacs widgets which is built in or using something like magit popups
which allows the user to selectively enter values.

I will focus on emacs widgets because some of the input could be quite large.
 
** Getting started
To get started creating your blog first install nikola with pip or use the docker container, then run =nikola init= to create your new blog.

#+BEGIN_SRC emacs-lisp :results silent
  (require 'widget)

  (eval-when-compile
    (require 'wid-edit))

  (defun widget-example-01 ()
    "Create the widgets from the Widget manual."
    (interactive)
    ;; create a new buffer and wrap all commands in buffer context
    (with-current-buffer (switch-to-buffer "Widget Test 1")

    ;; Reset back to defaults
    (kill-all-local-variables)
    (make-local-variable 'widget-example-repeat)

    ;; Clean up buffers
    (let ((inhibit-read-only t))
      (erase-buffer))
    
    ;; Insert description text into buffer
    (widget-insert "Fill in the form below\n\n")

    ;; Create our first widget with a text label
    (widget-insert "Server Name: ")
    (widget-create 'editable-field
                   :size 13
                   "Replace Me")
    (widget-insert "\n----\n")


    ;; Modify the current buffer to work with widgets
    (widget-setup)))
#+END_SRC

#+RESULTS:
: widget-example-01

** Adding submit and reset buttons

#+BEGIN_SRC emacs-lisp
  (require 'widget)

  (eval-when-compile
    (require 'wid-edit))

  (defvar widget-example-repeat)

  (defun widget-example-02 ()
    "Create the widgets from the Widget manual."
    (interactive)
    (with-current-buffer (switch-to-buffer "Widget Test 2")
    (kill-all-local-variables)
    (make-local-variable 'widget-example-repeat)
    (let ((inhibit-read-only t))
      (erase-buffer))
    (widget-insert "Fill in the form below\n\n")
    (widget-insert "Server Name: ")
    (widget-create 'editable-field
                   :size 13
                   "Replace Me")
    (widget-insert "\n----\n")

    (widget-create 'push-button
                   :notify (lambda (&rest ignore) 
                             (if (= (length (widget-value widget-example-repeat))
                                    3)
                                 (message "Congratulation!")
                               (error "Three was the count!")))
                   "Apply Form")
    (widget-insert " ")
    (widget-create 'push-button
                   :notify (lambda (&rest ignore)
                             (widget-example))
                   "Reset Form")
    (widget-insert "\n----\n")

    (widget-setup)))
#+END_SRC

#+RESULTS:
: widget-example-02

#+BEGIN_SRC emacs-lisp
  (require 'widget)

  (eval-when-compile
    (require 'wid-edit))

  (defvar widget-example-repeat)


  (defun widget-example ()
    "Create the widgets from the Widget manual."
    (interactive)
    (switch-to-buffer "*Digitalocean*")
    (kill-all-local-variables)
    (make-local-variable 'widget-example-repeat)
    (let ((inhibit-read-only t))
      (erase-buffer))
    (widget-insert "Digitalocean droplet creation")
    (widget-insert "Name: ")
    (widget-create 'editable-field
                   :size 13
                   "My Name")
    (widget-insert "Region: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Region")
    (widget-insert "Size: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Size")
    (widget-insert "Image: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Image")

    (widget-insert "Image: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Image")
    (widget-insert "Image: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Image")
    (widget-insert "Image: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Image")
    (widget-insert "Image: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Image")
    (widget-insert "Image: ")
    (widget-create 'editable-field
                   :size 13
                   "Your Image")

    (widget-create 'menu-choice
                   :tag "Choose"
                   :value "This"
                   :help-echo "Choose me, please!"
                   :notify (lambda (widget &rest ignore)
                             (message "%s is a good choice!"
                                      (widget-value widget)))
                   '(item :tag "This option" :value "This")
                   '(choice-item "That option")
                   '(editable-field :menu-tag "No option" "Thus option"))
    (widget-insert "Address: ")
    (widget-create 'editable-field
                   "Some Place\nIn some City\nSome country.")
    (widget-insert "\nSee also ")
    (widget-create 'link
                   :notify (lambda (&rest ignore)
                             (widget-value-set widget-example-repeat 
                                               '("En" "To" "Tre"))
                             (widget-setup))
                   "other work")
    (widget-insert " for more information.\n\nNumbers: count to three below\n")
    (setq widget-example-repeat
          (widget-create 'editable-list
                         :entry-format "%i %d %v"
                         :notify (lambda (widget &rest ignore)
                                   (let ((old (widget-get widget
                                                          ':example-length))
                                         (new (length (widget-value widget))))
                                     (unless (eq old new)
                                       (widget-put widget ':example-length new)
                                       (message "You can count to %d." new))))
                         :value '("One" "Eh, two?" "Five!")
                         '(editable-field :value "three")))
    (widget-insert "\n\nSelect multiple:\n\n")
    (widget-create 'checkbox t)
    (widget-insert " This\n")
    (widget-create 'checkbox nil)
    (widget-insert " That\n")
    (widget-create 'checkbox
                   :notify (lambda (&rest ignore) (message "Tickle"))
                   t)
    (widget-insert " Thus\n\nSelect one:\n\n")
    (widget-create 'radio-button-choice
                   :value "One"
                   :notify (lambda (widget &rest ignore)
                             (message "You selected %s"
                                      (widget-value widget)))
                   '(item "One") '(item "Another One.") '(item "A Final One."))
    (widget-insert "\n")
    (widget-create 'push-button
                   :notify (lambda (&rest ignore) 
                             (if (= (length (widget-value widget-example-repeat))
                                    3)
                                 (message "Congratulation!")
                               (error "Three was the count!")))
                   "Apply Form")
    (widget-insert " ")
    (widget-create 'push-button
                   :notify (lambda (&rest ignore)
                             (widget-example))
                   "Reset Form")
    (widget-insert "\n")
    (use-local-map widget-keymap)
    (widget-setup))
#+END_SRC
