home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume11 / templates / part03 / tplhelper.el
Encoding:
Text File  |  1987-10-04  |  44.0 KB  |  1,481 lines

  1. ;;; tplhelper.el -- Helper functions for template-mode.
  2. ;;; Copyright (C) 1987 Mark A. Ardis.
  3.  
  4. (provide 'tplhelper)
  5.  
  6. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  7.  
  8. (defun tpl-blank-line ()
  9.   "Returns t if current line contains only whitespace.
  10.     Otherwise, returns nil."
  11.                     ; Local Variables
  12.   (let (result)
  13.                     ; Body
  14.     (save-excursion
  15.       (beginning-of-line)
  16.       (if (eolp)
  17.       (setq result t)
  18.     ; else
  19.     (progn
  20.       (re-search-forward tpl-pattern-whitespace (point-max) t)
  21.       (if (eolp)
  22.           (setq result t)
  23.         (setq result nil)
  24.         ) ; if
  25.       ) ; progn
  26.     ) ; if
  27.       ) ; save
  28.     ; return
  29.     result
  30.     ) ; let
  31.   ) ; defun tpl-blank-line
  32.  
  33. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  34.  
  35. (defun tpl-build-template-list ()
  36.   "Build template-list, using current major mode."
  37.                     ; Local Variables
  38.   (let (mode-entry template-list)
  39.                     ; Body
  40.     (setq tpl-local-template-list
  41.       (list (tpl-mode-templates
  42.          (tpl-mode-match 'generic tpl-global-template-list))))
  43.     ; Use loaded templates if available
  44.     (setq template-list
  45.       (tpl-mode-templates
  46.        (tpl-mode-match major-mode tpl-global-template-list)))
  47.     (if template-list
  48.     (setq tpl-local-template-list
  49.           (cons template-list tpl-local-template-list))
  50.       ; else
  51.       (progn
  52.     (setq mode-entry (tpl-mode-match major-mode tpl-auto-template-alist))
  53.     (if mode-entry
  54.         (progn
  55.           (load-tpl-library (tpl-mode-file mode-entry) major-mode)
  56.           ) ; progn
  57.       ; else
  58.       (message "No templates found for this mode.")
  59.       ) ; if mode-entry
  60.     ) ; progn
  61.       ) ; if template-list
  62.     (if tpl-rebuild-all-templates-template
  63.     (tpl-make-all-templates-template)
  64.       ) ; if
  65.     ) ; let
  66.   ) ; defun tpl-build-template-list
  67.  
  68. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  69.  
  70. (defun tpl-delete-placeholders-in-region (start stop)
  71.   "Delete all placeholders in region between START and STOP."
  72.                     ; Local Variables
  73.   (let (stop-marker)
  74.                     ; Body
  75.     (setq stop-marker (make-marker))
  76.     (set-marker stop-marker stop)
  77.     (goto-char start)
  78.     (while (re-search-forward tpl-pattern-placeholder
  79.                   (marker-position stop-marker) t)
  80.       (re-search-backward tpl-pattern-placeholder)
  81.       (delete-placeholder)
  82.       ) ; while
  83.     (set-marker stop-marker nil)
  84.     ) ; let
  85.   ) ; defun tpl-delete-placeholders-in-region
  86.  
  87. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  88.  
  89. (defun tpl-expand-lexical-type (name stop)
  90.   "Expand the lexical placeholder NAME at point.  Replaces all instances
  91.     of identical placeholders before STOP with the same value.
  92.     Checks for match with lexical description."
  93.                     ; Local Variables
  94.   (let (save-hook)
  95.                     ; Body
  96.     (if (boundp 'sym-check-validity-hook)
  97.     (setq save-hook sym-check-validity-hook)
  98.       (setq save-hook nil)
  99.       ) ; if
  100.     (setq sym-check-validity-hook 'tpl-lexical-check)
  101.     (setq tpl-lexical-pattern (tpl-find-value-of-template name))
  102.     (if tpl-lexical-pattern
  103.     (tpl-expand-text-type stop)
  104.       (error "Cannot find template.")
  105.       ) ; if
  106.     (setq sym-check-validity-hook save-hook)
  107.     ) ; let
  108.   ) ; defun tpl-expand-lexical-type
  109.  
  110. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  111.  
  112. (defun tpl-expand-placeholder (stop)
  113.   "Expand the placeholder at point.  Replace identical occurrences
  114.     of text placeholders before STOP with the same value."
  115.                     ; Local Variables
  116.   (let (placeholder template-name start placeholder-name)
  117.                     ; Body
  118.     (setq start (point))
  119.                     ; Process placeholder
  120.     (setq placeholder (tpl-scan-placeholder))
  121.     (setq template-name (tpl-token-name placeholder))
  122.     (setq placeholder-name (tpl-token-value placeholder))
  123.     (cond
  124.      ((equal template-name "text")
  125.       (tpl-expand-text-type stop)
  126.       ) ; (equal template-name "text")
  127.      ((equal template-name "textenter")
  128.       (tpl-expand-textenter-type stop)
  129.       ) ; (equal template-name "textenter")
  130.      ((equal template-name "textlong")
  131.       (tpl-expand-textlong-type placeholder-name)
  132.       ) ; (equal template-name "textlong")
  133.      ((equal template-name tpl-destination-symbol)
  134.       (progn
  135.     (re-search-forward tpl-pattern-placeholder)
  136.     (ding)
  137.     (message "Cannot expand destination placeholder.")
  138.     ) ; progn
  139.       ) ; (equal template-name "textlong")
  140.      (t
  141.       (if (equal tpl-lexical-type
  142.          (tpl-find-type-of-template template-name))
  143.       (tpl-expand-lexical-type template-name stop)
  144.     ; else
  145.     (progn
  146.       (re-search-forward tpl-pattern-placeholder)
  147.       (delete-region start (point))
  148.       (tpl-insert-template template-name)
  149.       ) ; progn
  150.     ) ; if
  151.       ) ; t
  152.      ) ; cond
  153.     ) ; let
  154.   ) ; defun tpl-expand-placeholder
  155.  
  156. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  157.  
  158. (defun tpl-expand-text-type (stop)
  159.   "Expand the text placeholder at point.  Replace identical placeholders
  160.     before STOP with the same value.  Return that value."
  161.                     ; Local Variables
  162.   (let (start stop-marker placeholder-string sym-input)
  163.                     ; Body
  164.     (setq start (point))
  165.     (if stop
  166.     (progn
  167.       (setq stop-marker (make-marker))
  168.       (set-marker stop-marker stop)
  169.       ) ; progn
  170.       ) ; if stop
  171.     (re-search-forward tpl-pattern-placeholder)
  172.     (setq placeholder-string (buffer-substring start (point)))
  173.     (goto-char start)
  174.     (setq sym-input (sym-read-string
  175.              (concat "Replace " placeholder-string " with what? ")
  176.              placeholder-string))
  177.     (if (= (length sym-input) 0)
  178.     (re-search-forward placeholder-string)
  179.       ; else
  180.       (if stop
  181.       (progn
  182.         (setq start (point))
  183.                     ; Replace all identical placeholders
  184.         (while (re-search-forward placeholder-string
  185.                       (marker-position stop-marker) t)
  186.           (re-search-backward placeholder-string)
  187.           (insert-before-markers sym-input)
  188.           (delete-char (length placeholder-string))
  189.           ) ; while (re-search-forward...)
  190.         (goto-char start)
  191.         ) ; progn
  192.     ) ; if stop
  193.       ) ; if (= (length sym-input) 0)
  194.     ; return
  195.     sym-input
  196.     ) ; let
  197.   ) ; defun tpl-expand-text-type
  198.  
  199. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  200.  
  201. (defun tpl-expand-textenter-type (stop)
  202.   "Expand the text placeholder at point.  Replace identical placeholders
  203.     before STOP with the same value.  Enter that value in the symbol
  204.     table."
  205.                     ; Local Variables
  206.   (let (value)
  207.                     ; Body
  208.     (setq value (tpl-expand-text-type stop))
  209.     (sym-enter-id value)
  210.     ) ; let
  211.   ) ; defun tpl-expand-textenter-type
  212.  
  213.  
  214. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  215.  
  216. (defun tpl-expand-textlong-type (name)
  217.   "Expand the textlong placeholder at point called NAME."
  218.                     ; Local Variables
  219.   (let (start display-string save-buffer new-string start-column)
  220.                     ; Body
  221.                     ; Highlight placeholder
  222.     (setq start (point))
  223.     (re-search-forward tpl-pattern-placeholder)
  224.     (delete-region start (point))
  225.     (setq display-string (concat tpl-display-begin name tpl-display-end))
  226.     (insert-before-markers display-string)
  227.     (backward-char (length display-string))
  228.                     ; Save current location
  229.     (setq start (point))
  230.                     ; Prepare buffer
  231.     (save-window-excursion
  232.       (setq save-buffer (buffer-name))
  233.       (switch-to-buffer-other-window tpl-textlong-buffer)
  234.       (erase-buffer)
  235.       (shrink-window 5)
  236.                     ; Wait for return from recursive edit
  237.       (message (substitute-command-keys
  238.         "Type replacement and exit with \\[exit-recursive-edit]"))
  239.       (recursive-edit)
  240.                     ; Get new value and insert
  241.       (setq new-string (buffer-substring (point-min) (point-max)))
  242.       (set-buffer save-buffer)
  243.       (delete-windows-on tpl-textlong-buffer)
  244.       ) ; save-window-excursion
  245.     (bury-buffer tpl-textlong-buffer)
  246.                     ; Return to proper location
  247.     (goto-char start)
  248.     (delete-char (length display-string))
  249.     (setq start-column (current-column))
  250.     (setq start (point))
  251.     (insert-before-markers new-string)
  252.     (indent-rigidly start (point) start-column)
  253.     ) ; let
  254.   ) ; defun tpl-expand-textlong-type
  255.  
  256. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  257.  
  258. (defun tpl-find-end-of-group ()
  259.   "Find the end of a group defined for query-replace-groups."
  260.                     ; Local Variables
  261.   (let ()
  262.                     ; Body
  263.     (if tpl-form-placeholder-name-from-context
  264.     (tpl-make-placeholder-name)
  265.       ) ; if tpl-form-placeholder-name-from-context
  266.     (if tpl-include-prefix-in-groups
  267.     (beginning-of-line nil)
  268.       ) ; if tpl-include-prefix-in-groups
  269.     (set-mark (point))
  270.     (end-of-line nil)
  271.     (re-search-forward tpl-end-group nil "not-t")
  272.     (if tpl-verify-end-of-group
  273.     (progn
  274.       (message
  275.        (concat "Position point AFTER end of group and exit ("
  276.            (substitute-command-keys "\\[exit-recursive-edit]")
  277.            ")."))
  278.       (unwind-protect
  279.           (recursive-edit)
  280.         ) ; unwind-protect
  281.       ) ; progn
  282.       ) ; if tpl-verify-end-of-group
  283.     (end-of-line 0)
  284.     ) ; let
  285.   ) ; defun tpl-find-end-of-group
  286.  
  287. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  288.  
  289. (defun tpl-find-expansion-destination (start stop)
  290.   "Delete special destination placeholder between START and STOP
  291.     and set destination marker if a destination needs to be found."
  292.                     ; Local Variables
  293.   (let (stop-marker)
  294.                     ; Body
  295.     (goto-char start)
  296.     (setq stop-marker (make-marker))
  297.     (set-marker stop-marker stop)
  298.     (while (re-search-forward tpl-destination-placeholder stop stop)
  299.     (progn
  300.       (re-search-backward tpl-pattern-placeholder)
  301.       (delete-placeholder)
  302.       (if tpl-destination-needed
  303.           (progn
  304.         (set-marker tpl-destination-marker (point))
  305.         (setq tpl-destination-needed nil)
  306.         ) ; progn
  307.         ) ; if tpl-destination-needed
  308.       ) ; progn
  309.       ) ; while (re-search-forward tpl-destination-placeholder stop stop)
  310.     (goto-char (marker-position stop-marker))
  311.     (set-marker stop-marker nil)
  312.     ) ; let
  313.   ) ; defun tpl-find-expansion-destination
  314.  
  315. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  316.  
  317. (defun tpl-find-next-group ()
  318.   "Find the end of a group defined for query-replace-groups.
  319.     Do not interact with user."
  320.                     ; Local Variables
  321.   (let ()
  322.                     ; Body
  323.     (end-of-line nil)
  324.     (re-search-forward tpl-end-group nil "not-t")
  325.     (end-of-line 0)
  326.     ) ; let
  327.   ) ; defun tpl-find-next-group
  328.  
  329. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  330.  
  331. (defun tpl-find-template-file (file)
  332.   "Find FILE using the 'tpl-load-path value."
  333.                     ; Local Variables
  334.   (let (tpl-name compiled-name dir-list looking)
  335.                     ; Body
  336.     (setq tpl-name (concat file ".tpl"))
  337.     (setq compiled-name (concat file "tpl.elc"))
  338.     (setq name nil)
  339.     (setq looking t)
  340.                     ; First try compiled versions
  341.     (setq dir-list tpl-load-path)
  342.     (while (and looking dir-list)
  343.       (setq name (concat (car dir-list) "/" compiled-name))
  344.       (setq dir-list (cdr dir-list))
  345.       (if (file-readable-p name)
  346.       (setq looking nil)
  347.     ) ; if
  348.       ) ; while
  349.                     ; Second, try uncompiled
  350.     (setq dir-list tpl-load-path)
  351.     (while (and looking dir-list)
  352.       (setq name (concat (car dir-list) "/" tpl-name))
  353.       (setq dir-list (cdr dir-list))
  354.       (if (file-readable-p name)
  355.       (setq looking nil)
  356.     ) ; if
  357.       ) ; while
  358.                     ; Last, try literal name
  359.     (setq dir-list tpl-load-path)
  360.     (while (and looking dir-list)
  361.       (setq name (concat (car dir-list) "/" file))
  362.       (setq dir-list (cdr dir-list))
  363.       (if (file-readable-p name)
  364.       (setq looking nil)
  365.     ) ; if
  366.       ) ; while
  367.     ; return
  368.     name
  369.     ) ; let
  370.   ) ; defun tpl-find-template-file
  371.  
  372. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  373.  
  374. (defun tpl-find-template (tpl-name)
  375.   "Find template TPL_NAME and return template or nil (if not found)."
  376.                     ; Local Variables
  377.   (let (found file-list template-file template-list template template-name)
  378.                     ; Body
  379.     (setq found nil)
  380.     (setq file-list tpl-local-template-list)
  381.     (while (and file-list (not found))
  382.       (setq template-file (car file-list))
  383.       (setq file-list (cdr file-list))
  384.       (setq template-list (nth 1 template-file))
  385.       (while (and template-list (not found))
  386.     (setq template (car template-list))
  387.     (setq template-list (cdr template-list))
  388.     (setq template-name (tpl-token-name template))
  389.     (if (equal template-name tpl-name)
  390.         (setq found template)
  391.       ) ; if (equal template-name tpl-name)
  392.     ) ; while (and template-list (not found))
  393.       ) ; while (and file-list (not found))
  394.                     ; return
  395.     found
  396.     ) ; let
  397.   ) ; defun tpl-find-template
  398.  
  399. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  400.  
  401. (defun tpl-find-type-of-template (name)
  402.   "Find template NAME and return its type or nil (if not found)."
  403.                     ; Local Variables
  404.   (let (template result)
  405.                     ; Body
  406.     (setq template (tpl-find-template name))
  407.     (if template
  408.     (setq result (tpl-token-type template))
  409.       (setq result nil)
  410.       ) ; if
  411.                     ; return
  412.     result
  413.     ) ; let
  414.   ) ; defun tpl-find-type-of-template
  415.  
  416. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  417.  
  418. (defun tpl-find-value-of-template (name)
  419.   "Find template NAME and return its value or nil (if not found)."
  420.                     ; Local Variables
  421.   (let (template result)
  422.                     ; Body
  423.     (setq template (tpl-find-template name))
  424.     (if template
  425.     (setq result (tpl-token-value template))
  426.       (setq result nil)
  427.       ) ; if
  428.                     ; return
  429.     result
  430.     ) ; let
  431.   ) ; defun tpl-find-value-of-template
  432.  
  433. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  434.  
  435. (defun tpl-find-wrappers (tpl-name)
  436.   "Find the beginning and ending part of TPL-NAME that encloses a
  437.     destination placeholder."
  438.                     ; Local Variables
  439.   (let (msg template midpoint result)
  440.                     ; Body
  441.     (setq msg nil)
  442.     (setq template (tpl-find-template tpl-name))
  443.     (save-excursion
  444.       (set-buffer tpl-work-buffer)
  445.       (erase-buffer)
  446.       (if template
  447.       (progn
  448.         (tpl-unscan template)
  449.         (goto-char (point-min))
  450.         (if (re-search-forward tpl-destination-placeholder
  451.                    (point-max) t)
  452.         (progn
  453.           (delete-region (match-beginning 0) (match-end 0))
  454.           (setq midpoint (point))
  455.           ) ; progn
  456.           ; else
  457.           (progn
  458.         (setq msg "Template does not contain a destination placeholder.")
  459.         ) ; progn
  460.           ) ; if
  461.         ) ; progn
  462.     ; else
  463.     (progn
  464.       (setq msg "Cannot find template.")
  465.       ) ; progn
  466.     ) ; if template
  467.       (if (not msg)
  468.       (setq result (list (buffer-substring 1 midpoint)
  469.                  (buffer-substring midpoint (point-max))
  470.                  (current-column)))
  471.     ) ; if
  472.       ) ; save-excursion
  473.     (bury-buffer tpl-work-buffer)
  474.     (if msg
  475.     (error msg)
  476.       ) ; if
  477.                     ; return
  478.     result
  479.     ) ; let
  480.   ) ; defun tpl-find-wrappers
  481.  
  482. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  483.  
  484. (defun tpl-generate (tpl-name)
  485.   "Insert and expand the template TPL-NAME at point."
  486.                     ; Local Variables
  487.   (let (start stop)
  488.                     ; Body
  489.     ; Insert and expand template
  490.     (setq start (point))
  491.     (insert-before-markers tpl-begin-placeholder tpl-name tpl-end-placeholder)
  492.     (goto-char start)
  493.     (setq tpl-destination-needed t)
  494.     (message "Looking for template...")
  495.     (tpl-expand-placeholder nil)
  496.     (setq stop (point))
  497.     (if (not tpl-destination-needed)
  498.     (progn
  499.       (goto-char (marker-position tpl-destination-marker))
  500.       (set-marker tpl-destination-marker nil)
  501.       ) ; progn
  502.       ; else
  503.       (progn
  504.     (setq tpl-destination-needed nil)
  505.     (goto-char start)
  506.     (if (re-search-forward tpl-pattern-placeholder stop stop)
  507.         (re-search-backward tpl-pattern-placeholder)
  508.       ) ; if
  509.     ) ; progn
  510.       ) ; if (not tpl-destination-needed)
  511.     (message "%s" "Done.")
  512.     ) ; let
  513.   ) ; defun tpl-generate
  514.  
  515. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  516.  
  517. (defun tpl-get-placeholder-name ()
  518.   "Prompt for a placeholder name.  If none supplied, use temporary
  519.     name and regenerate another unique name.  Return the name."
  520.                     ; Local Variables
  521.   (let (name)
  522.                     ; Body
  523.     (if tpl-query-flag
  524.     (progn
  525.       (setq name (read-string
  526.               (concat "Template name? ("
  527.                   tpl-next-placeholder-name ") ")))
  528.       ) ; progn
  529.       ; else
  530.       (setq name "")
  531.       ) ; if tpl-query-flag
  532.     (if (equal name "")
  533.     (progn
  534.       (setq name tpl-next-placeholder-name)
  535.       (tpl-increment-next-placeholder-name)
  536.       ) ; progn
  537.       ) ; if (equal name "")
  538.                     ; return
  539.     name
  540.     ) ; let
  541.   ) ; tpl-get-placeholder-name
  542.  
  543. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  544.  
  545. (defun tpl-increment-next-placeholder-name ()
  546.   "Increment unique name for temporary placeholders."
  547.                     ; Local Variables
  548.   (let ()
  549.                     ; Body
  550.     (setq tpl-next-placeholder-number
  551.       (1+ tpl-next-placeholder-number))
  552.     (setq tpl-next-placeholder-name
  553.       (concat tpl-temporary-placeholder-name
  554.           tpl-next-placeholder-number))
  555.     ) ; let
  556.   ) ; defun tpl-increment-next-placeholder-name
  557.  
  558. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  559.  
  560. (defun tpl-initialize-modes ()
  561.   "Create initial Alist of major modes and their associated template files.
  562.     Calls 'template-mode-load-hook' if it is defined."
  563.                     ; Local Variables
  564.   (let ()
  565.                     ; Body
  566.     (or (assq 'template-mode minor-mode-alist)
  567.     (setq minor-mode-alist
  568.           (cons '(template-mode " Template") minor-mode-alist)))
  569.     (setq tpl-auto-template-alist
  570.       (list
  571.        (tpl-make-mode-entry 'awk-mode "awk")
  572.        (tpl-make-mode-entry 'bib-mode "bib")
  573.        (tpl-make-mode-entry 'c-mode "c")
  574.        (tpl-make-mode-entry 'emacs-lisp-mode "elisp")
  575.        (tpl-make-mode-entry 'generic "generic")
  576.        (tpl-make-mode-entry 'LaTeX-mode "latex")
  577.                     ; Should have another set of templates
  578.                     ;   for Lisp
  579.        (tpl-make-mode-entry 'lisp-mode "elisp")
  580.        (tpl-make-mode-entry 'pascal-mode "pascal")
  581.        (tpl-make-mode-entry 'scribe-mode "scribe")
  582.        (tpl-make-mode-entry 'texinfo-mode "texinfo")
  583.                     ; Should have another set of templates
  584.                     ;    for TeX
  585.        (tpl-make-mode-entry 'plain-TeX-mode "latex")
  586.         ))
  587.     (setq tpl-local-template-list nil)
  588.     (get-buffer-create tpl-menu-buffer)
  589.     (get-buffer-create tpl-textlong-buffer)
  590.     (get-buffer-create tpl-work-buffer)
  591.     (bury-buffer tpl-menu-buffer)
  592.     (bury-buffer tpl-textlong-buffer)
  593.     (bury-buffer tpl-work-buffer)
  594.     (tpl-initialize-scan)
  595.     (load-tpl-library "generic" 'generic)
  596.     (and (boundp 'template-mode-load-hook)
  597.      template-mode-load-hook
  598.      (funcall template-mode-load-hook))
  599.     ) ; let
  600.   ) ; defun tpl-initialize-modes
  601.  
  602. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  603.  
  604. (defun tpl-insert-function (template)
  605.   "Insert a template at point using the function type TEMPLATE."
  606.                     ; Local Variables
  607.   (let (start stop-marker result save-depth)
  608.                     ; Body
  609.     (setq start (point))
  610.     (setq stop-marker (make-marker))
  611.     (insert (tpl-token-value template))
  612.     (set-marker stop-marker (point))
  613.                     ; Temporarily expand placeholders
  614.                     ;    without asking
  615.     (setq save-depth tpl-ask-expansion-depth)
  616.     (setq tpl-ask-expansion-depth 10)
  617.     (expand-placeholders-in-region start (point))
  618.     (setq tpl-ask-expansion-depth save-depth)
  619.                     ; Evaluate result
  620.     (goto-char start)
  621.     (save-excursion
  622.       (setq result (eval (read (current-buffer))))
  623.       ) ; save-excursion
  624.                     ; Remove placeholder and insert result
  625.     (delete-region start (marker-position stop-marker))
  626.     (set-marker stop-marker nil)
  627.     (insert result)
  628.     ) ; let
  629.   ) ; defun tpl-insert-function
  630.  
  631. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  632.  
  633. (defun tpl-insert-repetition (template)
  634.   "Insert at point instances of the repetition type TEMPLATE."
  635.                     ; Local Variables
  636.   (let (start template-name column)
  637.                     ; Body
  638.     (setq start (point))
  639.     (setq column (current-column))
  640.     (setq template-name (tpl-token-name template))
  641.                     ; Insert first instance
  642.     (tpl-unscan template)
  643.     (re-search-backward tpl-pattern-placeholder)
  644.     (delete-region start (point))
  645.     (tpl-expand-placeholder nil)
  646.                     ; Insert more instances
  647.     (while (tpl-y-or-n-p (concat "More instances of " template-name "? "))
  648.       (tpl-unscan template column)
  649.       (cond
  650.        ((> tpl-ask-expansion-depth 0)
  651.     (progn
  652.       (re-search-backward tpl-pattern-placeholder)
  653.       (tpl-expand-placeholder nil)
  654.       ) ; progn
  655.     ) ; (> tpl-ask-expansion-depth 0)
  656.        ) ; cond
  657.       ) ; while (tpl-y-or-n-p...)
  658.     ) ; let
  659.   ) ; defun tpl-insert-repetition
  660.  
  661. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  662.  
  663. (defun tpl-insert-selection (template)
  664.   "Insert a template at point using the selection type TEMPLATE."
  665.                     ; Local Variables
  666.   (let (save-buffer start stop size choice choice-template choice-list
  667.             display-string)
  668.                     ; Body
  669.                     ; Highlight placeholder
  670.     (setq display-string (concat
  671.               tpl-display-begin
  672.               (tpl-token-name template)
  673.               tpl-display-end))
  674.     (insert-before-markers display-string)
  675.     (backward-char (length display-string))
  676.                     ; Prepare menu buffer
  677.     (save-window-excursion
  678.       (setq save-buffer (buffer-name))
  679.       (switch-to-buffer-other-window tpl-menu-buffer)
  680.       (erase-buffer)
  681.                     ; Build the menu
  682.       (tpl-unscan template)
  683.                     ; Size the window
  684.       (goto-char (point-max))
  685.       (setq stop (point))
  686.       (goto-char (point-min))
  687.       (setq start (point))
  688.       (setq size (1+ (count-lines start stop)))
  689.       (setq size (max size window-min-height))
  690.       (if (< size (window-height))
  691.       (shrink-window (- (window-height) size))
  692.     ) ; if
  693.                     ; Allow user to view and select
  694.       (setq choice (menu-mode))
  695.       (set-buffer save-buffer)
  696.       (delete-windows-on tpl-menu-buffer)
  697.       ) ; save-window-excursion
  698.     (bury-buffer tpl-menu-buffer)
  699.     (delete-char (length display-string))
  700.                     ; Insert choice as template or string
  701.     (if choice
  702.     (progn
  703.       (setq choice-list (tpl-parse-choice choice))
  704.       (setq choice-template (nth 1 choice-list))
  705.       (if choice-template
  706.           (tpl-insert-template choice-template)
  707.         ; else
  708.         (insert-before-markers (nth 0 choice-list))
  709.         ) ; choice-template
  710.       ) ; progn
  711.       ; else insert placeholder
  712.       (progn
  713.     (setq display-string (concat tpl-begin-placeholder
  714.                      (tpl-token-name template)
  715.                      tpl-end-placeholder))
  716.     (insert-before-markers display-string)
  717.     (backward-char (length display-string))
  718.     (error "Quit.")
  719.     ) ; progn
  720.       ) ; if choice
  721.     ) ; let
  722.   ) ; defun tpl-insert-selection
  723.  
  724. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  725.  
  726. (defun tpl-insert-string-from-buffer (tpl-name display-string &optional buffer)
  727.   "Insert a template at point using the string type TPL-NAME, temporarily
  728.    represented by DISPLAY-STRING.  Optional third argument BUFFER is the
  729.    buffer to search."
  730.                     ; Local Variables
  731.   (let (start string)
  732.                     ; Body
  733.     (if (not buffer)
  734.     (setq buffer
  735.           (read-buffer "tpl-insert-string: Template buffer? "
  736.                tpl-new-template-buffer t))
  737.       ) ; if
  738.     (save-window-excursion
  739.       (set-buffer buffer)
  740.       (goto-char (point-min))
  741.       (if (re-search-forward (concat tpl-begin-template-definition
  742.                      " " tpl-name " ")
  743.                  (point-max) t)
  744.       (progn
  745.         (re-search-forward tpl-begin-template-body)
  746.         (beginning-of-line 2)
  747.         (setq start (point))
  748.         (re-search-forward tpl-end-template-body)
  749.         (end-of-line 0)
  750.         (setq string (buffer-substring start (point)))
  751.         ) ; progn
  752.     ; else
  753.     (error "Could not find template in %s" buffer)
  754.     ) ; if
  755.       ) ; save-window-excursion
  756.     (delete-char (length display-string))
  757.     (insert-before-markers string)
  758.     ) ; let
  759.   ) ; defun tpl-insert-string-from-buffer
  760.  
  761. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  762.  
  763. (defun tpl-insert-template (tpl-name)
  764.   "Insert the template TPL-NAME at point."
  765.                     ; Local Variables
  766.   (let (display-string template start template-type looking)
  767.                     ; Body
  768.                     ; Display selected template
  769.     (setq display-string (concat tpl-display-begin tpl-name tpl-display-end))
  770.     (insert-before-markers display-string)
  771.     (backward-char (length display-string))
  772.     (setq looking t)
  773.     (while looking
  774.                     ; Find template.
  775.       (setq template (tpl-find-template tpl-name))
  776.       (if template
  777.       (progn
  778.         (setq looking nil)
  779.                     ; Insert template
  780.         (delete-char (length display-string))
  781.         (setq start (point))
  782.         (setq template-type (tpl-token-type template))
  783.         (cond
  784.          ((equal template-type tpl-sequence-type)
  785.           (progn
  786.         (tpl-unscan template)
  787.         (tpl-find-expansion-destination start (point))
  788.         (cond
  789.          ((< tpl-ask-expansion-depth 0)
  790.           (tpl-delete-placeholders-in-region start (point))
  791.           ) ; (< tpl-ask-expansion-depth 0)
  792.          ((> tpl-ask-expansion-depth 0)
  793.           (progn
  794.             (expand-placeholders-in-region start (point))
  795.             ) ; progn
  796.           ) ; (> tpl-ask-expansion-depth 0)
  797.          ) ; cond
  798.         ) ; progn
  799.           ) ; (equal template-type tpl-sequence-type)
  800.          ((equal template-type tpl-selection-type)
  801.           (progn
  802.         (tpl-insert-selection template)
  803.         ) ; progn
  804.           ) ; (equal template-type tpl-selection-type)
  805.          ((equal template-type tpl-repetition-type)
  806.           (progn
  807.         (tpl-insert-repetition template)
  808.         ) ; progn
  809.           ) ; (equal template-type tpl-repetition-type)
  810.          ((equal template-type tpl-function-type)
  811.           (progn
  812.         (tpl-insert-function template)
  813.         ) ; progn
  814.           ) ; (equal template-type tpl-function-type)
  815.          ((equal template-type tpl-string-type)
  816.           (progn
  817.         (tpl-unscan template)
  818.         ) ; progn
  819.           ) ; (equal template-type tpl-string-type)
  820.          ) ; cond
  821.         ) ; progn
  822.                     ; Else report failure
  823.     (progn
  824.       (if (y-or-n-p "Cannot find template---look in a buffer? ")
  825.           (progn
  826.         (setq looking nil)
  827.         (tpl-insert-string-from-buffer tpl-name display-string)
  828.         ) ; progn
  829.         ; else
  830.         (if (y-or-n-p "Cannot find template---load a template file? ")
  831.         (progn
  832.           (save-some-buffers)
  833.           (load-tpl-file)
  834.           ) ; progn
  835.           ; else
  836.           (progn
  837.         (setq looking nil)
  838.         (error "Gave up looking for template.")
  839.         ) ; progn
  840.           ) ; if (y-or-n-p ...load...)
  841.         ) ; if (y-or-n-p ...look...)
  842.       ) ; progn
  843.     ) ; if template
  844.       ) ; while looking
  845.     ) ; let
  846.   ) ; defun tpl-insert-template
  847.  
  848. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  849.  
  850. (defun tpl-lexical-check (input)
  851.   "Check INPUT for validity against lexical definition."
  852.                     ; Local Variables
  853.   (let (result)
  854.                     ; Body
  855.     (if (and (string-match tpl-lexical-pattern input)
  856.          (equal (match-beginning 0) 0)
  857.          (equal (match-end 0) (length input)))
  858.     (setq result t)
  859.       (setq result nil)
  860.       ) ; if
  861.     (if (not result)
  862.     (progn
  863.       (ding)
  864.       (message (concat "String does not match pattern: "
  865.                tpl-lexical-pattern))
  866.       ) ; progn
  867.       ) ; if
  868.                     ; return
  869.     result
  870.     ) ; let
  871.   ) ; defun tpl-lexical-check
  872.  
  873. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  874.  
  875. (defun tpl-make-all-templates-template ()
  876.   "Make a template consisting of a selection of all templates.
  877.     Replace existing version if present."
  878.                     ; Local Variables
  879.   (let (name template-tree template-file template-list file-name name-list
  880.          new-template-list)
  881.                     ; Body
  882.     (message "Rebuilding list of all templates...")
  883.                     ; Build name-list
  884.     (setq template-list tpl-local-template-list)
  885.     (setq new-template-list nil)
  886.     (setq name-list nil)
  887.     (while template-list
  888.       (setq template-file (car template-list))
  889.       (setq template-list (cdr template-list))
  890.       (setq file-name (nth 0 template-file))
  891.                     ; Remove existing version if present
  892.       (if (not (string-equal file-name tpl-all-templates-file))
  893.       (progn
  894.         (setq new-template-list
  895.           (append new-template-list (list template-file)))
  896.         (setq name-list
  897.           (append name-list (nth 2 template-file)))
  898.         ) ; progn
  899.     ) ; if
  900.       ) ; while template-list
  901.                     ; Build template
  902.     (save-window-excursion
  903.       (set-buffer tpl-work-buffer)
  904.       (erase-buffer)
  905.       (while name-list
  906.     (setq name (car name-list))
  907.     (setq name-list (cdr name-list))
  908.     (insert (car name) ":")
  909.     (newline)
  910.     ) ; while name-list
  911.       (shell-command-on-region (point-min) (point-max) "sort -u" t)
  912.                     ; Insert preface
  913.       (goto-char (point-min))
  914.       (insert tpl-begin-template-definition " "
  915.           tpl-all-templates-name " "
  916.           tpl-selection-type)
  917.       (newline)
  918.       (beginning-of-line 0)
  919.       (delete-char 1)            ; Remove regular exression anchor
  920.       (end-of-line)
  921.       (newline)
  922.       (insert tpl-begin-template-body)
  923.       (beginning-of-line)
  924.       (delete-char 1)            ; Remove regular exression anchor
  925.                     ; Insert suffix
  926.       (goto-char (point-max))
  927.       (insert tpl-end-template-body)
  928.       (beginning-of-line)
  929.       (delete-char 1)
  930.       (end-of-line)
  931.       (newline)
  932.                     ; Create template
  933.       (goto-char (point-min))
  934.       (setq template-tree (tpl-scan-template))
  935.       ) ; save-window-excursion
  936.     (bury-buffer tpl-work-buffer)
  937.                     ; Rebuild template-list
  938.     (setq tpl-local-template-list
  939.       (append (list (list tpl-all-templates-file
  940.                   (list template-tree) nil))
  941.           new-template-list))
  942.     (setq tpl-all-templates-template-invalid nil)
  943.     (message "Rebuilding list of all templates...Done.")
  944.     ) ; let
  945.   ) ; defun tpl-make-all-templates-template
  946.  
  947. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  948.  
  949. (defun tpl-make-completion-list ()
  950.   "Create a completion list of template names for prompting."
  951.                     ; Local Variables
  952.   (let (name completion-list file-list template-file name-list)
  953.                     ; Body
  954.     ; Build completion list
  955.     (setq completion-list nil)
  956.     (setq file-list tpl-local-template-list)
  957.     (while file-list
  958.       (setq template-file (car file-list))
  959.       (setq file-list (cdr file-list))
  960.       (setq name-list (nth 2 template-file))
  961.       (setq completion-list (append completion-list name-list))
  962.       ) ; while file-list
  963.                     ; return
  964.     completion-list
  965.     ) ; let
  966.   ) ; defun tpl-make-completion-list
  967.  
  968. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  969.  
  970. (defun tpl-make-keymap ()
  971.   "Make keymap for template-mode."
  972.                     ; Local Variables
  973.   (let ()
  974.                     ; Body
  975.     (setq tpl-saved-map (current-local-map))
  976.     (if (not template-mode-map)
  977.     (progn
  978.       (setq template-mode-map tpl-saved-map)
  979.       (define-key
  980.         template-mode-map "\^c\^t\t" 'expand-symbol)
  981.       (define-key
  982.         template-mode-map "\^c\^ta" 'add-symbol)
  983.       (define-key
  984.         template-mode-map "\^c\^te" 'expand-placeholder)
  985.       (define-key
  986.         template-mode-map "\^c\^tg" 'query-replace-groups)
  987.       (define-key
  988.         template-mode-map "\^c\^tl" 'query-replace-lines)
  989.       (define-key
  990.         template-mode-map "\^c\^tr" 'replace-line-with-placeholder)
  991.       (define-key
  992.         template-mode-map "\^c\^tt" 'generate-template)
  993.       (define-key
  994.         template-mode-map "\^c\^tu" 'unwrap-template-around-point)
  995.       (define-key
  996.         template-mode-map "\^c\^tw" 'wrap-template-around-word)
  997.       (define-key
  998.         template-mode-map "\^c\^tW" 'wrap-template-around-line)
  999.       (define-key
  1000.         template-mode-map "\^c\^t\^e" 'expand-placeholders-in-region)
  1001.       (define-key
  1002.         template-mode-map "\^c\^t\^h" 'describe-template-mode)
  1003.       (define-key
  1004.         template-mode-map "\^c\^t\^k" 'delete-placeholder)
  1005.       (define-key
  1006.         template-mode-map "\^c\^t\^n" 'next-placeholder)
  1007.       (define-key
  1008.         template-mode-map "\^c\^t\^p" 'previous-placeholder)
  1009.       (define-key
  1010.         template-mode-map "\^c\^t\^r" 'replace-region-with-placeholder)
  1011.       (define-key
  1012.         template-mode-map "\^c\^t\^u" 'rewrap-template-around-point)
  1013.       (define-key
  1014.         template-mode-map "\^c\^t\^w" 'wrap-template-around-region)
  1015.       (define-key
  1016.         template-mode-map "\^c\^t?" 'generate-any-template)
  1017.       ) ; progn
  1018.       ) ; if
  1019.     (use-local-map template-mode-map)
  1020.     ) ; let
  1021.   ) ; defun tpl-make-keymap
  1022.  
  1023. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1024.  
  1025. (defun tpl-make-mode-entry (name file)
  1026.   "Constructor for mode entries from NAME FILE."
  1027.                     ; Local Variables
  1028.   (let ()
  1029.                     ; Body
  1030.     (list (list 'name name) (list 'file file))
  1031.     ) ; let
  1032.   ) ; defun tpl-make-mode-entry
  1033.  
  1034. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1035.  
  1036. (defun tpl-make-placeholder-name ()
  1037.   "Create a name for a new template by searching for the first symbol
  1038.     after point."
  1039.                     ; Local Variables
  1040.   (let ()
  1041.                     ; Body
  1042.     (save-excursion
  1043.       (if (re-search-forward tpl-pattern-symbol nil t)
  1044.       (progn
  1045.         (setq tpl-formed-placeholder-name
  1046.           (buffer-substring (match-beginning 0) (match-end 0)))
  1047.         ) ; progn
  1048.     ; else
  1049.     (progn
  1050.       (setq tpl-formed-placeholder-name tpl-next-placeholder-name)
  1051.       (tpl-increment-next-placeholder-name)
  1052.       ) ; progn
  1053.     ) ; if
  1054.       ) ; save-excursion
  1055.     ) ; let
  1056.   ) ; defun tpl-make-placeholder-name
  1057.  
  1058. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1059.  
  1060. (defun tpl-make-template-entry (name templates)
  1061.   "Constructor for mode entries from NAME TEMPLATES."
  1062.                     ; Local Variables
  1063.   (let ()
  1064.                     ; Body
  1065.     (list (list 'name name) (list 'templates templates))
  1066.     ) ; let
  1067.   ) ; defun tpl-make-template-entry
  1068.  
  1069. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1070.  
  1071. (defun tpl-make-template-list (file &optional buffer)
  1072.   "Create a template list from the templates in FILE.
  1073.     Optional second argument non-nil means use a buffer, not a file."
  1074.                     ; Local Variables
  1075.   (let (template-list template-tree template-name
  1076.               name-list msg table root-name)
  1077.                     ; Body
  1078.     (setq msg (concat "Loading templates in " file ": "))
  1079.     (save-window-excursion
  1080.       (setq table (syntax-table))
  1081.       (set-buffer tpl-work-buffer)
  1082.       (erase-buffer)
  1083.       (if buffer
  1084.       (insert-buffer file)
  1085.     ; else
  1086.     (insert-file file)
  1087.     ) ;if buffer
  1088.       (set-syntax-table table)
  1089.       (goto-char (point-min))
  1090.       (setq name-list nil)
  1091.       (while (re-search-forward
  1092.           tpl-begin-template-definition (point-max) t)
  1093.     (beginning-of-line)
  1094.     (setq template-tree (tpl-scan-template))
  1095.     (setq template-list (append template-list (list template-tree)))
  1096.     (setq template-name (tpl-token-name template-tree))
  1097.     (message (concat msg template-name "..."))
  1098.     (if (not (equal tpl-lexical-type
  1099.             (tpl-token-type template-tree)))
  1100.         (setq name-list
  1101.           (append name-list (list (list template-name))))
  1102.       ) ; if
  1103.     ) ; while (re-search-forward...)
  1104.       (setq template-list
  1105.         (list (tpl-root-of-file-name (file-name-nondirectory file))
  1106.           template-list name-list))
  1107.       ) ; save-window-excursion
  1108.     (bury-buffer tpl-work-buffer)
  1109.     (message (concat msg "Done."))
  1110.                     ; return
  1111.     template-list
  1112.     ) ; let
  1113.   ) ; defun tpl-make-template-list
  1114.  
  1115. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1116.  
  1117. (defun tpl-mode-file (mode-entry)
  1118.   "Selector for file field of MODE-ENTRY."
  1119.                     ; Local Variables
  1120.   (let ()
  1121.                     ; Body
  1122.     (car (cdr (assq 'file mode-entry)))
  1123.     ) ; let
  1124.   ) ; defun tpl-mode-file
  1125.  
  1126. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1127.  
  1128. (defun tpl-mode-match  (mode-nm list)
  1129.   "Find mode-entry that matches MODE-NM in LIST."
  1130.                     ; Local Variables
  1131.   (let (entry)
  1132.                     ; Body
  1133.     (while list
  1134.       (setq entry (car list))
  1135.       (setq list (cdr list))
  1136.       (if (equal (tpl-mode-name entry) mode-nm)
  1137.       (setq list nil)
  1138.     ; else
  1139.     (setq entry nil)
  1140.     ) ; if
  1141.       ) ; while
  1142.                     ; return
  1143.     entry
  1144.     ) ; let
  1145.   ) ; defun tpl-mode-match
  1146.  
  1147. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1148.  
  1149. (defun tpl-mode-name (mode-entry)
  1150.   "Selector for name field of MODE-ENTRY."
  1151.                     ; Local Variables
  1152.   (let ()
  1153.                     ; Body
  1154.     (car (cdr (assq 'name mode-entry)))
  1155.     ) ; let
  1156.   ) ; defun tpl-mode-name
  1157.  
  1158. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1159.  
  1160. (defun tpl-mode-templates (mode-entry)
  1161.   "Selector for templates field of MODE-ENTRY."
  1162.                     ; Local Variables
  1163.   (let ()
  1164.                     ; Body
  1165.     (car (cdr (assq 'templates mode-entry)))
  1166.     ) ; let
  1167.   ) ; defun tpl-mode-templates
  1168.  
  1169. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1170.  
  1171. (defun tpl-parse-choice (line)
  1172.   "Break menu LINE into component parts: (string template) or (string nil)."
  1173.                     ; Local Variables
  1174.   (let (string-part template-part end-string end-template)
  1175.                     ; Body
  1176.                     ; Line = 
  1177.                     ; "abc" is string "abc"
  1178.                     ; "abc:" is template "abc"
  1179.                     ; "abc:def" is template "def"
  1180.                     ; ";" begins comment area
  1181.     (setq end-string (string-match tpl-pattern-symbol line))
  1182.     (setq string-part (substring line 0 (match-end 0)))
  1183.     (setq line (substring line (match-end 0)))
  1184.     (setq end-string (string-match "^\\(\\s \\)*:\\(\\s \\)*" line))
  1185.     (if end-string
  1186.     (progn
  1187.       (setq line (substring line (match-end 0)))
  1188.       (setq end-string (string-match
  1189.                 (concat "^" tpl-pattern-symbol) line))
  1190.       (if end-string
  1191.           (setq template-part (substring line 0 (match-end 0)))
  1192.         ; else
  1193.         (setq template-part string-part)
  1194.         ) ; if end-template
  1195.       ) ; progn
  1196.       ; else
  1197.       (progn
  1198.     (setq template-part nil)
  1199.     ) ; progn
  1200.       ) ; if end-string
  1201.     (list string-part template-part)
  1202.     ) ; let
  1203.   ) ; defun tpl-parse-choice
  1204.  
  1205. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1206.  
  1207. (defun tpl-rebuild-global-template-list (name templates)
  1208.   "Rebuild global template list, changing major mode NAME to
  1209.     include TEMPLATES."
  1210.                     ; Local Variables
  1211.   (let (mode-list mode-item entry result)
  1212.                     ; Body
  1213.     (setq result nil)
  1214.     (setq entry nil)
  1215.     (setq mode-list tpl-global-template-list)
  1216.     (while (and mode-list (not entry))
  1217.       (setq mode-item (car mode-list))
  1218.       (setq mode-list (cdr mode-list))
  1219.       (if (string-equal (tpl-mode-name mode-item) name)
  1220.       (setq entry mode-item)
  1221.     ; else
  1222.     (setq result (append result (list mode-item)))
  1223.     ) ; if (equal (tpl-mode-name mode-item) name)
  1224.       ) ; while mode-list
  1225.     (if (not entry)
  1226.     (progn
  1227.       (setq tpl-global-template-list
  1228.         (append result
  1229.             (list (tpl-make-template-entry name templates))))
  1230.       (message "Added templates for %s." name)
  1231.       ) ; progn
  1232.       ; else
  1233.       (if (or (not (tpl-mode-templates mode-item))
  1234.           (y-or-n-p "Replace existing templates for this mode? "))
  1235.       (progn
  1236.         (setq result
  1237.           (append result (list (tpl-make-template-entry name
  1238.                                 templates))))
  1239.         (setq result (append result mode-list))
  1240.         (setq tpl-global-template-list result)
  1241.         (message "Added templates for %s." name)
  1242.         ) ; progn
  1243.     ) ; if
  1244.       ) ; if
  1245.     ) ; let
  1246.   ) ; defun tpl-rebuild-global-template-list
  1247.  
  1248. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1249.  
  1250. (defun tpl-replace-group (from to)
  1251.   "Replace current region with a temporary placeholder.
  1252.     Arguments FROM and TO are ignored.  (They are only needed
  1253.     for compatibility with other replacement functions.)"
  1254.                     ; Local Variables
  1255.   (let (name)
  1256.                     ; Body
  1257.     (if tpl-get-placeholder-name-in-context
  1258.     (setq name nil)
  1259.       ; else
  1260.       (progn
  1261.     (setq name tpl-next-placeholder-name)
  1262.     (tpl-increment-next-placeholder-name)
  1263.     ) ; progn
  1264.       ) ; if tpl-get-placeholder-name-in-context
  1265.     (replace-region-with-placeholder (mark) (point) name
  1266.                      "new.tpl" nil)
  1267.     ) ; let
  1268.   ) ; defun tpl-replace-group
  1269.  
  1270. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1271.  
  1272. (defun tpl-replace-line (from to)
  1273.   "Replace current line with a temporary placeholder.
  1274.     Arguments FROM and TO are ignored.  (They are only needed
  1275.     for compatibility with other replacement functions.)"
  1276.                     ; Local Variables
  1277.   (let (name)
  1278.                     ; Body
  1279.     (if tpl-get-placeholder-name-in-context
  1280.     (setq name nil)
  1281.       ; else
  1282.       (progn
  1283.     (setq name tpl-next-placeholder-name)
  1284.     (tpl-increment-next-placeholder-name)
  1285.     ) ; progn
  1286.       ) ; if tpl-get-placeholder-name-in-context
  1287.     (replace-line-with-placeholder 1 name "new.tpl" nil)
  1288.     ) ; let
  1289.   ) ; defun tpl-replace-line
  1290.  
  1291. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1292.  
  1293. (defun tpl-root-of-file-name (file)
  1294.   "Find the root of FILE as a template file name."
  1295.                     ; Local Variables
  1296.   (let (result)
  1297.                     ; Body
  1298.     (cond
  1299.      ((and (> (length file) 7)
  1300.        (equal (substring file -7) "tpl.elc"))
  1301.       (setq result (substring file 0 -7))
  1302.       )
  1303.      ((and (> (length file) 6)
  1304.        (equal (substring file -6) "tpl.el"))
  1305.       (setq result (substring file 0 -6))
  1306.       )
  1307.      ((and (> (length file) 4)
  1308.        (equal (substring file -4) ".tpl"))
  1309.       (setq result (substring file 0 -4))
  1310.       )
  1311.      (t
  1312.       (setq result file)
  1313.       )
  1314.      ) ; cond
  1315.                     ; return
  1316.     result
  1317.     ) ; let
  1318.   ) ; defun tpl-root-of-file-name
  1319.  
  1320. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1321.  
  1322. (defun tpl-undo-keymap ()
  1323.   "Undo keymap for template-mode."
  1324.                     ; Local Variables
  1325.   (let ()
  1326.                     ; Body
  1327.     (use-local-map tpl-saved-map)
  1328.     ) ; let
  1329.   ) ; defun tpl-undo-keymap
  1330.  
  1331. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1332.  
  1333. (defun tpl-unwrap-template (template &optional arg)
  1334.   "Find the enclosing TEMPLATE around point and replace it with
  1335.     whatever is matching the destination placeholder.
  1336.     Optional second argument non-nil causes mark to be placed
  1337.     at the beginning of the resulting region."
  1338.                     ; Local Variables
  1339.   (let (origin wrapper-pair wrapper-begin wrapper-end indent-amount
  1340.            prefix another-wrapper-end start match-start
  1341.            match-stop-marker)
  1342.                     ; Body
  1343.     (setq origin (point))
  1344.     (setq match-stop-marker (make-marker))
  1345.     (setq wrapper-pair (tpl-find-wrappers template))
  1346.     (setq wrapper-begin (nth 0 wrapper-pair))
  1347.     (setq wrapper-end (nth 1 wrapper-pair))
  1348.     (setq indent-amount (nth 2 wrapper-pair))
  1349.     (if (search-backward wrapper-begin (point-min) t)
  1350.     (progn
  1351.       (setq start (point))
  1352.       (search-forward wrapper-begin)
  1353.       (delete-region start (point))
  1354.       (setq match-start (point))
  1355.                     ; Get prefix of line for another try
  1356.                     ;   at matching ending part.
  1357.       (beginning-of-line nil)
  1358.       (setq prefix (buffer-substring (point) match-start))
  1359.       (goto-char match-start)
  1360.       (setq another-wrapper-end (concat (substring wrapper-end 0 1)
  1361.                         prefix
  1362.                         (substring wrapper-end 1)))
  1363.       ) ; progn
  1364.       ; else
  1365.       (error "Enclosing template not found.")
  1366.       ) ; if
  1367.     (if (search-forward wrapper-end (point-max) t)
  1368.     (progn
  1369.       (setq start (point))
  1370.       (search-backward wrapper-end (point-min) t)
  1371.       (delete-region (point) start)
  1372.       (set-marker match-stop-marker (point))
  1373.       ) ; progn
  1374.       ; else
  1375.                     ; This is a hack to fix indented
  1376.                     ;   matches.
  1377.       (if (search-forward another-wrapper-end (point-max) t)
  1378.       (progn
  1379.         (setq start (point))
  1380.         (search-backward another-wrapper-end (point-min) t)
  1381.         (delete-region (point) start)
  1382.         (set-marker match-stop-marker (point))
  1383.         (goto-char match-start)
  1384.         (delete-backward-char (length prefix))
  1385.         (setq match-start (- match-start (length prefix)))
  1386.         ) ; progn
  1387.     ; else
  1388.     (progn
  1389.       (goto-char origin)
  1390.       (error "End of enclosing template not found.")
  1391.       ) ; progn
  1392.     ) ; if ...another...
  1393.       ) ; if
  1394.     (goto-char match-start)
  1395.     (forward-line 1)
  1396.     (if (< (point) (marker-position match-stop-marker))
  1397.     (indent-rigidly (point) (marker-position match-stop-marker)
  1398.             (- 0 indent-amount))
  1399.       ) ; if
  1400.     (goto-char (marker-position match-stop-marker))
  1401.     (set-marker match-stop-marker nil)
  1402.     (if arg
  1403.     (push-mark match-start)
  1404.       ) ; if arg
  1405.     ) ; let
  1406.   ) ; defun tpl-unwrap-template
  1407.  
  1408. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1409.  
  1410. (defun tpl-wrap-template (start stop template)
  1411.   "Replace the region between START and STOP with TEMPLATE,
  1412.     reinserting the replaced region at the destination placeholder.
  1413.     The region is indented rigidly at its insertion column."
  1414.                     ; Local Variables
  1415.   (let (save-expand-option region start-column orig-column)
  1416.                     ; Body
  1417.     (setq save-expand-option tpl-ask-expansion-depth)
  1418.     (setq tpl-ask-expansion-depth 0)
  1419.     (setq region (buffer-substring start stop))
  1420.     (delete-region start stop)
  1421.     (goto-char start)
  1422.     (setq orig-column (current-column))
  1423.     (unwind-protect            ; Protect against nonexistent template
  1424.     (tpl-generate template)
  1425.       (setq start (point))
  1426.       (setq start-column (current-column))
  1427.       (insert region)
  1428.       (indent-rigidly start (point) (- start-column orig-column))
  1429.       (setq tpl-ask-expansion-depth save-expand-option)
  1430.       ) ; unwind-protect
  1431.     (message "Done.")
  1432.     ) ; let
  1433.   ) ; defun tpl-wrap-template
  1434.  
  1435. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1436.  
  1437. (defun tpl-y-or-n-p (msg)
  1438.   "Display MSG and await positive ('y') or negative ('n') response.
  1439.     Differs from 'y-or-n-p' in that it leaves the cursor in the active
  1440.     window, rather than moving to the mode-line."
  1441.                     ; Local Variables
  1442.   (let (answered prompt reply result)
  1443.                     ; Body
  1444.     (setq answered nil)
  1445.     (setq prompt (concat msg "(y or n) "))
  1446.     (while (not answered)
  1447.       (message prompt)
  1448.       (setq reply (read-char))
  1449.       (cond
  1450.        ((char-equal reply ?y)
  1451.     (setq answered t)
  1452.     (setq result t)
  1453.     ) ; (char-equal reply ?y)
  1454.        ((char-equal reply ? )
  1455.     (setq answered t)
  1456.     (setq result t)
  1457.     ) ; (char-equal reply ? )
  1458.        ((char-equal reply ?n)
  1459.     (setq answered t)
  1460.     (setq result nil)
  1461.     ) ; (char-equal reply ?n)
  1462.        ((char-equal reply ?\177)
  1463.     (setq answered t)
  1464.     (setq result nil)
  1465.     ) ; (char-equal reply ?\177)
  1466.        (t
  1467.     (ding)
  1468.     (setq prompt (concat "Please respond 'y' or 'n'.  "
  1469.                  msg "(y or n) "))
  1470.     ) ; t
  1471.        ) ; cond
  1472.       ) ; while (not answered)
  1473.                     ; return
  1474.     result
  1475.     ) ; let
  1476.   ) ; defun tpl-y-or-n-p
  1477.  
  1478. ;;;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1479.  
  1480. ;;; end of tplhelper.el
  1481.