[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Filling woes
From: |
Alan Mackenzie |
Subject: |
Filling woes |
Date: |
Tue, 17 May 2005 20:20:11 +0000 (GMT) |
Hi, Emacs!
I wanted to enhance text-mode (for my own use only, not as a
contribution), so that it would recognise a list of items begun by
parenthesized roman numerals as list items, and fill them as below:
(i) The paragraph recognition code should regard each such list item as a
distinct paragraph, so that M-q and friends leave the paragraph
structure intact;
(ii) Filling, including the auto-fill variety, should indent the second
and subsequent lines of a "roman paragraph" by two spaces.
Should be easy, shouldn't it? Well, yes, but it took me many hours. I
wasn't able to understand the documentation (Emacs manual's pages "Fill
Prefix", "Adaptive Fill"; Elisp's "Adaptive Fill"). It was too vague
for me to get anything definite out of. In particular, there was no
clear description of how Emacs determines the fill prefix for a
paragraph; only inadequate disjoint descriptions of the pertinent
variables. In the end I had to edebugger my way through the filling
code.
And there I found something which I think should be changed: In the
function `fill-context-prefix' (whose purpose is determining the fill
prefix in the given region (usually a paragraph)), the code first tries
to match the start of a line against `adaptive-fill-regexp' and if it
fails, funcalls `adaptive-fill-function', if non-nil.
This is crazy! The default value for `adaptive-fiill-regexp' matches the
null string, so if I want to use `adaptive-fill-function', I've got to
somehow clobber this regexp. Having done that, I would have to
incorporate its functionality into my `adaptive-fill-function'. YUCK!!!
Surely `adaptive-fill-function' should be tried first. MUST be tried
first. Surely? Or have I missed something significant in the filling
mechanism?
Once I'd put this change into fill.el (see the patch below), I was able
to get the formatting I wanted with this code in my .emacs:
#########################################################################
;; Stuff for formatting "Roman lists" in text-mode
(defconst roman-u (regexp-opt '("i" "ii" "iii" "iv" "v" "vi" "vii" "viii"
"ix")))
(defconst roman-t (regexp-opt '("x" "xx" "xxx" "xl" "l" "lx" "lxx" "lxxx"
"xc")))
(defconst roman
(concat "\\(\\(" roman-t "\\)\\(" roman-u "\\)?\\)\\|\\(" roman-u "\\)"))
(defconst p-roman (concat "(\\(" roman "\\))"))
(defconst opt-nl-p-roman (concat "\n?" p-roman )) ; backward-paragraph can go
to the blank line before.
(defun roman-adaptive-fill-prefix ()
"Return a string of 2 spaces iff we're in a \"Roman list\" item."
(save-excursion
(forward-line 0)
(unless (and (looking-at paragraph-start) (not (looking-at
paragraph-separate)))
(backward-paragraph))
(if (looking-at opt-nl-p-roman) " ")))
(defun enable-paren-lists ()
(setq paragraph-start (concat p-roman "\\|" paragraph-start)
adaptive-fill-function 'roman-adaptive-fill-prefix))
(add-hook 'text-mode-hook 'enable-paren-lists)
#########################################################################
Here is the patch to fill.el. (I've only tested with the equivalent
patch on 21.3's fill.el, though.)
2005-05-17 Alan Mackenzie <address@hidden>
* fill.el (fill-context-prefix): Try `adaptive-fill-function'
BEFORE `adaptive-fill-regexp' when determining a fill prefix.
(adaptive-file-function): Minor amendment to doc-string.
*** fill-1.175.el Sat May 14 19:51:44 2005
--- fill-1.175.acm.el Tue May 17 19:37:57 2005
***************
*** 114,120 ****
(defcustom adaptive-fill-function nil
"*Function to call to choose a fill prefix for a paragraph, or nil.
! This function is used when `adaptive-fill-regexp' does not match."
:type '(choice (const nil) function)
:group 'fill)
--- 114,120 ----
(defcustom adaptive-fill-function nil
"*Function to call to choose a fill prefix for a paragraph, or nil.
! nil means the function has not determined the fill prefix."
:type '(choice (const nil) function)
:group 'fill)
***************
*** 229,237 ****
;; Also setting first-line-prefix to nil prevents
;; second-line-prefix from being used.
(cond ;; ((looking-at paragraph-start) nil)
((and adaptive-fill-regexp (looking-at adaptive-fill-regexp))
! (match-string-no-properties 0))
! (adaptive-fill-function (funcall adaptive-fill-function))))
(forward-line 1)
(if (< (point) to)
(progn
--- 229,237 ----
;; Also setting first-line-prefix to nil prevents
;; second-line-prefix from being used.
(cond ;; ((looking-at paragraph-start) nil)
+ ((and adaptive-fill-function (funcall
adaptive-fill-function)))
((and adaptive-fill-regexp (looking-at adaptive-fill-regexp))
! (match-string-no-properties 0))))
(forward-line 1)
(if (< (point) to)
(progn
***************
*** 239,249 ****
(setq start (point))
(setq second-line-prefix
(cond ((looking-at paragraph-start) nil) ;Can it happen ? -stef
((and adaptive-fill-regexp
(looking-at adaptive-fill-regexp))
! (buffer-substring-no-properties start (match-end 0)))
! (adaptive-fill-function
! (funcall adaptive-fill-function))))
;; If we get a fill prefix from the second line,
;; make sure it or something compatible is on the first line too.
(when second-line-prefix
--- 239,249 ----
(setq start (point))
(setq second-line-prefix
(cond ((looking-at paragraph-start) nil) ;Can it happen ? -stef
+ ((and adaptive-fill-function
+ (funcall adaptive-fill-function)))
((and adaptive-fill-regexp
(looking-at adaptive-fill-regexp))
! (buffer-substring-no-properties start (match-end 0)))))
;; If we get a fill prefix from the second line,
;; make sure it or something compatible is on the first line too.
(when second-line-prefix
--
Alan Mackenzie (Munich, Germany)
- Filling woes,
Alan Mackenzie <=