[comp.emacs] Enhancement to scribe.el

lrs@Sun.COM@wobegon.UUCP (Lynn Slater) (05/20/87)

GNU Emacs 18.38.4 of Thu Mar 19 1987 on wobegon (berkeley-unix)

The following enhancements were made at Silvar-Lisco to scribe.el.

It works as is. However, I direct your attention to the function
"find-scribe-args". There should be a better way than mine.
Suggestions are welcome.

I would like to also direct your attention to the changes listed under
"Misc fix".  These are safe on my emacs setup but may interact
destructively with other (unknown to me) changes or enhancements.

The changes offer a fuller subset of scribe commands directly
accessible through the scribe-mode-map. For consistency, only a single
type of brackets "[]" are used.  Added features include a C-template
like facility, simple raising and lowering of document header levels,
a means to add version information to parts of scribe (-draft)
documents, and support of indented scribe source.

-------------------------cut here-------------------------
*** scribe.el~	Tue May 19 15:27:46 1987
--- scribe.el	Tue May 19 16:18:47 1987
***************
*** 1,5 ****
--- 1,6 ----
  ;; scribe mode, and its ideosyncratic commands.
  ;; Copyright (C) 1985 Free Software Foundation, Inc.
+ ;; Copyright (C) 1987 Free Software Foundation, Inc.
  
  ;; This file might become part of GNU Emacs.
  
***************
*** 18,23 ****
--- 19,61 ----
  ;; copyright notice and this notice must be preserved on all copies.
  
  
+ ;; =========================================================================
+ ;; Revised by Lynn Slater, Silvar-Lisco,  UUCP: ...!sun!silvlis!lrs
+ ;; (415) 853-6336 1080 Marsh Rd. Menlo Park, CA 94025-1053 USA
+ ;;   On 1-APR-87 (no fooling), revisions tagged with ";; lrs"
+ ;;   Rights assigned to the Free Software Foundation, Inc
+ ;;
+ ;; Major changes from 18.38 and 18.44 releases
+ ;;  1. Made functions use the square brackets "[]" consistently.
+ ;;  2. Enriched the set of scribe formatting commands bound
+ ;;     to scribe mode keys. Did minimal changes to existing bindings.
+ ;;     In particular, added scribe-comment, scribe-paragraph,
+ ;;     scribe-appendix, scribe-subparagraph, scribe-footnote,
+ ;;     scribe-itemize, scribe-enumerate, scribe-description,
+ ;;     and scribe-verbatim.
+ ;;  3. Added commands to change the levels of headings in a buffer.
+ ;;     I.E. Paragraphs to sections and vice versa.  Am not satisfied
+ ;;     with it yet.  A) The knowledge of what commands transform into
+ ;;     other commands is hardcoded.  I would prefer a user-settable list.
+ ;;     B) I would prefer a fcn smarter than keyboard macros.  But for
+ ;;     the effort invested, they work very well.
+ ;;  4. Added scribe-version function that inserts a source control footnote.
+ ;;     This uses "advanced" scribe features but seems to work anyway.
+ ;;     Sorry about it not being real understandable.
+ ;;  5. Added (at end of this file) changes by Warren Cory for scribe keyword
+ ;;     templates.
+ ;;  6. Added ability to have indented-mode like indents within scribe.
+ ;;     Bound toggling fcn to ^c^i  command for those times the indentation
+ ;;     gets in the way.
+ ;;  7. Made the prefix argument cause most scribe commands to wrap around
+ ;;     the region rather than insert at point.  This was clumsy and could
+ ;;     use a emacs hacker inspection of its comments.
+ ;;  8. To get around a possible emacs defects, made scribe (and all
+ ;;     other) buffers always have a region defined. Emacs developers,
+ ;;     please consider for general adoption.
+ ;;
+ ;;  If only were allowed LaTex, but until then . . .
+ 
  (defvar scribe-mode-syntax-table nil
    "Syntax table used while in scribe mode.")
  
***************
*** 75,91 ****
    (define-key scribe-mode-map "[" 'scribe-parenthesis)
    (define-key scribe-mode-map "{" 'scribe-parenthesis)
    (define-key scribe-mode-map "<" 'scribe-parenthesis)
    (define-key scribe-mode-map "\^cc" 'scribe-chapter)
    (define-key scribe-mode-map "\^cS" 'scribe-section)
    (define-key scribe-mode-map "\^cs" 'scribe-subsection)
    (define-key scribe-mode-map "\^ce" 'scribe-insert-environment)
!   (define-key scribe-mode-map "\^c\^e" 'scribe-bracket-region-be)
    (define-key scribe-mode-map "\^c[" 'scribe-begin)
    (define-key scribe-mode-map "\^c]" 'scribe-end)
    (define-key scribe-mode-map "\^ci" 'scribe-italicize-word)
    (define-key scribe-mode-map "\^cb" 'scribe-bold-word)
!   (define-key scribe-mode-map "\^cu" 'scribe-underline-word))
  
  (defun scribe-mode ()
    "Major mode for editing files of Scribe (a text formatter) source.
  Scribe-mode is similar text-mode, with a few extra commands added.
--- 113,160 ----
    (define-key scribe-mode-map "[" 'scribe-parenthesis)
    (define-key scribe-mode-map "{" 'scribe-parenthesis)
    (define-key scribe-mode-map "<" 'scribe-parenthesis)
+ 
+   ;; Scribe commands  "@command[]"
    (define-key scribe-mode-map "\^cc" 'scribe-chapter)
+   (define-key scribe-mode-map "\^cA" 'scribe-appendix)              ;; lrs
+   (define-key scribe-mode-map "\^cp" 'scribe-paragraph)             ;; lrs
+   ;;  pseodo scribe command, used with up-scale and down-scale
+   (define-key scribe-mode-map "\^cq" 'scribe-subparagraph)          ;; lrs
+   ;; Note: redefined key follows
+   ;; (define-key scribe-mode-map "\^cP" 'scribe-paragraph)          ;; lrs
    (define-key scribe-mode-map "\^cS" 'scribe-section)
    (define-key scribe-mode-map "\^cs" 'scribe-subsection)
+   (define-key scribe-mode-map "\^cf" 'scribe-footnote)              ;; lrs
+   (define-key scribe-mode-map "\^c\^c" 'scribe-comment)             ;; lrs
+ 
+   ;; scribe environments "@Begin[x]  @End[x]
    (define-key scribe-mode-map "\^ce" 'scribe-insert-environment)
!   ;; below fcn made obsolete by lrs, but kept anyway
!   (define-key scribe-mode-map "\^c\^e" 'scribe-bracket-region-be)   
!   (define-key scribe-mode-map "\^c0" 'scribe-itemize)               ;; lrs
!   (define-key scribe-mode-map "\^c1" 'scribe-enumerate)             ;; lrs
!   (define-key scribe-mode-map "\^cd" 'scribe-description)           ;; lrs
!   (define-key scribe-mode-map "\^cv" 'scribe-verbatim)              ;; lrs
! 
!   ;; 
    (define-key scribe-mode-map "\^c[" 'scribe-begin)
    (define-key scribe-mode-map "\^c]" 'scribe-end)
+ 
+   ;; scribe commands wrapped around a word
    (define-key scribe-mode-map "\^ci" 'scribe-italicize-word)
    (define-key scribe-mode-map "\^cb" 'scribe-bold-word)
!   (define-key scribe-mode-map "\^cu" 'scribe-underline-word)
  
+   ;; scribe special editing effects
+   (define-key scribe-mode-map "\^c>" 'scribe-down-scale)            ;; lrs
+   (define-key scribe-mode-map "\^c<" 'scribe-up-scale)              ;; lrs
+   (define-key scribe-mode-map "\^c\^i" 'scribe-toggle-indent-mode)  ;; lrs
+   (define-key scribe-mode-map "\^c@" 'sc-match-key)                 ;; wec  
+ 
+   ;; special scribe formatting effects
+   (define-key scribe-mode-map "\^c\^v" 'scribe-version)             ;; lrs
+   )
+ 
  (defun scribe-mode ()
    "Major mode for editing files of Scribe (a text formatter) source.
  Scribe-mode is similar text-mode, with a few extra commands added.
***************
*** 119,131 ****
    (setq comment-end "]")
    (make-local-variable 'paragraph-start)
    (setq paragraph-start (concat "\\(^[\n\f]\\)\\|\\(^@\\w+["
!                                  scribe-open-parentheses
                                  "].*["
!                                  scribe-close-parentheses
                                  "]$\\)"))
    (make-local-variable 'paragraph-separate)
    (setq paragraph-separate (if scribe-fancy-paragraphs
                                 paragraph-start "^$"))
    (make-local-variable 'compile-command)
    (setq compile-command (concat "scribe " (buffer-file-name)))
    (set-syntax-table scribe-mode-syntax-table)
--- 188,203 ----
    (setq comment-end "]")
    (make-local-variable 'paragraph-start)
    (setq paragraph-start (concat "\\(^[\n\f]\\)\\|\\(^@\\w+["
!                                 scribe-open-parentheses
                                  "].*["
!                                 scribe-close-parentheses
                                  "]$\\)"))
    (make-local-variable 'paragraph-separate)
    (setq paragraph-separate (if scribe-fancy-paragraphs
                                 paragraph-start "^$"))
+   ;; lrs improvement for indented scribe mode
+   (make-local-variable 'indent-line-function)        ;; lrs
+   (setq indent-line-function 'indent-relative-maybe) ;; lrs
    (make-local-variable 'compile-command)
    (setq compile-command (concat "scribe " (buffer-file-name)))
    (set-syntax-table scribe-mode-syntax-table)
***************
*** 171,179 ****
                  (setq ccoun (1+ ccoun))))
      (if (>= ccoun (length scribe-open-parentheses))
          (progn (goto-char epos)
!                (insert "@end(" string ")")
                 (goto-char spos)
!                (insert "@begin(" string ")"))
        (goto-char epos)
        (insert (aref scribe-close-parentheses ccoun))
        (goto-char spos)
--- 243,251 ----
                  (setq ccoun (1+ ccoun))))
      (if (>= ccoun (length scribe-open-parentheses))
          (progn (goto-char epos)
!                (insert "@End[" string "]") ;; lrs
                 (goto-char spos)
!                (insert "@Begin[" string "]")) ;; lrs
        (goto-char epos)
        (insert (aref scribe-close-parentheses ccoun))
        (goto-char spos)
***************
*** 182,187 ****
--- 254,270 ----
        (forward-char 3)
        (skip-chars-forward scribe-close-parentheses))))
  
+ (defun scribe-toggle-indent-mode ()
+   "Toggles the meaning of indentation from that of indented text mode
+    and that of text mode."
+    (interactive)
+   (if (eq   indent-line-function 'indent-relative-maybe)
+       (setq  indent-line-function 'indent-to-left-margin)
+     (setq indent-line-function 'indent-relative-maybe))
+     (message "Indentation behavior toggled.")
+     )
+ 
+ 
  (defun scribe-underline-word (count)
    "Underline COUNT words around point by means of Scribe constructs."
    (interactive "p")
***************
*** 218,223 ****
--- 301,374 ----
    (scribe-envelop-word "Chapter" 0)
    (re-search-forward (concat "[" scribe-open-parentheses "]")))
  
+ (defun scribe-comment (argument &optional min max) ;; lrs
+   "With no argument, inserts @Comment[] at current point
+     With universal argument, will wrap region in a comment environment."
+   (interactive "P \nr")
+   (if argument
+       (scribe-bracket-region-be "Comment" min max)
+     (scribe-simple-comment)
+     ))
+ 
+ (defun scribe-simple-comment () ;; lrs
+   "Inserts a blank comment command at the current point"
+   ;;(interactive)
+   (insert "\n")
+   (forward-char -1)
+   (scribe-envelop-word "Comment" 0)
+   (re-search-forward (concat "[" scribe-open-parentheses "]")))
+ 
+ (defun scribe-appendix () ;; lrs
+   (interactive)
+   (insert "\n")
+   (forward-char -1)
+   (scribe-envelop-word "Appendix" 0)
+   (re-search-forward (concat "[" scribe-open-parentheses "]")))
+ 
+ (defun scribe-footnote () ;; lrs
+   (interactive)
+   (insert "\n")
+   (forward-char -1)
+   (scribe-envelop-word "Foot" 0)
+   (re-search-forward (concat "[" scribe-open-parentheses "]")))
+ 
+ (defun scribe-paragraph () ;; lrs
+   (interactive)
+   (insert "\n")
+   (forward-char -1)
+   (scribe-envelop-word "Paragraph" 0)
+   (re-search-forward (concat "[" scribe-open-parentheses "]")))
+ 
+ (defun scribe-subparagraph () ;; lrs
+   (interactive)
+   (insert "\n")
+   (forward-char -1)
+   (insert "@Comment[Subparagraph]")
+   (scribe-envelop-word "b" 0)
+   (forward-char -1)
+   ;;(re-search-forward (concat "[" scribe-open-parentheses "]"))
+   )
+ 
+ (defun scribe-enumerate () ;; lrs
+   ;; bound to scrivbe-1 because it makes numbered lists
+   (interactive)
+   (scribe-insert-environment "Enumerate"))
+ 
+ (defun scribe-itemize () ;; lrs
+   ;; bound to scribe-1 because it makes numbered lists
+   (interactive)
+   (scribe-insert-environment "Itemize"))
+ 
+ (defun scribe-verbatim () ;; lrs
+   (interactive)
+   (scribe-insert-environment "Verbatim"))
+ 
+ (defun scribe-description () ;; lrs
+   (interactive)
+   (scribe-insert-environment "Description")
+   (insert "@/ @Multiple[]")
+   )
+ 
  (defun scribe-section ()
    (interactive)
    (insert "\n")
***************
*** 232,252 ****
    (scribe-envelop-word "SubSection" 0)
    (re-search-forward (concat "[" scribe-open-parentheses "]")))
  
  (defun scribe-bracket-region-be (env min max)
    (interactive "sEnvironment: \nr")
    (save-excursion
      (goto-char max)
!     (insert "@end(" env ")\n")
      (goto-char min)
!     (insert "@begin(" env ")\n")))
  
! (defun scribe-insert-environment (env)
!   (interactive "sEnvironment: ")
!   (scribe-bracket-region-be env (point) (point))
!   (forward-line 1)
!   (insert ?\n)
!   (forward-char -1))
  
  (defun scribe-insert-quote (count)
    "If scribe-electric-quote is non-NIL, insert ``, '' or \" according
  to preceding character.  With numeric arg N, always insert N \" characters.
--- 383,462 ----
    (scribe-envelop-word "SubSection" 0)
    (re-search-forward (concat "[" scribe-open-parentheses "]")))
  
+ 
+ (defun scribe-version () ;; lrs
+   "Inserts a footnote that will give the name of the file,
+    who was the Author and on what date;
+    when it was last modified; and
+    who scribed it and when.
+    Is best used at the start of every file in a Chapter, Section or Appendix.
+    It may be used anywhere, even inside the brackets of these commands
+ 
+    To get the version info, include -draft AFTER the file names in the
+    scribe command. Ex: scribe file1.mss file2.mss -draft"
+   (interactive)
+   (insert (concat
+            "\n@Case[Draft, 1 \"@begin[Text, Break off, Size=10]"
+            "\n@Foot[Source File: @Value[SourceFile]@*"
+            "\n@ @ @ @  Author: "
+            (user-full-name)
+            " on "
+            (find-todays-date)
+            "@*"
+            "\n@ @ @ @  Last Modified: @Value[FileDate]@*"
+            "\n@ @ @ @  Scribed by @Value[Username] on @Value[Date]  @ @Value[time]]"
+            "\n@end[Text]\"]"
+            )))
+ 
  (defun scribe-bracket-region-be (env min max)
+   "Inserts a scribe environment aroung the region.  This function is
+    obsolete for interactive calling , just supply an argument to
+    scribe-insert-environment instead of using this function." ;; lrs
    (interactive "sEnvironment: \nr")
    (save-excursion
      (goto-char max)
!     (insert "@End[" env "]\n");; lrs
      (goto-char min)
!     (insert "@Begin[" env "]\n")));; lrs
  
! (defun scribe-insert-environment (env) ;; lrs altered
!   "If called interactively, prompts for name of scribe environment, otherwise
!    accepts environment as only argument.  Creates a pair of scribe begin
!    and end's inserted at the point.  If a prefix argument is supplied,
!    the begin and ends are inserted around the region."
!   (interactive "sEnvironment:")
!   (let ((arg-min-max (call-interactively 'find-scribe-args)) ;; <-! <-! <-!
!         ;; This is really clutzy, but I know of no other way to get argument
!         ;; and region data in a nested fcn without hacking C code.
!         ;; I would consider this a gnu-emacs defect.
!         ;; I understand the desireability for the speed of C, but lisp callable
!         ;; primitives are still needed for  the purposes of easy extensibility.
!         ;;
!         ;; It is also unfortionate that the interactive argument fetching
!         ;; only works for the first function called.
!         )
!     (if (car arg-min-max)
!         (scribe-bracket-region-be env  (car (cdr arg-min-max))
!                                   (car (cdr (cdr arg-min-max))))
!       (scribe-bracket-region-be env (point) (point)))
!     (forward-line 1)
!     (insert ?\n)
!     (forward-char -1)))
  
+ (defun find-scribe-args (argument min max) ;; lrs HACK! HACK! HACK! HACK!
+   "This functions sole purpose is to return to its lisp caller
+    certain values that are available in C code and available to the
+    top level function (through 'interactive) but not available
+    to nested functions.  This is the only workaround if a function
+    is called from more than one place and all the data cannot be passed
+    down in all cases.
+ 
+    Suggestion: ALL options of interactive should have direct lisp callable
+    equivilents."
+   (interactive "P \nr")
+   (list argument min max))
+ 
+ 
  (defun scribe-insert-quote (count)
    "If scribe-electric-quote is non-NIL, insert ``, '' or \" according
  to preceding character.  With numeric arg N, always insert N \" characters.
***************
*** 305,307 ****
--- 515,677 ----
                                     scribe-open-parentheses)))
            (save-excursion
              (insert (aref scribe-close-parentheses paren-char)))))))
+ 
+ 
+  ;; ======= functions to up grade or downgrade a file ;; lrs
+ (fset 'scribe-down-scale ;; lrs
+       (concat
+        "<xreplace-regexp
+        "<xreplace-regexp
+        "<xreplace-regexp
+        "<xreplace-regexp
+        "<xreplace-regexp
+ 
+ (fset 'scribe-up-scale ;; lrs
+       (concat
+        "<xreplace-regexp
+        "<xreplace-regexp
+        "<xreplace-regexp
+        "<xreplace-regexp
+        ))
+ 
+ 
+ ;; Misc fix ;; lrs
+ ;; The interactive function barfs on "\nr" if the region is not set
+ ;; yet.  I consider this to be a defect in emacs because
+ ;;  1. There is not a "safe" alternative to \nr
+ ;;  2. As a user, I always think that I have a region
+ ;;  3. As a developer, I cannot write functions that use the region in
+ ;;  some cases and not in others.  The scribe-comment command above
+ ;;  does not use the region unless there is an argument.  You
+ ;;  cannot call this function immediately after finding a file because
+ ;;  the region is not set, even if you were using the regionless operation.
+ ;;  Perhaps I can get around this by adopting a convention that
+ ;;  all functions that use the region must use it all the time and
+ ;;  must be called by functions that check for the region. (But note that
+ ;;  there is no function that can check for the region without also
+ ;;  generating a disturbing message to the user in case of error.)
+ ;;
+ ;;  The best solution is to be sure that there is always a region!
+ ;;  This should go into the filesys stuff, but for now, I shall
+ ;;  do it using a provided hook.  Hopefully the scribe mode stuff is
+ ;;  loaded before the hook is checked.
+ 
+ 
+ (defun push-mark-quietly (&optional location message)
+   "An argumentless version of push mark that generates no message by default."
+   (push-mark location (not message)))
+ 
+ ;; (if (not (memq 'push-mark-quietly find-file-hooks))
+ ;;     (setq find-file-hooks (cons 'push-mark-quietly find-file-hooks)))
+ 
+ 
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;;; scribe.el
+ ;;; 86/11/14 wec Warren E. Cory, Silvar-Lisco
+ ;;;
+ ;;; This file defines templates for various SCRIBE constructs.
+ ;;; A template is activated by typing a SCRIBE keyword
+ ;;;    immediately followed by C-c at-sign "@".
+ ;;; Unlike the C templates, these templates do not use
+ ;;;    recursive-edit.
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ 
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ 
+ 
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;;; Predicate:  Is point immediately preceded by string in key?
+ ;;; Exact match is required; no regular expression syntax or
+ ;;; case conversion.
+ ;;;
+ (defun c-preceded-by-p (key) "\
+ Return t if point is immediately preceded by string in key.\n\
+ Exact match is required; no regular expression syntax or case\n\
+ conversion is performed."
+     (interactive "sMatch string:  ")
+     (cond (  (< (- (point) (length key)) (point-min))
+              nil)
+           (  t
+              (equal (buffer-substring (- (point) (length key))
+                                       (point))
+                     key))))
+ 
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;;; Is key found in list match-list?
+ ;;;
+ (defun sc-match-any (key match-list)
+ "Return t if KEY is found in list MATCH-LIST; nil otherwise."
+     (interactive "\
+ sMatch string KEY:  \n\
+ xMatch set MATCH-LIST:  ")
+     (progn
+         (while
+             match-list
+             (if (equal key (car match-list))
+                 (progn (setq key nil) (setq match-list nil))
+                 (setq match-list (cdr match-list))))
+         (null key)))
+ 
+ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ 
+ (defun sc-match-key () "\
+ If point is immediately preceded by a SCRIBE keyword, enter\n\
+    a template for that keyword.  Most environment names are\n\
+    recognized. If Prefix argument, place template around the region"
+   (interactive)
+   (let ((sc-key (downcase (buffer-substring
+                            (save-excursion (forward-word -1) (point))
+                            (point)))))
+     (message "found=%s" sc-key)
+     (cond
+      ( (equal sc-key "figure")
+        (progn
+          (delete-region
+           (point)
+           (progn (forward-word -1) (point)))
+          (insert "@begin[figure]")
+          (newline 2)
+          (insert "@caption[]")
+          (newline)
+          (insert "@tag[]")
+          (newline)
+          (insert "@end[figure]")
+          (next-line -2)
+          (end-of-line)
+          (forward-char -1)))
+      ( (sc-match-any
+         sc-key
+         (list
+          "+" "-" "abstract" "b" "black" "blue" "c"
+          "center" "copyright" "copyrightnotice"
+          "corollary" "cyan" "dark" "definition"
+          "description" "display" "down" "enumerate"
+          "equation" "example" "f0" "f1" "f2" "f3"
+          "f4" "f5" "f6" "f7" "f8" "f9"
+          "fileexample" "float" "flushleft"
+          "flushright" "format" "fullpagefigure"
+          "fullpagetable" "g" "green" "group"
+          "heading" "i" "inputexample" "itemize"
+          "lemma" "magenta" "majorheading" "math"
+          "mathdisplay" "minus" "multiple" "o"
+          "outputexample" "p" "plus"
+          "programexample" "proof" "proposition"
+          "quotation" "r" "red" "researchcredit"
+          "scr" "sr" "subheading" "t" "table" "text"
+          "theorem" "titlebox" "titlepage"
+          "transparent" "u" "un" "up" "ux"
+          "verbatim" "verse" "w" "white" "yellow"))
+        (progn
+          (delete-region
+           (point)
+           (progn (forward-word -1) (point)))
+          ;;(insert (concat "@begin[" sc-key "]"))
+          ;;(newline 2)
+          ;;(insert (concat "@end[" sc-key "]"))
+          ;;(next-line -1)
+          (scribe-insert-environment sc-key)
+          ))
+      ( t
+        (call-interactively 'self-insert-command)))
+     ))
+