2023-03-01 Emacs widget for my literature list This is an update to my phlog post "AWK replaces LibreCalc"[1] where I describe how I use Awk to view, sort and filter my literature list (a basic csv-file). This works great but manually adding new books to the list is a bit cumbersome. I always wanted to make use of the Emacs widget library[2] and this was the perfect opportunity. So I created a simple widget containing editable-input fields corresponding to the column header of the csv-file. Then I added one button to append the data row to the file and one to reset the form. This was fun because - I learned how to use the widget library - I learned about buffer-local variables[3] - I came up with an elegant way to check if a list of variables is defined (look for boundp in the source) - I could use a macro to refactor the code Code ~~~~ (require 'widget) (defmacro sulaco/generate-field-widget (VAR LENGTH) `(progn (widget-insert (format "%s:\n" ,(capitalize VAR))) (widget-create 'editable-field :size ,LENGTH :notify (lambda (this &rest ignore) (setq-local ,(intern VAR) (widget-value this)))) (widget-insert "\n"))) (defun sulaco/add-book () "Create a widget to append a new entry to literaturliste.csv." (interactive) (if (not (get-buffer "*Add Book Form*")) (progn (switch-to-buffer "*Add Book Form*") (kill-all-local-variables) (let ((inhibit-read-only t)) (erase-buffer)) (sulaco/generate-field-widget "author" 60) (sulaco/generate-field-widget "title" 60) (sulaco/generate-field-widget "year" 5) (sulaco/generate-field-widget "language" 20) (sulaco/generate-field-widget "epoch" 20) (sulaco/generate-field-widget "type" 20) (sulaco/generate-field-widget "date-read" 20) (sulaco/generate-field-widget "annotation" 60) (widget-insert "\n") (widget-create 'push-button :notify (lambda (&rest ignore) (let ((output-line (mapconcat (lambda (x) (if (boundp x) (symbol-value x) "")) '(author title year language epoch type date-read annotation) "\t"))) (append-to-file (concat output-line "\n") nil "~/Dokumente/literaturliste.csv"))) "Add book") (widget-create 'push-button :notify (lambda (&rest ignore) (progn (kill-buffer (current-buffer)) (sulaco/add-book))) "Reset Form") (use-local-map widget-keymap) (widget-setup) (goto-char 9)) ;; else (switch-to-buffer "*Add Book Form*"))) Screenshot ~~~~~~~~~~ Author: ____________________________________ Title: ____________________________________ Year: _____ Language: ______________________ Epoch: ______________________ Type: ______________________ Date-Read: ______________________ Annotation: ____________________________________ [Add book][Reset Form] U:@**- *Add Book Form* All (2,0) (Fundamental) Footnotes ~~~~~~~~~ [1] gopher://tilde.club/0/~sulaco/phlog/9993-2023-02-12-AWK_replaces_LibreCalc [2] https://www.gnu.org/software/emacs/manual/html_mono/widget.html or C-h i s widget RET RET [3] https://www.gnu.org/software/emacs/manual/html_node/elisp/Buffer_002dLocal-Variables.html or C-h i s elisp RET RET s buffer-local RET RET