elisp/stack-mode/checklist.el
changeset 80 e848f1863d6b
equal deleted inserted replaced
79:f3334abf4322 80:e848f1863d6b
       
     1 ;;; checklist.el --- Simple checklist UI functionality
       
     2 
       
     3 ;; Copyright (c) 2015 Chris Done. All rights reserved.
       
     4 
       
     5 ;; This file is free software; you can redistribute it and/or modify
       
     6 ;; it under the terms of the GNU General Public License as published by
       
     7 ;; the Free Software Foundation; either version 3, or (at your option)
       
     8 ;; any later version.
       
     9 
       
    10 ;; This file is distributed in the hope that it will be useful,
       
    11 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    13 ;; GNU General Public License for more details.
       
    14 
       
    15 ;; You should have received a copy of the GNU General Public License
       
    16 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
       
    17 
       
    18 ;;; Code:
       
    19 
       
    20 (defvar checklist-read-checklist-result nil)
       
    21 (make-variable-buffer-local 'checklist-read-checklist-result)
       
    22 
       
    23 (defun checklist-read-checklist (prompt choices)
       
    24   "Prompt with PROMPT to choose one or more from the list of CHOICES."
       
    25   (switch-to-buffer (generate-new-buffer-name "checklist"))
       
    26   (let ((inhibit-read-only t))
       
    27     (special-mode)
       
    28     (setq buffer-read-only t)
       
    29     (setq cursor-type 'box)
       
    30     (insert (concat prompt "\n\n"))
       
    31     (use-local-map (copy-keymap special-mode-map))
       
    32     (local-set-key "n" 'next-line)
       
    33     (local-set-key "p" 'previous-line)
       
    34     (local-set-key (kbd "RET") 'checklist-checklist-choose)
       
    35     (local-set-key (kbd "SPC") 'checklist-checklist-choose)
       
    36     (local-set-key (kbd "C-c C-c") 'checklist-checklist-done)
       
    37     (save-excursion
       
    38       (cl-loop for choice in choices
       
    39                do (insert (propertize (concat "[ ] " (cdr choice) "\n")
       
    40                                       'checklist-check-item (car choice))))
       
    41       (insert "\n")
       
    42       (insert "Hit " (propertize "C-c C-c" 'face 'bold) " to finish."))
       
    43     (add-hook 'post-command-hook #'checklist-highlight-section t t)
       
    44     (setq checklist-read-checklist-result nil)
       
    45     (recursive-edit)
       
    46     (let ((result  checklist-read-checklist-result)
       
    47           (kill-buffer-query-functions nil))
       
    48       (kill-buffer (current-buffer))
       
    49       result)))
       
    50 
       
    51 (defun checklist-checklist-done ()
       
    52   "Done with the checklist, return the result."
       
    53   (interactive)
       
    54   (throw 'exit nil))
       
    55 
       
    56 (defun checklist-highlight-section ()
       
    57   "Highlight the item at point."
       
    58   (remove-overlays)
       
    59   (when (get-text-property (point) 'checklist-check-item)
       
    60     (let ((o (make-overlay (line-beginning-position)
       
    61                            (1+ (line-end-position)))))
       
    62       (overlay-put o 'face 'secondary-selection))))
       
    63 
       
    64 (defun checklist-checklist-choose ()
       
    65   "Choose the current item at point."
       
    66   (interactive)
       
    67   (let ((inhibit-read-only t)
       
    68         (checked (get-text-property (point) 'checklist-item-checked)))
       
    69     (when (get-text-property (point) 'checklist-check-item)
       
    70       (if checked
       
    71           (setq checklist-read-checklist-result
       
    72                 (delete (get-text-property (point) 'checklist-check-item)
       
    73                         checklist-read-checklist-result))
       
    74           (add-to-list 'checklist-read-checklist-result
       
    75                        (get-text-property (point) 'checklist-check-item)
       
    76                        t))
       
    77       (save-excursion (goto-char (line-beginning-position))
       
    78                       (delete-region (line-beginning-position)
       
    79                                      (+ (line-beginning-position) (length "[ ]")))
       
    80                       (if checked
       
    81                           (insert "[ ]")
       
    82                         (insert "[x]")))
       
    83       (put-text-property (line-beginning-position)
       
    84                          (1+ (line-end-position))
       
    85                          'checklist-item-checked (not checked))
       
    86       (put-text-property (line-beginning-position)
       
    87                          (1+ (line-end-position))
       
    88                          'face (if checked nil 'bold))
       
    89       (put-text-property (line-beginning-position)
       
    90                          (1+ (line-end-position))
       
    91                          'checklist-check-item t)
       
    92       (checklist-highlight-section))))
       
    93 
       
    94 (provide 'checklist)