[comp.emacs] gin-mode for GNU Emacs

jackr@dblues.wpd.sgi.com (John Repenning) (12/04/90)

I have a copy of a minor mode, called ``gin-mode'', which modifies
text-mode so that the indentation functions guess the appropriate
indentation and follow it - no more set-fill-prefix!  And, no more
"ah, shoot!  I forgot to reset set-fill-prefix" either!!!  The code
was written by Martin Neitzel, around a year ago, and I believe I got
it (indirectly) from this news group, so I wont repost it (but if
someone wants it, I'd be happy to provide you a copy - email me).

However, I've found what appears to be a simple, minor bug in it.  The
code that handles hanging indents doesn't recognize the ones that look
like this:

	1. 	Paragraph about something or other, long enough to
		require several lines
	...

This recognition is controled by a regular expression, which seems to
be trying to include this format, but misses it by just a hair:
instead of being defined like this:

(defvar gin-left-hang-indent-re
  "\\s *\\([-*]\\|([a-zA-Z0-9])\\|[a-zA-Z0-9]\\.?:]?\\)\\s +"
  "*Regexp that defines a hanging indent of a paragraph.
If it is seen by gin-guess-prefix, the next lines are indented with
white space beyond the hanging indent.  Setting this variable makes
it buffer-local.")

...it shouls be like this:

(defvar gin-left-hang-indent-re
  "\\s *\\([-*]\\|([a-zA-Z0-9])\\|[a-zA-Z0-9]\\.?:?]?\\)\\s +"
  "*Regexp that defines a hanging indent of a paragraph.
If it is seen by gin-guess-prefix, the next lines are indented with
white space beyond the hanging indent.  Setting this variable makes
it buffer-local.")

The change is in the sequence "\\.?:]?", near the end - I've made the
colon optional, like the period and the bracket.

Or, maybe the sequence should just be "[].:]?", to permit zero or one
of any of these characters - strictly, the present code allows a form
like 

	1.:]	stuff

...which doesn't look like anything anyone might want.

I thought of sending this change to Martin (with whom I've
corresponded before), but I've lost his new address.  (Do you read
this group, Martin?  Do you agree with my interpretation?)

Jack Repenning
jackr@dblues.wpd.sgi.com

ralph@laas.fr (Ralph P. Sobek) (12/06/90)

I have not looked into the problem of mis-specified REGEXPs.

But, I have patched gin-mode to properly indent paragraphs and I even
added gin-indent-region.  The problem with the original gin-mode is
that it uses the free (or special) variable `fill-prefix', and when
one gin-fill's a paragraph or a region it eventually calls
fill-paragraph or fill-region respectively.  When one gin-fill's one
wants to add the gin guessed prefix (gin-fill-prefix) to all lines in
the paragraph that do *not* already have it.

The problem is in paragraph.el: both forward-paragraph and backward
paragraph use fill-prefix in order to isolate the paragraph.  And
gin-mode has already assigned fill-prefix from its gin-fill-prefix.  I
would suggest that fill-prefix become an optional argument to all the
functions that use it rather than be a specail variable.  I do *not*
know if this might break some other code!!

In the mean time, here are the context diffs for gin-mode that work
for me.  Let me know if you have problems.  Basically, I just inserted
the source code for fill-paragraph and fill-region directly into
gin-mode. 

*** /usr/local/emacs/lisp/local/gin.el	Fri Nov  2 20:46:59 1990
--- gin.el	Mon Nov 12 15:46:44 1990
***************
*** 43,48 ****
--- 43,51 ----
  ;; 	* what line beginnings are really hanging indents.  The
  ;; 	  standard setup recognizes the stars used right here,
  ;; 	  enumerations, and some more...
+ 
+ ;; Change History:
+ ;; Nov 9, 1990 - Ralph P.Sobek - Added gin-fill-region.
  
  ;; The guessing stuff
  
***************
*** 98,107 ****
  With arg, also justify."
    (interactive "P")
    (if gin-mode
!       (let ((fill-prefix (gin-guess-prefix)))
! 	(funcall 'gin-old-fill-paragraph arg))
      (funcall 'gin-old-fill-paragraph arg)))
  
  (defun gin-do-auto-fill()
    (if gin-mode
        (let ((fill-prefix (gin-guess-prefix)))
--- 101,138 ----
  With arg, also justify."
    (interactive "P")
    (if gin-mode
!       (let ((gin-fill-prefix (gin-guess-prefix))
! 	    end)
! 	(save-excursion
! 	  (forward-paragraph)
! 	  (or (bolp) (newline 1))
! 	  (setq end (point))
! 	  (backward-paragraph)
! 	  (let ((fill-prefix gin-fill-prefix))
! 	    (fill-region-as-paragraph (point) end arg))))
      (funcall 'gin-old-fill-paragraph arg)))
  
+ (defun gin-fill-region (from to &optional justify-flag)
+   "fill-region in Gin mode, tries to guess the appropriate fill-prefix.
+ Prefix arg (non-nil third arg, if called from program)
+ means justify as well."
+   (interactive "r\nP")
+   (if gin-mode
+       (let ((gin-fill-prefix (gin-guess-prefix)))
+ 	(save-restriction
+ 	  (narrow-to-region from to)
+ 	  (goto-char (point-min))
+ 	  (while (not (eobp))
+ 	    (let* ((initial (point))
+ 		  (end (progn
+ 			 (forward-paragraph 1) (point)))
+ 		  (fill-prefix gin-fill-prefix))
+ 	      (forward-paragraph -1)
+ 	      (if (>= (point) initial)
+ 		  (fill-region-as-paragraph (point) end justify-flag))
+ 	      (goto-char end)))))
+     (funcall 'gin-old-fill-region from to justify-flag)))
+ 
  (defun gin-do-auto-fill()
    (if gin-mode
        (let ((fill-prefix (gin-guess-prefix)))
***************
*** 115,120 ****
--- 146,154 ----
  (defconst gin-old-fill-paragraph nil
    "Keeps the true fill-paragraph function during Gin mode.")
  
+ (defconst gin-old-fill-region nil
+   "Keeps the true fill-region function during Gin mode.")
+ 
  (defconst gin-old-do-auto-fill nil
    "Keeps the true do-auto-fill function during Gin mode.")
  
***************
*** 121,131 ****
--- 155,167 ----
  (defun gin-overlay-functions()
    "Undermine emacs with Gin stuff."
    (fset 'fill-paragraph (symbol-function 'gin-fill-paragraph))
+   (fset 'fill-region (symbol-function 'gin-fill-region))
    (fset 'do-auto-fill (symbol-function 'gin-do-auto-fill)))
  
  (defun gin-restore-originals ()
    "Throw gin-mode functions out everywhere."
    (fset 'fill-paragraph (symbol-function 'gin-old-fill-paragraph))
+   (fset 'fill-region (symbol-function 'gin-old-fill-region))
    (fset 'do-auto-fill (symbol-function 'gin-old-do-auto-fill)))
  
  (if (boundp 'gin-mode)
***************
*** 137,142 ****
--- 173,179 ----
    (make-variable-buffer-local 'gin-left-hang-indent-re)
    (make-variable-buffer-local 'gin-retain-indent-re)
    (fset 'gin-old-fill-paragraph (symbol-function 'fill-paragraph))
+   (fset 'gin-old-fill-region (symbol-function 'fill-region))
    (fset 'gin-old-do-auto-fill (symbol-function 'do-auto-fill))
    (gin-overlay-functions))
  
***************
*** 151,160 ****
  two regexps 'gin-left-hang-indent-re' and 'gin-retain-indent-re', see
  their documentation.
  
! When Gin mode is active, auto-filling and fill-paragraph will both use
! a \"guessed\" value as fill-prefix."
  
    (interactive "P")
    (setq gin-mode
  	(if (null arg) (not gin-mode)
  	  (> (prefix-numeric-value arg) 0)))
--- 188,197 ----
  two regexps 'gin-left-hang-indent-re' and 'gin-retain-indent-re', see
  their documentation.
  
! When Gin mode is active, auto-filling, fill-paragraph, and fill-region
! will both use a \"guessed\" value as fill-prefix."
  
    (interactive "P")
    (setq gin-mode
  	(if (null arg) (not gin-mode)
  	  (> (prefix-numeric-value arg) 0)))
--
Ralph P. Sobek			  Disclaimer: The above ruminations are my own.
ralph@laas.fr				   Addresses are ordered by importance.
ralph@laas.uucp, or ...!uunet!laas!ralph		
If all else fails, try:				      sobek@eclair.Berkeley.EDU
===============================================================================
Reliable software should kill people reliably! -Andy Mickel, Pascal News #13,78