unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* JUSTIFY COMMENT BLOCK elisp function
@ 2009-07-27 16:39 David McCracken
  2009-07-27 21:20 ` Stefan Monnier
  0 siblings, 1 reply; 2+ messages in thread
From: David McCracken @ 2009-07-27 16:39 UTC (permalink / raw)
  To: emacs-devel

I'm not sure how to share this but I have written an elisp function that 
justifies a marked region while inserting a user-defined string at the 
beginning of each line as would be typically found in a comment block. 
The function, justify-region, takes one interactive argument, which 
defines the line prefix. This may be empty or comprise one or more 
characters, including space, for example "#" or "//     " or "rem ". Any 
existing instances of this string that appear at the beginning of lines 
are removed (elsewhere in the line, they are considered part of the 
text) and they are (re)inserted at the beginning of each line 
reformatted to wrap at the fill-column point (typically 80). The 
function is generally language-agnostic but aware of common conventions. 
For example, it splits A-B between - and B but it does not split -B.

;----------------------------- justify-region 
--------------------------------
; Purpose: word-wrap the marked region at the fill-column point (e.g. 
80) with
; the given prefix string on the left edge. This is typically used to 
justify a
; comment block. The prefix comprises 0 or more characters, for example 
;,;;,
; or ;;; for lisp, // for C++, rem for Windows batch, # for sh and make.
;
; Input: this may be called non-interactively with the prefix string 
argument
; pfstring. Interactively, the user is asked for pfstring. This is used
; exactly. If it contains no trailing space, there will be no space 
between it
; and the text. Typically, pfstring is the language's comment character or
; string followed by one space. Instances of pfstring that appear at the
; beginning of a line are considered to be discardable. Any that appear
; elsewhere are considered part of the text and are not disturbed.
;............................... notes 
.........................................
; Operation: this comprises two loops, reduction and expansion, applied 
to each
; line from top to bottom of the region. The reduction loop merges the next
; line with the current one by removing the newline and pfstring (if 
any) at
; the beginning of the next line. This continues until it produces a 
line that
; crosses the fill column point. Then the expansion loop traverses this 
line
; from the end until it finds a whole word that does not cross the 
fill-column.
; The line is split between this and the next word after accounting for 
certain
; character combinations that belong with the next word. For example, 
word-word
; splits to word- and word, but -word cannot split to - and word.
;...............................................................................
(defun justify-region( pfstring )
    "Word-wrap region at fill-column, applying optional prefix at left. 
The prefix
may be nothing or one or more characters.Existing instances of the 
prefix on
the left edge are removed before formatting."
    (interactive "sPrefix string: " )
    (let ((length (string-width pfstring)) count)
    (if mark-active
        (if (> (point) (mark))
        (exchange-point-and-mark))
            ; Else no region marked. Treat cursor line as region.
        (end-of-line)
        (set-mark (point))
        (beginning-of-line))

    ;; If the first line doesn't have the prefix string then insert it now.
    (if (not (looking-at pfstring))
        (insert pfstring))
   
    (catch 'end
        (while t
        (end-of-line)
;; Reduction loop deletes newlines while EOL < fill-column. At each 
reduction,
;; if we see the prefix string, it is removed because it was at the 
beginning
;; of the line before the newline was deleted.
        (while (< (current-column) (1- fill-column)) ; Reduction loop.
            (if (>= (point) (- (mark) 2))
            (progn
                (forward-char 1) ;Leave point at beginning of next line.
                (pop-mark) ; Unmarks region for the few cases that don't.
                (throw 'end 1))
            (delete-char 1)
            (if (looking-at pfstring)
                (delete-char length)) ;kill-word goes too far if 
pfstring length = 1.
            (fixup-whitespace)      ; Normalize to one space.
            (end-of-line)))          ; Close reduction loop.

;; Expansion loop steps back from EOL one word at a time until the point 
is on
;; a word that doesn't cross over the fill-column and breaks the line after
;; that by inserting newline (unless starting point was already less 
than fill-
;; column). The prefix string is inserted on next line if not already there.
        (setq count 0)
        (while (> (current-column) fill-column) ; Expansion loop.
            (backward-word 1)
            (setq count (1+ count)))

;; If the word we intend to move down to the next line is immediately 
preceded
;; by ", ', `, (, or < then bring that along as well. If preceded by - 
itself
;; preceded by space then bring the - character along. This represents 
-word as
;; opposed to word-word. If preceded by the combination </ then bring that.
;; This is for HTML but shouldn't be a problem for other languages.
        (cond
            ((looking-back "</")
            (backward-char 2))
            ((looking-back "[\"\'\`(<]")
            (backward-char 1))
            ((looking-back "[ \t]-")
            (backward-char 1)))

        (if ( > count 0)
            (insert ?\n)
            (forward-char 1))
        (if (not (looking-at pfstring))
            (insert pfstring))))))





^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: JUSTIFY COMMENT BLOCK elisp function
  2009-07-27 16:39 JUSTIFY COMMENT BLOCK elisp function David McCracken
@ 2009-07-27 21:20 ` Stefan Monnier
  0 siblings, 0 replies; 2+ messages in thread
From: Stefan Monnier @ 2009-07-27 21:20 UTC (permalink / raw)
  To: David McCracken; +Cc: emacs-devel

> I'm not sure how to share this but I have written an elisp function that
> justifies a marked region while inserting a user-defined string at the
> beginning of each line as would be typically found in a comment block.

How does it compare to: comment-region + fill-region ?


        Stefan




^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-07-27 21:20 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-27 16:39 JUSTIFY COMMENT BLOCK elisp function David McCracken
2009-07-27 21:20 ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).