aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1995-01-19 04:20:52 +0000
committerRichard M. Stallman1995-01-19 04:20:52 +0000
commit0cb08f98380da55714e253028eaf57c5b6afa217 (patch)
tree9e7038a4be754fabcc0308103896b1f07f65a612
parent106b6d0e36341b7b6a438c8a1df546205bb59726 (diff)
downloademacs-0cb08f98380da55714e253028eaf57c5b6afa217.tar.gz
emacs-0cb08f98380da55714e253028eaf57c5b6afa217.zip
(set-justification): New function.
(set-justification-{none,left,right,full,center}): New functions. (fill-region-as-paragraph, fill-region, justify-current-line): New arg NOSQUEEZE defeats normal removal of extra whitespace. (fill-region-as-paragraph, fill-region) (fill-nonuniform-paragraphs, fill-individual-paragraphs): Arg JUSTIFY-FLAG (JUSTIFYP) renamed to JUSTIFY. (fill-region-as-paragraph): Obey left-margin; fill-prefix starts after left-margin. Disable filling if JUSTIFY == none, but indent to margin anyway. Adaptive-fill removes text-props from fill-prefixes it finds. Adaptive-fill no longer has to notice left-margin: std fill does that. Use fill-column and canonically-space-region functions. (canonically-space-region): New fn split from fill-region-as-paragraph. (fill-region): New args NOSQUEEZE (as above) and TO-EOP. (default-justification): New variable. (current-left-margin, fill-column, justification): New functions. (fill-paragraph): Use fill-region-as-paragraph when possible. (justify-current-line): New arguments; different kinds of justification handled. Uses left-margin and fill-column functions.
-rw-r--r--lisp/textmodes/fill.el602
1 files changed, 393 insertions, 209 deletions
diff --git a/lisp/textmodes/fill.el b/lisp/textmodes/fill.el
index 9880e8c5fca..336236d8822 100644
--- a/lisp/textmodes/fill.el
+++ b/lisp/textmodes/fill.el
@@ -60,17 +60,79 @@ If Adaptive Fill mode is enabled, whatever text matches this pattern
60on the second line of a paragraph is used as the standard indentation 60on the second line of a paragraph is used as the standard indentation
61for the paragraph.") 61for the paragraph.")
62 62
63(defun fill-region-as-paragraph (from to &optional justify-flag) 63(defun current-fill-column ()
64 "Return the fill-column to use for this line.
65The fill-column to use for a buffer is stored in the variable `fill-column',
66but can be locally modified by the `right-margin' text property, which is
67subtracted from `fill-column'.
68
69The fill column to use for a line is the first column at which the column
70number equals or exceeds the local fill-column - right-margin difference."
71 (save-excursion
72 (let* ((here (progn (beginning-of-line) (point)))
73 (here-col 0)
74 (eol (progn (end-of-line) (point)))
75 margin fill-col change col)
76 ;; Look separately at each region of line with a different right-margin
77 (while (and (setq margin (get-text-property here 'right-margin)
78 fill-col (- fill-column (or margin 0))
79 change (text-property-not-all here eol
80 'right-margin margin))
81 (progn (goto-char (1- change))
82 (setq col (current-column))
83 (< col fill-col)))
84 (setq here change
85 here-col col))
86 (max here-col fill-col))))
87
88(defun canonically-space-region (beg end)
89 "Remove extra spaces between words in region.
90Puts one space between words in region; two between sentences.
91Remove indenation from each line."
92 (interactive "r")
93 (save-excursion
94 (goto-char beg)
95 ;; Nuke tabs; they get screwed up in a fill.
96 ;; This is quick, but loses when a tab follows the end of a sentence.
97 ;; Actually, it is difficult to tell that from "Mr.\tSmith".
98 ;; Blame the typist.
99 (subst-char-in-region beg end ?\t ?\ )
100 (while (and (< (point) end)
101 (re-search-forward " *" end t))
102 (delete-region
103 (+ (match-beginning 0)
104 ;; Determine number of spaces to leave:
105 (save-excursion
106 (skip-chars-backward " ]})\"'")
107 (cond ((and sentence-end-double-space
108 (memq (preceding-char) '(?. ?? ?!))) 2)
109 ((char-equal (preceding-char) ?\n) 0)
110 (t 1))))
111 (match-end 0)))
112 ;; Make sure sentences ending at end of line get an extra space.
113 ;; loses on split abbrevs ("Mr.\nSmith")
114 (goto-char beg)
115 (while (and (< (point) end)
116 (re-search-forward "[.?!][])}\"']*$" end t))
117 (insert-and-inherit ? ))))
118
119(defun fill-region-as-paragraph (from to &optional justify nosqueeze)
64 "Fill region as one paragraph: break lines to fit `fill-column'. 120 "Fill region as one paragraph: break lines to fit `fill-column'.
65Any paragraph breaks in the region will be removed. 121This removes any paragraph breaks in the region.
66Prefix arg means justify too. 122It performs justification according to the `justification' text-property,
123but a prefix arg can be used to override this and request full justification.
124
125Optional fourth arg NOSQUEEZE non-nil means to leave whitespace other than line
126breaks untouched. Normally it is made canonical before filling.
127
67If `sentence-end-double-space' is non-nil, then period followed by one 128If `sentence-end-double-space' is non-nil, then period followed by one
68space does not end a sentence, so don't break a line there. 129space does not end a sentence, so don't break a line there."
69From program, pass args FROM, TO and JUSTIFY-FLAG."
70 (interactive "r\nP") 130 (interactive "r\nP")
71 ;; Arrange for undoing the fill to restore point. 131 ;; Arrange for undoing the fill to restore point.
72 (if (and buffer-undo-list (not (eq buffer-undo-list t))) 132 (if (and buffer-undo-list (not (eq buffer-undo-list t)))
73 (setq buffer-undo-list (cons (point) buffer-undo-list))) 133 (setq buffer-undo-list (cons (point) buffer-undo-list)))
134 (or justify (setq justify (justification)))
135
74 ;; Don't let Adaptive Fill mode alter the fill prefix permanently. 136 ;; Don't let Adaptive Fill mode alter the fill prefix permanently.
75 (let ((fill-prefix fill-prefix)) 137 (let ((fill-prefix fill-prefix))
76 ;; Figure out how this paragraph is indented, if desired. 138 ;; Figure out how this paragraph is indented, if desired.
@@ -80,173 +142,172 @@ From program, pass args FROM, TO and JUSTIFY-FLAG."
80 (goto-char (min from to)) 142 (goto-char (min from to))
81 (if (eolp) (forward-line 1)) 143 (if (eolp) (forward-line 1))
82 (forward-line 1) 144 (forward-line 1)
145 (move-to-left-margin)
83 (if (< (point) (max from to)) 146 (if (< (point) (max from to))
84 (let ((start (point))) 147 (let ((start (point)))
85 (re-search-forward adaptive-fill-regexp) 148 (re-search-forward adaptive-fill-regexp)
86 (setq fill-prefix (buffer-substring start (point)))) 149 (setq fill-prefix (buffer-substring start (point)))
150 (set-text-properties 0 (length fill-prefix) nil fill-prefix))
87 (goto-char (min from to)) 151 (goto-char (min from to))
88 (if (eolp) (forward-line 1)) 152 (if (eolp) (forward-line 1))
89 ;; If paragraph has only one line, don't assume in general 153 ;; If paragraph has only one line, don't assume in general
90 ;; that additional lines would have the same starting 154 ;; that additional lines would have the same starting
91 ;; decoration. Assume no indentation. 155 ;; decoration. Assume no indentation.
92 ;; But if left-margin is nonzero, we can assume ordinary
93 ;; lines do have indentation.
94 (if (> left-margin 0)
95 (progn
96 (re-search-forward adaptive-fill-regexp)
97 (setq fill-prefix (make-string (current-column) ?\ ))))
98 ))) 156 )))
99 157
100 (save-restriction 158 (if (not justify) ; filling disabled: just check indentation
101 (let (beg) 159 (progn
102 (goto-char (min from to)) 160 (goto-char (min from to))
103 (skip-chars-forward "\n") 161 (setq to (max from to))
104 (setq beg (point)) 162 (while (< (point) to)
105 (goto-char (max from to)) 163 (if (not (eolp))
106 (skip-chars-backward "\n") 164 (if (< (current-indentation) (left-margin))
107 (setq to (point) 165 (indent-to-left-margin)))
108 from beg) 166 (forward-line 1)))
109 (goto-char from) 167
110 (beginning-of-line) 168 (save-restriction
111 (narrow-to-region (point) to)) 169 (let (beg)
112 (if use-hard-newlines 170 (goto-char (min from to))
113 (remove-text-properties from to '(hard nil))) 171 (skip-chars-forward "\n")
114 (if (> from (point)) 172 (setq beg (point))
115 (goto-char from)) 173 (goto-char (max from to))
116 (let ((fpre (and fill-prefix (not (equal fill-prefix "")) 174 (skip-chars-backward "\n")
117 (regexp-quote fill-prefix)))) 175 (setq to (point)
176 from beg)
177 (goto-char from)
178 (beginning-of-line)
179 (narrow-to-region (point) to))
180 (if use-hard-newlines
181 (remove-text-properties from to '(hard nil)))
182 ;; Make sure first line is indented (at least) to left margin...
183 (if (or (memq justify '(right center))
184 (< (current-indentation) (left-margin)))
185 (indent-to-left-margin))
186 ;; and remove indentation from other lines.
187 (beginning-of-line 2)
188 (indent-region (point) (point-max) 0)
118 ;; Delete the fill prefix from every line except the first. 189 ;; Delete the fill prefix from every line except the first.
119 ;; The first line may not even have a fill prefix. 190 ;; The first line may not even have a fill prefix.
120 (and fpre 191 (goto-char from)
121 (progn 192 (let ((fpre (and fill-prefix (not (equal fill-prefix ""))
122 (if (>= (length fill-prefix) fill-column) 193 (concat "[ \t]*"
123 (error "fill-prefix too long for specified width")) 194 (regexp-quote fill-prefix)))))
124 (goto-char from) 195 (and fpre
125 (forward-line 1)
126 (while (not (eobp))
127 (if (looking-at fpre)
128 (delete-region (point) (match-end 0)))
129 (forward-line 1))
130 (goto-char from)
131 (and (looking-at fpre) (forward-char (length fill-prefix)))
132 (setq from (point)))))
133 ;; from is now before the text to fill,
134 ;; but after any fill prefix on the first line.
135
136 ;; Make sure sentences ending at end of line get an extra space.
137 ;; loses on split abbrevs ("Mr.\nSmith")
138 (goto-char from)
139 (while (re-search-forward "[.?!][])}\"']*$" nil t)
140 (insert-and-inherit ? ))
141
142 ;; Then change all newlines to spaces.
143 (subst-char-in-region from (point-max) ?\n ?\ )
144
145 ;; Flush excess spaces, except in the paragraph indentation.
146 (goto-char from)
147 (skip-chars-forward " \t")
148 ;; Nuke tabs while we're at it; they get screwed up in a fill.
149 ;; This is quick, but loses when a tab follows the end of a sentence.
150 ;; Actually, it is difficult to tell that from "Mr.\tSmith".
151 ;; Blame the typist.
152 (subst-char-in-region (point) (point-max) ?\t ?\ )
153 (while (re-search-forward " *" nil t)
154 (delete-region
155 (+ (match-beginning 0)
156 (if (and sentence-end-double-space
157 (save-excursion
158 (skip-chars-backward " ]})\"'")
159 (memq (preceding-char) '(?. ?? ?!))))
160 2 1))
161 (match-end 0)))
162 (goto-char (point-max))
163 (delete-horizontal-space)
164 (insert-and-inherit " ")
165 (goto-char (point-min))
166
167 ;; This is the actual filling loop.
168 (let ((prefixcol 0) linebeg)
169 (while (not (eobp))
170 (setq linebeg (point))
171 (move-to-column (1+ fill-column))
172 (if (eobp)
173 (delete-horizontal-space)
174 ;; Move back to start of word.
175 (skip-chars-backward "^ \n" linebeg)
176 ;; Don't break after a period followed by just one space.
177 ;; Move back to the previous place to break.
178 ;; The reason is that if a period ends up at the end of a line,
179 ;; further fills will assume it ends a sentence.
180 ;; If we now know it does not end a sentence,
181 ;; avoid putting it at the end of the line.
182 (if sentence-end-double-space
183 (while (and (> (point) (+ linebeg 2))
184 (eq (preceding-char) ?\ )
185 (not (eq (following-char) ?\ ))
186 (eq (char-after (- (point) 2)) ?\.))
187 (forward-char -2)
188 (skip-chars-backward "^ \n" linebeg)))
189 (if (if (zerop prefixcol)
190 (save-excursion
191 (skip-chars-backward " " linebeg)
192 (bolp))
193 (>= prefixcol (current-column)))
194 ;; Keep at least one word even if fill prefix exceeds margin.
195 ;; This handles all but the first line of the paragraph.
196 ;; Meanwhile, don't stop at a period followed by one space.
197 (let ((first t))
198 (move-to-column prefixcol)
199 (while (and (not (eobp))
200 (or first
201 (and (not (bobp))
202 sentence-end-double-space
203 (save-excursion (forward-char -1)
204 (and (looking-at "\\. ")
205 (not (looking-at "\\. ")))))))
206 (skip-chars-forward " ")
207 (skip-chars-forward "^ \n")
208 (setq first nil)))
209 ;; Normally, move back over the single space between the words.
210 (forward-char -1))
211 (if (and fill-prefix (zerop prefixcol)
212 (< (- (point) (point-min)) (length fill-prefix))
213 (string= (buffer-substring (point-min) (point))
214 (substring fill-prefix 0 (- (point) (point-min)))))
215 ;; Keep at least one word even if fill prefix exceeds margin.
216 ;; This handles the first line of the paragraph.
217 ;; Don't stop at a period followed by just one space.
218 (let ((first t))
219 (while (and (not (eobp))
220 (or first
221 (and (not (bobp))
222 sentence-end-double-space
223 (save-excursion (forward-char -1)
224 (and (looking-at "\\. ")
225 (not (looking-at "\\. ")))))))
226 (skip-chars-forward " ")
227 (skip-chars-forward "^ \n")
228 (setq first nil))))
229 ;; Replace all whitespace here with one newline.
230 ;; Insert before deleting, so we don't forget which side of
231 ;; the whitespace point or markers used to be on.
232 (skip-chars-backward " ")
233 (insert ?\n)
234 ;; Give newline the properties of the space(s) it replaces
235 (set-text-properties (1- (point)) (point)
236 (text-properties-at (point)))
237 (delete-horizontal-space)
238 ;; Insert the fill prefix at start of each line.
239 ;; Set prefixcol so whitespace in the prefix won't get lost.
240 (and fill-prefix (not (equal fill-prefix ""))
241 (progn
242 (insert-and-inherit fill-prefix)
243 (setq prefixcol (current-column)))))
244 ;; Justify the line just ended, if desired.
245 (and justify-flag (not (eobp))
246 (progn 196 (progn
247 (forward-line -1) 197 (if (>= (+ (left-margin) (length fill-prefix))
248 (justify-current-line) 198 (current-fill-column))
249 (forward-line 1)))))))) 199 (error "fill-prefix too long for specified width"))
200 (goto-char from)
201 (forward-line 1)
202 (while (not (eobp))
203 (if (looking-at fpre)
204 (delete-region (point) (match-end 0)))
205 (forward-line 1))
206 (goto-char from)
207 (and (looking-at fpre) (goto-char (match-end 0)))
208 (setq from (point)))))
209 ;; "from" is now before the text to fill,
210 ;; but after any fill prefix on the first line.
211
212 ;; Make sure sentences ending at end of line get an extra space.
213 ;; loses on split abbrevs ("Mr.\nSmith")
214 (while (re-search-forward "[.?!][])}\"']*$" nil t)
215 (insert-and-inherit ? ))
216 (goto-char from)
217 (skip-chars-forward " \t")
218 ;; Then change all newlines to spaces.
219 (subst-char-in-region from (point-max) ?\n ?\ )
220 (if (and nosqueeze (not (eq justify 'full)))
221 nil
222 (canonically-space-region (point) (point-max))
223 (goto-char (point-max))
224 (delete-horizontal-space)
225 (insert-and-inherit " "))
226 (goto-char (point-min))
227
228 ;; This is the actual filling loop.
229 (let ((prefixcol 0) linebeg)
230 (while (not (eobp))
231 (setq linebeg (point))
232 (move-to-column (1+ (current-fill-column)))
233 (if (eobp)
234 (or nosqueeze (delete-horizontal-space))
235 ;; Move back to start of word.
236 (skip-chars-backward "^ \n" linebeg)
237 ;; Don't break after a period followed by just one space.
238 ;; Move back to the previous place to break.
239 ;; The reason is that if a period ends up at the end of a line,
240 ;; further fills will assume it ends a sentence.
241 ;; If we now know it does not end a sentence,
242 ;; avoid putting it at the end of the line.
243 (if sentence-end-double-space
244 (while (and (> (point) (+ linebeg 2))
245 (eq (preceding-char) ?\ )
246 (not (eq (following-char) ?\ ))
247 (eq (char-after (- (point) 2)) ?\.))
248 (forward-char -2)
249 (skip-chars-backward "^ \n" linebeg)))
250 (if (if (zerop prefixcol)
251 (save-excursion
252 (skip-chars-backward " " linebeg)
253 (bolp))
254 (>= prefixcol (current-column)))
255 ;; Keep at least one word even if fill prefix exceeds margin.
256 ;; This handles all but the first line of the paragraph.
257 ;; Meanwhile, don't stop at a period followed by one space.
258 (let ((first t))
259 (move-to-column prefixcol)
260 (while (and (not (eobp))
261 (or first
262 (and (not (bobp))
263 sentence-end-double-space
264 (save-excursion (forward-char -1)
265 (and (looking-at "\\. ")
266 (not (looking-at "\\. ")))))))
267 (skip-chars-forward " ")
268 (skip-chars-forward "^ \n")
269 (setq first nil)))
270 ;; Normally, move back over the single space between the words.
271 (forward-char -1))
272 (if (and fill-prefix (zerop prefixcol)
273 (< (- (point) (point-min)) (length fill-prefix))
274 (string= (buffer-substring (point-min) (point))
275 (substring fill-prefix 0 (- (point) (point-min)))))
276 ;; Keep at least one word even if fill prefix exceeds margin.
277 ;; This handles the first line of the paragraph.
278 ;; Don't stop at a period followed by just one space.
279 (let ((first t))
280 (while (and (not (eobp))
281 (or first
282 (and (not (bobp))
283 sentence-end-double-space
284 (save-excursion (forward-char -1)
285 (and (looking-at "\\. ")
286 (not (looking-at "\\. ")))))))
287 (skip-chars-forward " ")
288 (skip-chars-forward "^ \n")
289 (setq first nil))))
290 ;; Replace whitespace here with one newline, then indent to left
291 ;; margin.
292 (skip-chars-backward " ")
293 (insert ?\n)
294 ;; Give newline the properties of the space(s) it replaces
295 (set-text-properties (1- (point)) (point)
296 (text-properties-at (point)))
297 (indent-to-left-margin)
298 ;; Insert the fill prefix after indentation.
299 ;; Set prefixcol so whitespace in the prefix won't get lost.
300 (and fill-prefix (not (equal fill-prefix ""))
301 (progn
302 (insert-and-inherit fill-prefix)
303 (setq prefixcol (current-column)))))
304 ;; Justify the line just ended, if desired.
305 (if justify
306 (if (eobp)
307 (justify-current-line justify t t)
308 (forward-line -1)
309 (justify-current-line justify nil t)
310 (forward-line 1)))))))))
250 311
251(defun fill-paragraph (arg) 312(defun fill-paragraph (arg)
252 "Fill paragraph at or after point. Prefix arg means justify as well. 313 "Fill paragraph at or after point. Prefix arg means justify as well.
@@ -266,9 +327,15 @@ space does not end a sentence, so don't break a line there."
266 (fill-region beg end arg) 327 (fill-region beg end arg)
267 (fill-region-as-paragraph beg end arg)))))) 328 (fill-region-as-paragraph beg end arg))))))
268 329
269(defun fill-region (from to &optional justify-flag) 330(defun fill-region (from to &optional justify nosqueeze to-eop)
270 "Fill each of the paragraphs in the region. 331 "Fill each of the paragraphs in the region.
271Prefix arg (non-nil third arg, if called from program) means justify as well. 332Prefix arg (non-nil third arg, if called from program) means justify as well.
333
334Noninteractively, fourth arg NOSQUEEZE non-nil means to leave
335whitespace other than line breaks untouched, and fifth arg TO-EOP
336non-nil means to keep filling to the end of the paragraph (or next
337hard newline, if `use-hard-newlines' is on).
338
272If `sentence-end-double-space' is non-nil, then period followed by one 339If `sentence-end-double-space' is non-nil, then period followed by one
273space does not end a sentence, so don't break a line there." 340space does not end a sentence, so don't break a line there."
274 (interactive "r\nP") 341 (interactive "r\nP")
@@ -278,6 +345,9 @@ space does not end a sentence, so don't break a line there."
278 end beg) 345 end beg)
279 (save-restriction 346 (save-restriction
280 (goto-char (max from to)) 347 (goto-char (max from to))
348 (if to-eop
349 (progn (skip-chars-backward "\n")
350 (forward-paragraph)))
281 (setq end (point)) 351 (setq end (point))
282 (goto-char (setq beg (min from to))) 352 (goto-char (setq beg (min from to)))
283 (beginning-of-line) 353 (beginning-of-line)
@@ -290,55 +360,169 @@ space does not end a sentence, so don't break a line there."
290 (if (< (point) beg) 360 (if (< (point) beg)
291 (goto-char beg)) 361 (goto-char beg))
292 (if (>= (point) initial) 362 (if (>= (point) initial)
293 (fill-region-as-paragraph (point) end justify-flag) 363 (fill-region-as-paragraph (point) end justify nosqueeze)
294 (goto-char end))))))) 364 (goto-char end)))))))
295 365
296(defun justify-current-line () 366
297 "Add spaces to line point is in, so it ends at `fill-column'." 367(defconst default-justification 'left
298 (interactive) 368 "*Method of justifying text not otherwise specified.
369Possible values are `left', `right', `full', `center', or `none'.
370The requested kind of justification is done whenever lines are filled.
371The `justification' text-property can locally override this variable.
372This variable automatically becomes buffer-local when set in any fashion.")
373(make-variable-buffer-local 'default-justification)
374
375(defun justification ()
376 "How should we justify this line?
377This returns the value of the text-property `justification',
378or the variable `default-justification' if there is no text-property.
379However, it returns nil rather than `none' to mean \"don't justify\"."
380 (let ((j (or (get-text-property
381 ;; Make sure we're looking at paragraph body.
382 (save-excursion (skip-chars-forward " \t") (point))
383 'justification)
384 default-justification)))
385 (if (eq 'none j)
386 nil
387 j)))
388
389(defun set-justification (begin end value)
390 "Set the region's justification style.
391If the mark is not active, this operates on the current line.
392In interactive use, if the BEGIN and END points are
393not at line breaks, they are moved outward to the next line break.
394If `use-hard-newlines' is true, they are moved to the next hard line breaks.
395Noninteractively, the values of BEGIN, END and VALUE are not modified."
396 (interactive (list (if mark-active (region-beginning) (point))
397 (if mark-active (region-end) (point))
398 (let ((s (completing-read
399 "Set justification to: "
400 '(("left") ("right") ("full") ("center")
401 ("none"))
402 nil t)))
403 (if (equal s "")
404 (error "")
405 (intern s)))))
406 (let* ((paragraph-start (if use-hard-newlines "^" paragraph-start)))
407 (save-excursion
408 (goto-char begin)
409 (while (bolp) (forward-char 1))
410 (backward-paragraph)
411 (setq begin (point))
412
413 (goto-char end)
414 (skip-chars-backward " \t\n" begin)
415 (forward-paragraph)
416 (setq end (point))
417 (set-mark begin)
418 (goto-char end)
419 (y-or-n-p "set-just")))
420 (put-text-property begin end 'justification value)
421 (fill-region begin end nil t))
422
423(defun set-justification-none (b e)
424 "Disable automatic filling for paragraphs in the region.
425If the mark is not active, this applies to the current paragraph."
426 (interactive "r")
427 (set-justification b e 'none))
428
429(defun set-justification-left (b e)
430 "Make paragraphs in the region left-justified.
431This is usually the default, but see `enriched-default-justification'.
432If the mark is not active, this applies to the current paragraph."
433 (interactive "r")
434 (set-justification b e 'left))
435
436(defun set-justification-right (b e)
437 "Make paragraphs in the region right-justified:
438Flush at the right margin and ragged on the left.
439If the mark is not active, this applies to the current paragraph."
440 (interactive "r")
441 (set-justification b e 'right))
442
443(defun set-justification-full (b e)
444 "Make paragraphs in the region fully justified:
445Flush on both margins.
446If the mark is not active, this applies to the current paragraph."
447 (interactive "r")
448 (set-justification b e 'both))
449
450(defun set-justification-center (b e)
451 "Make paragraphs in the region centered.
452If the mark is not active, this applies to the current paragraph."
453 (interactive "r")
454 (set-justification b e 'center))
455
456(defun justify-current-line (&optional how eop nosqueeze)
457 "Add spaces to line point is in, so it ends at `fill-column'.
458Optional first argument HOW specifies alternate type of justification:
459it can be `left', `right', `full', `center', or `none'.
460If HOW is t, will justify however the `justification' function says.
461Any other value, including nil, is taken to mean `full'.
462Second arg EOP non-nil means that this is the last line of the paragraph, so
463it will not be stretched by full justification.
464Third arg NOSQUEEZE non-nil means to leave interior whitespace unchanged,
465otherwise it is made canonical."
466 (interactive (list 'full nil nil))
467 (if (eq t how) (setq how (or (justification) 'none)))
299 (save-excursion 468 (save-excursion
300 (save-restriction 469 (save-restriction
301 (let (ncols beg indent end) 470 (let ((fc (current-fill-column))
302 (beginning-of-line) 471 ncols beg indent end)
303 (forward-char (length fill-prefix))
304 (skip-chars-forward " \t")
305 (setq indent (current-column))
306 (setq beg (point))
307 (end-of-line) 472 (end-of-line)
308 (narrow-to-region beg (point)) 473 (if (and use-hard-newlines (null eop)
309 (setq end (point)) 474 (get-text-property (point) 'hard))
475 (setq eop t))
310 (skip-chars-backward " \t") 476 (skip-chars-backward " \t")
311 (delete-char (- end (point))) 477 (if (= (current-column) fc)
312 (goto-char beg) 478 nil ;; Quick exit if it appears to be properly justified already.
313 (while (re-search-forward " *" nil t) 479 (setq end (point))
314 (delete-region 480 (beginning-of-line)
315 (+ (match-beginning 0) 481 (skip-chars-forward " \t")
316 (if (save-excursion 482 (if (and fill-prefix
317 (skip-chars-backward " ])\"'") 483 (equal fill-prefix
318 (memq (preceding-char) '(?. ?? ?!))) 484 (buffer-substring (point)
319 2 1)) 485 (+ (point) (length fill-prefix)))))
320 (match-end 0))) 486 (forward-char (length fill-prefix)))
321 (goto-char beg) 487 (setq indent (current-column))
322 (while (re-search-forward "[.?!][])\"']*\n" nil t) 488 (setq beg (point))
323 (forward-char -1) 489 (goto-char end)
324 (insert-and-inherit ? )) 490 (cond ((or (eq 'none how) (eq 'left how))
325 (goto-char (point-max)) 491 nil)
326 ;; Note that the buffer bounds start after the indentation, 492 ((eq 'right how)
327 ;; so the columns counted by INDENT don't appear in (current-column). 493 (setq ncols (- (+ indent (current-fill-column))
328 (setq ncols (- fill-column (current-column) indent)) 494 (current-column)))
329 (if (search-backward " " nil t) 495 (if (> ncols 0)
330 (while (> ncols 0) 496 (indent-line-to ncols)))
331 (let ((nmove (+ 3 (random 3)))) 497 ((eq 'center how)
332 (while (> nmove 0) 498 (setq ncols
333 (or (search-backward " " nil t) 499 (/ (- (+ indent (current-fill-column)) (current-column))
334 (progn 500 2))
335 (goto-char (point-max)) 501 (if (>= ncols 0)
336 (search-backward " "))) 502 (indent-line-to ncols)
337 (skip-chars-backward " ") 503 (message "Line to long to center")))
338 (setq nmove (1- nmove)))) 504 (t ;; full
339 (insert-and-inherit " ") 505 (narrow-to-region beg end)
340 (skip-chars-backward " ") 506 (or nosqueeze
341 (setq ncols (1- ncols))))))) 507 (canonically-space-region beg end))
508 (goto-char (point-max))
509 (setq ncols (- (current-fill-column) indent (current-column)))
510 (if (< ncols 0)
511 (message "Line to long to justify")
512 (if (and (not eop)
513 (search-backward " " nil t))
514 (while (> ncols 0)
515 (let ((nmove (+ 3 (random 3))))
516 (while (> nmove 0)
517 (or (search-backward " " nil t)
518 (progn
519 (goto-char (point-max))
520 (search-backward " ")))
521 (skip-chars-backward " ")
522 (setq nmove (1- nmove))))
523 (insert-and-inherit " ")
524 (skip-chars-backward " ")
525 (setq ncols (1- ncols)))))))))))
342 nil) 526 nil)
343 527
344 528
@@ -351,14 +535,14 @@ in the paragraph.
351 535
352When calling from a program, pass range to fill as first two arguments. 536When calling from a program, pass range to fill as first two arguments.
353 537
354Optional third and fourth arguments JUSTIFY-FLAG and MAIL-FLAG: 538Optional third and fourth arguments JUSTIFY and MAIL-FLAG:
355JUSTIFY-FLAG to justify paragraphs (prefix arg), 539JUSTIFY to justify paragraphs (prefix arg),
356MAIL-FLAG for a mail message, i. e. don't fill header lines." 540MAIL-FLAG for a mail message, i. e. don't fill header lines."
357 (interactive "r\nP") 541 (interactive "r\nP")
358 (let ((fill-individual-varying-indent t)) 542 (let ((fill-individual-varying-indent t))
359 (fill-individual-paragraphs min max justifyp mailp))) 543 (fill-individual-paragraphs min max justifyp mailp)))
360 544
361(defun fill-individual-paragraphs (min max &optional justifyp mailp) 545(defun fill-individual-paragraphs (min max &optional justify mailp)
362 "Fill paragraphs of uniform indentation within the region. 546 "Fill paragraphs of uniform indentation within the region.
363This command divides the region into \"paragraphs\", 547This command divides the region into \"paragraphs\",
364treating every change in indentation level as a paragraph boundary, 548treating every change in indentation level as a paragraph boundary,
@@ -366,8 +550,8 @@ then fills each paragraph using its indentation level as the fill prefix.
366 550
367When calling from a program, pass range to fill as first two arguments. 551When calling from a program, pass range to fill as first two arguments.
368 552
369Optional third and fourth arguments JUSTIFY-FLAG and MAIL-FLAG: 553Optional third and fourth arguments JUSTIFY and MAIL-FLAG:
370JUSTIFY-FLAG to justify paragraphs (prefix arg), 554JUSTIFY to justify paragraphs (prefix arg),
371MAIL-FLAG for a mail message, i. e. don't fill header lines." 555MAIL-FLAG for a mail message, i. e. don't fill header lines."
372 (interactive "r\nP") 556 (interactive "r\nP")
373 (save-restriction 557 (save-restriction
@@ -421,7 +605,7 @@ MAIL-FLAG for a mail message, i. e. don't fill header lines."
421 (looking-at paragraph-start)))))))))) 605 (looking-at paragraph-start))))))))))
422 ;; Fill this paragraph, but don't add a newline at the end. 606 ;; Fill this paragraph, but don't add a newline at the end.
423 (let ((had-newline (bolp))) 607 (let ((had-newline (bolp)))
424 (fill-region-as-paragraph start (point) justifyp) 608 (fill-region-as-paragraph start (point) justify)
425 (or had-newline (delete-char -1)))))))) 609 (or had-newline (delete-char -1))))))))
426 610
427;;; fill.el ends here 611;;; fill.el ends here