#+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