home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / misc / num-outline.el < prev    next >
Encoding:
Text File  |  1990-07-22  |  11.7 KB  |  329 lines

  1. ;From utkcs2!emory!samsung!usc!zaphod.mps.ohio-state.edu!tut.cis.ohio-state.edu!ansa.co.uk!ajw Thu Jul 12 13:37:24 EDT 1990
  2. ;Article 3184 of gnu.emacs:
  3. ;Path: utkcs2!emory!samsung!usc!zaphod.mps.ohio-state.edu!tut.cis.ohio-state.edu!ansa.co.uk!ajw
  4. ;>From: ajw@ansa.co.uk (Andrew Watson)
  5. ;Newsgroups: gnu.emacs
  6. ;Subject: outline-regexp still broken
  7. ;Message-ID: <9007121207.AA12843%crippen@ansa.co.uk>
  8. ;Date: 12 Jul 90 12:07:41 GMT
  9. ;References: <487@exodus.Eng.Sun.COM>
  10. ;Sender: daemon@tut.cis.ohio-state.edu
  11. ;Distribution: gnu
  12. ;Organization: GNUs Not Usenet
  13. ;Lines: 312
  14. ;
  15. ;Brian Holtz (holtz@netcord.Eng.Sun.COM) asks:
  16. ;
  17. ;>                            Has anyone even seen
  18. ;> outline mode working for anything other than the default heading-line
  19. ;> pattern of 1 or more asterisks?
  20. ;
  21. ;Yes. I'm apending some code that I wrote, and frequently use, to provide
  22. ;numbered outline headings. All of the hide-subtree/show-subtree things work OK.
  23. ;It doesn't answer Brian's main question, but perhaps people will find it of
  24. ;interest.
  25. ;
  26. ;To use: Go into outline-mode, then (load-library "numbered-outline").
  27. ;Alternatively, I'm also appending a file called document-mode.el, which I use
  28. ;to pull together numbered-outline and Martin Neitzel's gin-mode.
  29. ;M-x document-mode will then do all the work for you. The general roundaboutness
  30. ;of approach is because outline-mode doesn't provide a feature to say whether
  31. ;it's loaded or not - to my mind this is an oversight.
  32. ;
  33. ;       .                           Regards,
  34. ;      / \^
  35. ;     / / \ \                           Andrew
  36. ;    / /   \ \
  37. ;   '=========`        Andrew Watson                Tel:      +44 223 323010
  38. ;  /| |\ | <  |\          APM Ltd, Poseidon House,     Fax:      +44 223 359779
  39. ; / | | \| _> | \      Castle Park,                 UUCP:     mcvax!ukc!ansa!ajw
  40. ; ---------------      Cambridge CB3 0RD, UK        Internet: ajw@ansa.co.uk
  41. ;
  42. ;--First File--First File--First File--First File--First File--First File--First File--
  43. ;;; numbered-outline.el
  44. ;;;
  45. ;;; Andrew Watson (ajw@ansa.co.uk) 3/3/90
  46. ;;;
  47. ;;; This code is distributed without any warranty of any sort.
  48. ;;;
  49. ;;; This code augments outline mode by changing the regexps and things to support the
  50. ;;; notion that a heading is of the form 1.2.3, and by adding  new commands to
  51. ;;; automagically generate next heading labels:
  52. ;;;
  53. ;;; outline-next-heading-along (bound to c-c c-c)
  54. ;;;    Searches back for the previous heading, and insert the next one in
  55. ;;;    sequence, so that 1.2.4.5 -> 1.2.4.6 -> 1.2.4.7 etc
  56. ;;;    Given a prefix argument, generates the next heading at that level.
  57. ;;;    Example: ESC-2 c-c c-c when last heading was 1.4.5.9.2 gives 1.5
  58. ;;;
  59. ;;; outline-next-heading-down (bound to c-c c-e)
  60. ;;;    Inserts a heading at the next nesting level, so that 1.2.4.5 ->
  61. ;;;    1.2.4.5.1 -> 1.2.4.5.1.1
  62. ;;;
  63. ;;; outline-next-heading-up (bound to c-c c-d)
  64. ;;;    Inserts a heading at the next level up, so that 1.2.4.5 -> 1.2.5 -> 1.3
  65. ;;;    With a prefix arg goes that many levels out. Example: ESC-2 c-c c-d when
  66. ;;;    last heading was 1.4.5.9.2 gives 1.4.6
  67. ;;;
  68. ;;; renumber-heading
  69. ;;;    Change the number on this heading without changing the text. The heading
  70. ;;;    number is supplied as an argument, with the default being to search back
  71. ;;;    for the last heading and use the next sequential heading at the level
  72. ;;;    of the current heading.
  73. ;;;
  74. ;;; renumber-region
  75. ;;;    Renumber all the headings in a region, keeping them at the same relative
  76. ;;;    levels as they are at present. The first heading is either supplied as
  77. ;;;    an argument, or inferred in the same fashion as for renumber-heading.
  78. ;;;    (Q: What if supplied argument is at wrong level?)
  79. ;;;
  80. ;;; To do:
  81. ;;;
  82. ;;; renumber-buffer (easy)
  83. ;;;    Renumber all the headings in the buffer. Supplied arg is first heading,
  84. ;;;    defaults to first heading at current level.
  85. ;;;
  86. ;;; subordinate-region
  87. ;;;    Renumber the region so that the levels of the headings relative to each
  88. ;;;    other remains the same, but the first one is subordinated to the
  89. ;;;    immediately preceeding heading.
  90. ;;;
  91. ;;; running-region (bad name)
  92. ;;;    Renumber the region so that the levels of the headings relative to each
  93. ;;;    other remains the same, but the highest level headings in the region run
  94. ;;;    on from the previous heading before the region.
  95. ;;;
  96. ;;; mark-heading
  97. ;;;    Place the region around all the text in the heading containing point.
  98. ;;;    With a heading argument, find and mark that heading and all its children.
  99.  
  100. (provide 'numbered-outline)
  101.  
  102. (defvar component-regexp)
  103. (defvar seperator-regexp)
  104.  
  105. (defvar heading-leader "\n" "String to insert before a heading")
  106. (defvar heading-trailer " " "String to insert after a heading")
  107. (defvar heading-seperator "." "String to use as seperator when inserting heading")
  108.  
  109. (setq component-regexp "[0-9]+")
  110. (setq seperator-regexp "\\.")
  111. (setq outline-regexp (concat component-regexp
  112.                  "\\(" seperator-regexp component-regexp "\\)*"))
  113.  
  114.  
  115. ;;; Basic representation - a heading is represented as a list, each element
  116. ;;; being one component. Hence (length x) = depth of x. List is stored reversed
  117. ;;; to save on garbageful operations when we're bashing the last element.
  118.  
  119. ;;; What heading are we looking-at?
  120.   
  121. (defun outline-heading ()
  122.   (save-excursion
  123.     (if (looking-at component-regexp)
  124.     (nreverse
  125.      (cons (read (current-buffer))
  126.            (progn (backward-char 1) (outline-heading1)))))))
  127.  
  128. (defun outline-heading1 ()
  129.   (if (looking-at seperator-regexp)
  130.       (progn
  131.     (goto-char (match-end 0))      ; end of the seperator
  132.     (if (looking-at component-regexp)
  133.         (progn (goto-char (match-end 0))
  134.            (cons (car (read-from-string     ; do this with setcdr?
  135.                    (buffer-substring (match-beginning 0)
  136.                          (match-end 0))))
  137.              (outline-heading1)))))))
  138.  
  139. (defun outline-level ()
  140.   (length (outline-heading)))
  141.  
  142. ;;; Something to insert a heading at the current point
  143.  
  144. (defun insert-heading (heading where)
  145.   (princ heading-leader where)
  146.   (insert-heading1 heading where)
  147.   (princ heading-trailer where))
  148.  
  149. (defun insert-heading1 (heading where)
  150.   (let ((first (car heading))
  151.     (rest (cdr heading)))
  152.     (if rest
  153.     (progn
  154.       (insert-heading1 rest where)
  155.       (princ heading-seperator where)))
  156.     (princ first where)))
  157.  
  158. ;;; AJW 8/2/90 Change outline-newline-maybe to throw a newline only if point is
  159. ;;; on a line with text. Blank lines get deleted. This may or may not be right ...
  160.  
  161. (defun outline-newline-maybe ()
  162.   (beginning-of-line 1)
  163.   (if (looking-at "^[ \t]*$")    ; if line is blank
  164.       (delete-region (point) (progn (end-of-line 1) (point))) ; delete all chars on it
  165.     (progn (end-of-line 1)
  166.        (newline))))
  167.  
  168. ;;; The three commands at present introduce new headings
  169.  
  170. (defun outline-next-heading-along (arg)
  171.   "Do next heading"
  172.   (interactive "P")
  173.   (if arg
  174.       (outline-insert-absolute-heading arg)
  175.     (outline-insert-relative-heading 0)))
  176.  
  177. (defun outline-next-heading-up (arg)
  178.   "Do next heading up. With prefix arg, go that many levels up."
  179.   (interactive "p")
  180.   (outline-insert-relative-heading arg))
  181.  
  182. (defun outline-next-heading-down ()
  183.   "Insert next most nested heading"
  184.   (interactive)
  185.   (outline-insert-next-heading-down))
  186.  
  187. (define-key outline-mode-map "\C-c\C-c" 'outline-next-heading-along)
  188. (define-key outline-mode-map "\C-c\C-d" 'outline-next-heading-up)
  189. (define-key outline-mode-map "\C-c\C-e" 'outline-next-heading-down)
  190.  
  191. ;;; Thing to find the previous heading and return it
  192.  
  193. (defun outline-previous-heading ()
  194.   (catch 'outline-heading-found
  195.     (save-excursion
  196.       (while (not (bobp))
  197.     (beginning-of-line 0)   ; start of previous line
  198.     (if (looking-at outline-regexp)
  199.         (throw 'outline-heading-found (outline-heading)))))
  200.  
  201.     ;; Nothing found means that the "previous" heading was the zeroth
  202.  
  203.     (list 0)))
  204.  
  205. (defun outline-insert-relative-heading (arg)
  206.   (outline-newline-maybe)
  207.   (let* ((last-heading (outline-previous-heading))
  208.      (last-at-this-level (nthcdr arg last-heading)))
  209.     (if last-at-this-level
  210.     (progn
  211.       (insert-heading (increment-heading last-at-this-level)
  212.               (current-buffer))
  213.       (princ "Last heading was " t)
  214.       (insert-heading1 last-heading t))
  215.       (error "You can't go that far out!"))))
  216.  
  217. (defun outline-insert-absolute-heading (arg)
  218.   (let* ((last-heading (outline-previous-heading))
  219.      (last-depth (length last-heading))
  220.      (x (- last-depth arg)))
  221.     (outline-insert-relative-heading x))) ; h-e-a-v-y !
  222.  
  223.  
  224. (defun outline-insert-next-heading-down ()
  225.   (outline-newline-maybe)
  226.   (let ((last-heading (outline-previous-heading)))
  227.     (insert-heading (cons 1 last-heading) (current-buffer))
  228.     (princ "Last heading was " t)
  229.     (insert-heading1 last-heading t)))
  230.  
  231. ;;; Renumbering things. Note the level of the heading on this line, then look
  232. ;;; back for the last heading and renmber this one to be at the same level as
  233. ;;; it was before, but consistent with the last one. Note that this will quite
  234. ;;; happily make the successor to 2.4 be 2.4.1.1.1.1.1.1.1 if that's what you
  235. ;;; want ... If called with an argument, use that as the values of the last
  236. ;;; heading and increment it to make this one. Otherwise, go find the last one.
  237. ;;; Return this heading as result.
  238.  
  239. (defun renumber-heading ()
  240.   (interactive)
  241.   (renumber-heading1 nil))
  242.  
  243. (defun renumber-heading1 (arg)
  244.   (save-excursion
  245.     (beginning-of-line 1)
  246.     (if (looking-at outline-regexp)
  247.     (let* ((x1 (match-beginning 0))     ; snatch the match
  248.            (x2 (match-end 0))
  249.            (last-heading (or arg (outline-previous-heading)))
  250.            (delta (- (length last-heading) (outline-level)))
  251.            (new-hdg (if (natnump delta)        ; that's >= 0 to you, squire
  252.                 (increment-heading (nthcdr delta last-heading))
  253.               (append (make-list (- delta) 1) last-heading))))
  254.       (delete-region x1 x2)
  255.       (insert-heading1 new-hdg (current-buffer))
  256.       new-hdg)
  257.       (error "No heading on this line"))))
  258.  
  259. ;;; Put this in a function ...
  260.  
  261. (defun increment-heading (x)
  262.   (cons (1+ (car x)) (cdr x)))
  263.  
  264. ;;; Renumber a region - might not work yet ... got to make this interactive, too.
  265. ;;; Must also factor out that nasty concat  put it in a global variable?
  266.  
  267. (defun renumber-region1 (hdg start end)
  268.   (if (> start end)
  269.       (let ((tmp end))
  270.     (setq end start start tmp)))
  271.   (save-excursion
  272.     (goto-char start)
  273.     (while (re-search-forward (concat "[\n\^M]\\(" outline-regexp "\\)") end t)
  274.       (goto-char (match-beginning 1))
  275.       (setq hdg (renumber-heading1 hdg)))))
  276.  
  277. (defun renumber-region (from to)
  278.   (interactive "r")
  279.   (renumber-region1 nil from to))
  280.  
  281. --Second file--Second file--Second file--Second file--Second file--Second file--
  282.  
  283. ;;; Quick hack to hold together all the disparate bits of emacs lisp that I use
  284. ;;; for writing documents.
  285. ;;;
  286. ;;; This code is distributed without any warranty of any sort.
  287. ;;;
  288. ;;; AJW 14/3/89
  289.  
  290.  
  291. (defun autoloadp (x)
  292.   "T if the symbol-function of x is an autoload"
  293.   (and (fboundp x)
  294.        (consp (symbol-function x))
  295.        (eq (car (symbol-function x)) 'autoload)))
  296.  
  297. ;;; Outline-mode hacks the paragraph-start and paragraph-separate regexps
  298. ;;; unmercifully
  299.  
  300. (defun document-mode ()
  301.   "Edit documents with numbered headings, outlining and automatic indentation"
  302.   (interactive)
  303.   (kill-all-local-variables)
  304.   (make-local-variable 'paragraph-ignore-fill-prefix)
  305.   (setq paragraph-ignore-fill-prefix t)
  306.   (setq paragraph-separate "^\\s *$")
  307.   (setq paragraph-start "^\\s *$")
  308.   (if (and (featurep 'numbered-outline)
  309.        (autoloadp 'outline-mode))
  310.       (progn
  311.     (outline-mode)  ; will autoload
  312.     (load-library "numbered-outline"))  ; re-load over the top
  313.     (outline-mode)
  314.     (require 'numbered-outline))
  315.   (require 'gin-mode)
  316.   (gin-mode 1) ; switch it on
  317.   (setq gin-left-hang-indent-re 
  318.     "\\s *\\([0-9]+[.)]\\|[ivx]+)\\|[-*]\\|Editorial:\\|Action:\\)\\s +")
  319.   (setq gin-retain-indent-re "[-+>]+[ \t]*\\|[ \t]+")
  320.   (setq paragraph-ignore-fill-prefix t)
  321.   (setq paragraph-separate "^\\s *$")
  322.   (setq paragraph-start "^\\s *$"))  
  323.  
  324. (defun forward-document-paragraph ()
  325.   (interactive)
  326.   (re-search-forward "^\\s *$"))
  327.  
  328.  
  329.