changelog shortlog graph tags branches files raw help

Mercurial > core / changeset: emacs config

changeset 39: e87c995efea1
parent 38: a4186c03d6cf
child 40: 222de63be8ed
author: ellis <ellis@rwest.io>
date: Tue, 07 Nov 2023 18:50:41 -0500
files: emacs/ellis.el emacs/keys.el emacs/lib/sk.el
description: emacs config
     1.1--- a/emacs/ellis.el	Mon Nov 06 22:49:52 2023 -0500
     1.2+++ b/emacs/ellis.el	Tue Nov 07 18:50:41 2023 -0500
     1.3@@ -28,10 +28,26 @@
     1.4 (enable-paredit-mode)
     1.5 (repeat-mode)
     1.6 
     1.7+(keymap-global-set "C-<tab>" #'hippie-expand)
     1.8+(keymap-set minibuffer-local-map "C-<tab>" #'hippie-expand)
     1.9+
    1.10+(require 'sk)
    1.11+
    1.12+(add-hook 'prog-mode-hook #'skt-mode)
    1.13+(add-hook 'org-mode-hook #'skt-mode)
    1.14+
    1.15+(setopt skt-enable-tempo-elements t
    1.16+        skt-completing-read t
    1.17+        skt-delete-duplicate-marks t)
    1.18+
    1.19+(keymap-set skt-mode-map "C-c M-b" #'tempo-backward-mark)
    1.20+(keymap-set skt-mode-map "C-c M-f" #'tempo-forward-mark)
    1.21+(keymap-set skt-mode-map "C-c M-a" #'tempo-complete-tag)
    1.22+
    1.23 (use-package notmuch 
    1.24   :ensure t
    1.25   :custom 
    1.26-  notmuch-init-file "~/.notmuch-config"
    1.27+  ;; notmuch-init-file "~/.notmuch-config"
    1.28   mail-user-agent 'message-user-agent
    1.29   smtpmail-smtp-server "smtp.gmail.com"
    1.30   message-send-mail-function 'message-smtpmail-send-it
    1.31@@ -97,5 +113,20 @@
    1.32 (use-package sh-script
    1.33   :hook (sh-mode . flymake-mode))
    1.34 
    1.35+(use-package tempo
    1.36+  :custom
    1.37+  tempo-interactive t
    1.38+  :config
    1.39+  (tempo-define-template 
    1.40+   "org:readme"
    1.41+   '("#+TITLE: " p n>
    1.42+     "#+AUTHOR: " user-full-name " <" user-mail-address ">" n>)
    1.43+   "org:readme"
    1.44+   "Insert a readme.org file template.")
    1.45+  (tempo-define-template "org:src"
    1.46+                         '("#+begin_src " p n>
    1.47+                           "#+end_src" n>)
    1.48+                         "org:src"))
    1.49+
    1.50 (provide 'ellis)
    1.51 ;;; ellis.el ends here
     2.1--- a/emacs/keys.el	Mon Nov 06 22:49:52 2023 -0500
     2.2+++ b/emacs/keys.el	Tue Nov 07 18:50:41 2023 -0500
     2.3@@ -12,6 +12,7 @@
     2.4 
     2.5 ;;; User keys
     2.6 ;; paredit-map
     2.7+(require 'default)
     2.8 (defvar-keymap parens-map
     2.9   :doc "parens-minor-mode keymap."
    2.10   :repeat (:enter)
     3.1--- a/emacs/lib/sk.el	Mon Nov 06 22:49:52 2023 -0500
     3.2+++ b/emacs/lib/sk.el	Tue Nov 07 18:50:41 2023 -0500
     3.3@@ -1,8 +1,8 @@
     3.4 ;;; sk.el --- skel Emacs Mode -*- lexical-binding: t; -*-
     3.5 
     3.6-;; skel-mode and friends
     3.7+;; skel-mode, skt-mode, sk-classes
     3.8 
     3.9-;; Copyright (C) 2023  anticorp
    3.10+;; Copyright (C) 2023  The Compiler Company
    3.11 
    3.12 ;; Author: ellis <ellis@rwest.io>
    3.13 ;; Keywords: languages, lisp
    3.14@@ -22,19 +22,13 @@
    3.15 
    3.16 ;;; Commentary:
    3.17 
    3.18-;; TODO
    3.19-
    3.20-;; - auto-insert
    3.21-;; - skeleton
    3.22-;; - tempo
    3.23-;; - d/abbrevs
    3.24-
    3.25 ;;; Code:
    3.26 
    3.27 (eval-and-compile (require 'eieio)
    3.28 		  (require 'cl-lib)
    3.29-		  (require 'fu (expand-file-name "lisp/fu" user-emacs-directory))
    3.30-		  (require 'sxp (expand-file-name "sxp/sxp" user-dev-directory))
    3.31+		  (require 'sxp (expand-file-name "sxp.el" (join-paths user-emacs-directory "lib/")))
    3.32+                  (require 'skeleton)
    3.33+                  (require 'tempo)
    3.34 		  (defvar skel-debug nil)
    3.35 		  (when skel-debug (require 'ede)))
    3.36 
    3.37@@ -75,7 +69,6 @@
    3.38 (define-derived-mode skel-mode lisp-data-mode "SKEL"
    3.39   "skel-mode")
    3.40 
    3.41-
    3.42 (defun maybe-skel-minor-mode ()
    3.43   "Check the current environment and determine if `skel-minor-mode' should
    3.44 be enabled. This function is added as a hook to
    3.45@@ -142,5 +135,414 @@
    3.46   (add-to-list 'auto-mode-alist '("skelfile" . skel-mode))
    3.47   (add-to-list 'auto-mode-alist '("\\.sk\\'" . skel-mode)))
    3.48 
    3.49+;;; Autotype
    3.50+;; From: https://github.com/xFA25E/skempo/blob/master/skempo.el
    3.51+(defun modify-lisp-syntax-tables ()
    3.52+  (modify-syntax-entry ?* "w" (syntax-table))
    3.53+  (modify-syntax-entry ?- "w" (syntax-table)))
    3.54+
    3.55+(dolist (hook '(lisp-mode-hook emacs-lisp-mode-hook))
    3.56+  (add-hook hook #'modify-lisp-syntax-tables))
    3.57+
    3.58+(defun skt--tags-variable (mode)
    3.59+  "Return a tempo tags variable's symbol for MODE."
    3.60+  (when mode
    3.61+    (intern (replace-regexp-in-string
    3.62+             (rx "-mode" eos) "-skt-tags"
    3.63+             (symbol-name mode)))))
    3.64+
    3.65+(defun skt--remove-tag-list (tag-list)
    3.66+  "Remove TAG-LIST from `tempo-local-tags'."
    3.67+  (setf (alist-get tag-list tempo-local-tags nil t) nil))
    3.68+
    3.69+(defun skt--insert-mark (marker)
    3.70+  "Insert a MARKER to `tempo-marks' while keeping it sorted.
    3.71+Remove duplicate marks from `tempo-marks'.  Set to nil removed
    3.72+markers.  This function is used as an :override advice to
    3.73+`tempo-insert-mark', because the original function does not
    3.74+remove duplicate elements.  Duplicate markers appear when the
    3.75+buffer gets smaller, markers start pointing to the same location.
    3.76+We don't want that, because a lot of useless markers can slow
    3.77+down Emacs."
    3.78+  (if (not tempo-marks)
    3.79+      (setq tempo-marks (list marker))
    3.80+    (let ((markers tempo-marks))
    3.81+      (cond
    3.82+       ((< marker (car markers))
    3.83+        (setq tempo-marks (cons marker tempo-marks)))
    3.84+       (t
    3.85+        (while (and (cdr markers) (<= (cadr markers) marker))
    3.86+          (if (/= (car markers) (cadr markers))
    3.87+              (setq markers (cdr markers))
    3.88+            (when (markerp (cadr markers)) (set-marker (cadr markers) nil))
    3.89+            (setcdr markers (cddr markers))))
    3.90+
    3.91+        (if (= marker (car markers))
    3.92+            (when (markerp marker) (set-marker marker nil))
    3.93+          (setcdr markers (cons marker (cdr markers))))))
    3.94+
    3.95+      (while (cdr markers)
    3.96+        (if (/= (car markers) (cadr markers))
    3.97+            (setq markers (cdr markers))
    3.98+          (when (markerp (cadr markers)) (set-marker (cadr markers) nil))
    3.99+          (setcdr markers (cddr markers)))))))
   3.100+
   3.101+(defun skt--add-tag (tag template &optional tag-list)
   3.102+  "Add a TEMPLATE TAG to TAG-LIST or to `tempo-tags'.
   3.103+It is an :override function for `tempo-add-tag'.  The original
   3.104+function does not update identical tags."
   3.105+  (interactive "sTag: \nCTemplate: ")
   3.106+  (let ((tag-list (or tag-list 'tempo-tags)))
   3.107+    (if-let ((value (assoc tag (symbol-value tag-list))))
   3.108+        (setcdr value template)
   3.109+      (set tag-list (cons (cons tag template) (symbol-value tag-list))))
   3.110+    (tempo-invalidate-collection)))
   3.111+
   3.112+(defun skt--list-derived-modes (mode)
   3.113+  "List all derived modes of MODE + MODE itself."
   3.114+  (let ((modes nil))
   3.115+    (while mode
   3.116+      (when-let ((alias (symbol-function mode)))
   3.117+        (when (symbolp alias)
   3.118+          (setq mode alias)))
   3.119+      (push mode modes)
   3.120+      (setq mode (get mode 'derived-mode-parent))  )
   3.121+    (nreverse modes)))
   3.122+
   3.123+;;; Commands
   3.124+
   3.125+(defvar-keymap skt-mode-map
   3.126+  :doc "skt-mode keymap."
   3.127+  :repeat (:enter))
   3.128+
   3.129+(define-minor-mode skt-mode
   3.130+  "Minor mode for skt-templates."
   3.131+  :init-value nil
   3.132+  :lighter " Skt"
   3.133+  :keymap skt-mode-map
   3.134+  (let* ((modes (skt--list-derived-modes major-mode))
   3.135+         (tag-vars (mapcar #'skt--tags-variable modes))
   3.136+         (bound-tag-vars (cl-delete-if-not #'boundp tag-vars)))
   3.137+    (if skt-mode
   3.138+        (mapc #'tempo-use-tag-list bound-tag-vars)
   3.139+      (mapc #'skt--remove-tag-list bound-tag-vars))))
   3.140+
   3.141+(defun skt--define-tempo (function-symbol body &optional docstring)
   3.142+  "Define a tempo template with BODY.
   3.143+This will generate a function with FUNCTION-SYMBOL and
   3.144+DOCSTRING.
   3.145+
   3.146+The main purpose of this function is to have a better controlled
   3.147+alternative to `tempo-define-template'."
   3.148+  (let ((template-symbol (gensym (symbol-name function-symbol))))
   3.149+    (set template-symbol body)
   3.150+    (defalias function-symbol
   3.151+      (lambda (&optional arg)
   3.152+        (interactive "*P")
   3.153+        (tempo-insert-template template-symbol (xor tempo-insert-region arg)))
   3.154+      docstring)))
   3.155+
   3.156+(defun skt--define-skeleton (function-symbol body &optional docstring)
   3.157+  "Define a skeleton template with BODY.
   3.158+This will generate a function with FUNCTION-SYMBOL and
   3.159+DOCSTRING.
   3.160+
   3.161+The main purpose of this function is to have a better controlled
   3.162+alternative to `define-skeleton', especially because it is a
   3.163+function instead of a macro."
   3.164+  (defalias function-symbol
   3.165+    (lambda (&optional str arg)
   3.166+      (interactive "*P\nP")
   3.167+      (skeleton-proxy-new body str arg))
   3.168+    docstring))
   3.169+
   3.170+(defun skt--define-function (function-symbol function &optional docstring)
   3.171+  "This will generate an alias to FUNCTION with FUNCTION-SYMBOL.
   3.172+DOCSTRING is used as a docstring to FUNCTION-SYMBOL."
   3.173+  (defalias function-symbol function docstring))
   3.174+
   3.175+(defun skt--mode-name (mode)
   3.176+  "Get MODE name without a -mode suffix."
   3.177+  (string-trim-right (symbol-name mode) (rx "-mode" eos)))
   3.178+
   3.179+(defun skt--function-name (name modes)
   3.180+  "Generate a name for a skt template function.
   3.181+NAME and MODES are used to generate unique, but consistent
   3.182+names."
   3.183+  (concat "skt-template-"
   3.184+          (mapconcat (lambda (mode) (concat (skt--mode-name mode) "-"))
   3.185+                     (sort modes #'string<) "")
   3.186+          name))
   3.187+
   3.188+(defun skt--mode-abbrev-table (mode)
   3.189+  "Get abbrev table for MODE or `global-abbrev-table' if nil."
   3.190+  (if mode
   3.191+      (derived-mode-abbrev-table-name mode)
   3.192+    'global-abbrev-table))
   3.193+
   3.194+(defun skt--abbrev-table (mode)
   3.195+  "Get skt abbrev table for MODE."
   3.196+  (intern (concat "skt-" (symbol-name (skt--mode-abbrev-table mode)))))
   3.197+
   3.198+(defun skt--abbrev-table-names (table)
   3.199+  "Return abbrev TABLE names."
   3.200+  (let ((names nil))
   3.201+    (mapatoms (lambda (abbrev)
   3.202+                (when (symbol-value abbrev)
   3.203+                  (push (symbol-name abbrev) names)))
   3.204+              (symbol-value table))
   3.205+    names))
   3.206+
   3.207+(defun skt--modes (mode)
   3.208+  "Normalize MODE argument."
   3.209+  (cond ((consp mode) mode)
   3.210+        ((null mode) nil)
   3.211+        ((symbolp mode) (list mode))))
   3.212+
   3.213+;;;###autoload
   3.214+(defun skt-define (define-function name modes tag abbrev docstring body)
   3.215+  "Define a skt template.
   3.216+
   3.217+DEFINE-FUNCTION is a function that takes a function symbol, BODY
   3.218+and DOCSTRING as its arguments.  It must define a new function
   3.219+with that symbol and that docstring.
   3.220+
   3.221+NAME is a string used in generating a function symbol, TAG and
   3.222+ABBREV.
   3.223+
   3.224+MODES is a list of modes for which TAG and ABBREV will be
   3.225+created.  If it's nil, TAG and ABBREV will be generated
   3.226+globally.
   3.227+
   3.228+TAG/ABBREV is a boolean, which indicates whether a tag/abbrev
   3.229+must be created for this template.
   3.230+
   3.231+DOCSTRING is a string (or nil) which will be supplied to
   3.232+DEFINE-FUNCTION.
   3.233+
   3.234+BODY is an arbitrary argument passed to DEFINE-FUNCTION."
   3.235+  (let* ((function-symbol (intern (skt--function-name name modes)))
   3.236+         (modes (or modes '(nil))))
   3.237+    (funcall define-function function-symbol body docstring)
   3.238+    (put function-symbol 'no-self-insert t)
   3.239+
   3.240+    (when tag
   3.241+      (let ((tag-symbol (gensym (symbol-name function-symbol))))
   3.242+        (if (eq #'skt--define-tempo define-function)
   3.243+            (set tag-symbol body)
   3.244+          (set tag-symbol `((ignore (,function-symbol)))))
   3.245+        (dolist (mode modes)
   3.246+          (let ((var (skt--tags-variable mode)))
   3.247+            (unless (boundp var)
   3.248+              (set var nil))
   3.249+            (tempo-add-tag name tag-symbol var)))
   3.250+        (dolist (buffer (buffer-list))
   3.251+          (with-current-buffer buffer
   3.252+            (when (and (or (equal '(nil) modes) (apply #'derived-mode-p modes))
   3.253+                       skt-mode)
   3.254+              (skt-mode -1)
   3.255+              (skt-mode 1))))))
   3.256+
   3.257+    (when abbrev
   3.258+      (dolist (mode modes)
   3.259+        (let ((mode-table (skt--mode-abbrev-table mode))
   3.260+              (table (skt--abbrev-table mode)))
   3.261+          (define-abbrev-table mode-table nil)
   3.262+          (define-abbrev-table table nil :case-fixed t :skt t)
   3.263+          (define-abbrev (symbol-value table) name "" function-symbol
   3.264+            :case-fixed t :system t :skt t)
   3.265+
   3.266+          (let* ((names (skt--abbrev-table-names table))
   3.267+                 (regexp (concat (regexp-opt names "\\_<\\(") " *")))
   3.268+            (abbrev-table-put (symbol-value table) :regexp regexp))
   3.269+
   3.270+          (let ((parents (abbrev-table-get (symbol-value mode-table) :parents)))
   3.271+            (cl-pushnew (symbol-value table) parents :test #'eq)
   3.272+            (abbrev-table-put (symbol-value mode-table) :parents parents)))))
   3.273+
   3.274+    function-symbol))
   3.275+
   3.276+;;;###autoload
   3.277+(cl-defmacro skt-define-tempo (name (&key mode tag abbrev docstring) &rest body)
   3.278+  "Define a tempo template.
   3.279+This macro defines a new tempo template or updates the old one.
   3.280+NAME is a symbol.  ARGS is a list of the form ([KEY VALUE]...)
   3.281+where each KEY can be one of :tag, :abbrev, :docstring or :mode.
   3.282+
   3.283+If KEY is :tag, VALUE should be a boolean.  If VALUE is non-nil,
   3.284+then a tempo tag with NAME will be created for this template.
   3.285+
   3.286+If KEY is :abbrev, VALUE should be a boolean.  If VALUE is
   3.287+non-nil, then a NAME abbrev will be created for this template.
   3.288+
   3.289+If KEY is :docstring, VALUE should be a string.  It will be a
   3.290+docstring of the generated function.
   3.291+
   3.292+If KEY is :mode, VALUE should be a list of modes or single mode.
   3.293+If this option is provided, than a tempo tag and an abbrev will
   3.294+be created for these modes, otherwise they will be global (if
   3.295+:tag and :abbrev options were provided, of course).
   3.296+
   3.297+BODY is a sequence of tempo elements that will be passed as a
   3.298+list directly to `tempo-define-template's second argument.
   3.299+
   3.300+Example:
   3.301+\(skt-define-tempo defvar (:mode `emacs-lisp-mode' :tag t :abbrev t
   3.302+                             :docstring \"defvar template\")
   3.303+  \"(defvar \" (string-trim-right (buffer-name) (rx \".el\" eos)) \"-\" p n>
   3.304+  r> \")\")"
   3.305+  `(skt-define #'skt--define-tempo ,(symbol-name name)
   3.306+                  ',(skt--modes mode) ,tag ,abbrev ,docstring ',body))
   3.307+
   3.308+;;;###autoload
   3.309+(cl-defmacro skt-define-skeleton (name (&key mode tag abbrev docstring) &rest body)
   3.310+  "Define skeleton template.
   3.311+See `skt-define-tempo' for explanation of NAME, MODE, TAG,
   3.312+ABBREV and DOCSTRING.
   3.313+
   3.314+BODY is a sequence of skeleton elements that will be passed
   3.315+directly to `define-skeleton'.
   3.316+
   3.317+Example:
   3.318+\(skt-define-skeleton defun (:mode (emacs-lisp-mode `lisp-interaction-mode')
   3.319+                               :tag t :abbrev t
   3.320+                               :docstring \"defun template\")
   3.321+  \"(defun \" str \" (\" @ - \")\" \n
   3.322+  @ _ \")\" \n)"
   3.323+  `(skt-define #'skt--define-skeleton ,(symbol-name name)
   3.324+                  ',(skt--modes mode) ,tag ,abbrev ,docstring ',body))
   3.325+
   3.326+;;;###autoload
   3.327+(cl-defmacro skt-define-function (name (&key mode tag abbrev docstring) function)
   3.328+  "Define FUNCTION template.
   3.329+See `skt-define-tempo' for explanation of NAME, MODE, TAG,
   3.330+ABBREV and DOCSTRING.
   3.331+
   3.332+The main purpose of this macro, is to create tempo tags and
   3.333+abbrevs for existing skeleton templates, such as `sh-case'.
   3.334+
   3.335+Example:
   3.336+\(skt-define-function shcase (:tag t :abbrev t :mode `sh-mode') `sh-case')"
   3.337+  `(skt-define #'skt--define-function ,(symbol-name name)
   3.338+                  ',(skt--modes mode) ,tag ,abbrev ,docstring ',function))
   3.339+
   3.340+(defun skt--complete-template (string tag-list)
   3.341+  "An :override advice function for `tempo-display-completions'.
   3.342+Show completion for STRING in a TAG-LIST.  After selection
   3.343+expand template.
   3.344+
   3.345+Rewritten because the original function uses an old way of
   3.346+displaying completions in a separate buffer, which is not
   3.347+clickable anyway.  Now it uses new (compared to the originial
   3.348+tempo package) and shiny `completing-read' interface."
   3.349+  (let* ((tags (mapcar #'car tag-list))
   3.350+         (tag (completing-read "Skt: " tags nil t string)))
   3.351+    (delete-char (- (length string)))
   3.352+    (tempo-insert-template (cdr (assoc tag tag-list)) nil)))
   3.353+
   3.354+;;;###autoload
   3.355+(defcustom skt-enable-tempo-elements nil
   3.356+  "Enable extra tempo elements.
   3.357+These elements add conditionals and looping support for tempo
   3.358+like those in skeleton, making skeleton pretty much obsolete.
   3.359+
   3.360+If you want to set this option from ELisp, you have to remove
   3.361+`skt-tempo-user-elements' from `tempo-user-elements' on nil
   3.362+and add it on non-nil."
   3.363+  :type '(boolean :tag "Enable tempo elements?")
   3.364+  :set (lambda (variable value)
   3.365+         (if value
   3.366+             (add-hook 'tempo-user-elements #'skt-tempo-user-elements)
   3.367+           (remove-hook 'tempo-user-elements #'skt-tempo-user-elements))
   3.368+         (set-default variable value))
   3.369+  :group 'skel)
   3.370+
   3.371+(defcustom skt-completing-read nil
   3.372+  "Override default `tempo-display-completions'.
   3.373+By default it uses a completion buffer to show completions.  This
   3.374+option overrides this function to use `completing-read' to select
   3.375+partial skempo tag or complete tag on region.
   3.376+
   3.377+If you wish to set this variable from ELisp code, you have to
   3.378+remove `skt--complete-template' advice from
   3.379+`tempo-display-completions' on nil and add it as on :override
   3.380+advice on non-nil."
   3.381+  :type '(boolean :tag "Override?")
   3.382+  :set (lambda (variable value)
   3.383+         (if value
   3.384+             (advice-add 'tempo-display-completions :override #'skt--complete-template)
   3.385+           (advice-remove 'tempo-display-completions #'skt--complete-template))
   3.386+         (set-default variable value))
   3.387+  :group 'skel)
   3.388+
   3.389+(defcustom skempo-delete-duplicate-marks nil
   3.390+  "Override default `tempo-insert-mark'.
   3.391+Marks are used to jump on points of interest in a template.  By
   3.392+default `tempo-insert-mark' does not remove duplicate marks.
   3.393+Duplicate marks might appear when the buffer shrinks and some of
   3.394+the marks start pointing to the same location.  This option tries
   3.395+to fix this by checking for duplicate marks every time the
   3.396+function is called.  Emacs might get slower with a lot of
   3.397+marks.
   3.398+
   3.399+If you want to set this option from ELisp, you have to remove
   3.400+`skt--insert-mark' advice from `tempo-insert-mark' on nil and
   3.401+add it as on :override advice on non-nil."
   3.402+  :type '(boolean :tag "Override?")
   3.403+  :set (lambda (variable value)
   3.404+         (if value
   3.405+             (advice-add 'tempo-insert-mark :override #'skt--insert-mark)
   3.406+           (advice-remove 'tempo-insert-mark #'skt--insert-mark))
   3.407+         (set-default variable value))
   3.408+  :group 'skel)
   3.409+
   3.410+(progn
   3.411+  (put 'skt-define-tempo 'lisp-indent-function 2)
   3.412+  (put 'skt-define-skeleton 'lisp-indent-function 2)
   3.413+  (put 'skt-define-function 'lisp-indent-function 2))
   3.414+
   3.415+;;; Tempo Elements
   3.416+(defvar skt-tempo-else-key (kbd "C-M-g")
   3.417+  "Key used to execute else branch in tempo conditional.")
   3.418+
   3.419+(defun skt-tempo--prompt (prompt)
   3.420+  "Make prompt for tempo conditional.
   3.421+PROMPT is preceded with `skt-tempo-else-key'."
   3.422+  (concat "(" (key-description skt-tempo-else-key) " to quit) " prompt))
   3.423+
   3.424+(defun skt-tempo-user-elements (element)
   3.425+  "Support for conditional and looping tempo elements.
   3.426+The following forms are supported for ELEMENT:
   3.427+
   3.428+\(:if (PROMPT VAR) THEN ELSE)
   3.429+
   3.430+\(:when (PROMPT VAR) BODY...)
   3.431+
   3.432+\(:while (PROMPT VAR) BODY...)
   3.433+
   3.434+PROMPT is a string used to read value for VAR.  VAR is a tempo
   3.435+variable symbol.  Its value can be read with s, as usual.  BODY,
   3.436+THEN and ELSE are tempo elements.  To abort the execution of
   3.437+these elements, user must press `skt-tempo-else-key'.
   3.438+
   3.439+The main purpose of this extension is to mimic skeleton
   3.440+conditionals and iterative templats.  Skeleton becomes pretty
   3.441+much obsolete with this extension."
   3.442+  (pcase element
   3.443+    (`(:if (,(and (pred stringp) prompt) ,(and (pred symbolp) var)) ,then ,else)
   3.444+     (let ((prompt (skt-tempo--prompt prompt))
   3.445+           (map (make-sparse-keymap)))
   3.446+       (set-keymap-parent map minibuffer-local-map)
   3.447+       (define-key map skt-tempo-else-key
   3.448+         (lambda () (interactive) (throw 'else else)))
   3.449+       (catch 'else
   3.450+         (tempo-save-named var (read-from-minibuffer prompt nil map))
   3.451+         then)))
   3.452+    (`(:when (,(and (pred stringp) prompt) ,(and (pred symbolp) var)) . ,body)
   3.453+     `(:if (,prompt ,var) (l ,@body) (l)))
   3.454+    (`(:while (,(and (pred stringp) prompt) ,(and (pred symbolp) var)) . ,body)
   3.455+     `(:when (,prompt ,var) ,@body ,element))))
   3.456+
   3.457 (provide 'skel)
   3.458-;;; skel.el ends here
   3.459+(provide 'sk)
   3.460+;;; sk.el ends here