comparison lisp/textmodes/fill.el @ 41303:ada5571dc737

(fill-delete-prefix, fill-delete-newlines): New functions, extracted from fill-region-as-paragraph. (fill-region-as-paragraph): Use them. Use an end marker instead of eob. Ignore whitespace-only fill-prefixes when indenting according to mode. Simply the loop that searches for spaces backwards.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Mon, 19 Nov 2001 23:51:03 +0000
parents 56aa9e5dc60c
children f0a204c61f81
comparison
equal deleted inserted replaced
41302:65b9b5655f50 41303:ada5571dc737
149 ;; This is quick, but loses when a tab follows the end of a sentence. 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". 150 ;; Actually, it is difficult to tell that from "Mr.\tSmith".
151 ;; Blame the typist. 151 ;; Blame the typist.
152 (subst-char-in-region beg end ?\t ?\ ) 152 (subst-char-in-region beg end ?\t ?\ )
153 (while (and (< (point) end) 153 (while (and (< (point) end)
154 (re-search-forward " *" end t)) 154 (re-search-forward " +" end t))
155 (delete-region 155 (delete-region
156 (+ (match-beginning 0) 156 (+ (match-beginning 0)
157 ;; Determine number of spaces to leave: 157 ;; Determine number of spaces to leave:
158 (save-excursion 158 (save-excursion
159 (skip-chars-backward " ]})\"'") 159 (skip-chars-backward " ]})\"'")
171 (goto-char beg) 171 (goto-char beg)
172 (let ((eol-double-space-re (if colon-double-space 172 (let ((eol-double-space-re (if colon-double-space
173 "[.?!:][])}\"']*$" 173 "[.?!:][])}\"']*$"
174 "[.?!][])}\"']*$"))) 174 "[.?!][])}\"']*$")))
175 (while (and (< (point) end) 175 (while (and (< (point) end)
176 (re-search-forward eol-double-space-re end t)) 176 (re-search-forward eol-double-space-re end t))
177 ;; We insert before markers in case a caller such as 177 ;; We insert before markers in case a caller such as
178 ;; do-auto-fill has done a save-excursion with point at the end 178 ;; do-auto-fill has done a save-excursion with point at the end
179 ;; of the line and wants it to stay at the end of the line. 179 ;; of the line and wants it to stay at the end of the line.
180 (insert-before-markers-and-inherit ? ))))) 180 (insert-before-markers-and-inherit ? )))))
181 181
182 (defun fill-common-string-prefix (s1 s2) 182 (defun fill-common-string-prefix (s1 s2)
183 "Return the longest common prefix of strings S1 and S2, or nil if none." 183 "Return the longest common prefix of strings S1 and S2, or nil if none."
184 (let ((cmp (compare-strings s1 nil nil s2 nil nil))) 184 (let ((cmp (compare-strings s1 nil nil s2 nil nil)))
185 (if (eq cmp t) 185 (if (eq cmp t)
249 "\\([ \t]*\\|.\\)" 249 "\\([ \t]*\\|.\\)"
250 (regexp-quote (string c)))) 250 (regexp-quote (string c))))
251 second-line-prefix)))) 251 second-line-prefix))))
252 second-line-prefix 252 second-line-prefix
253 253
254 ;; Use the longest common substring of both prefixes, 254 ;; Use the longest common substring of both prefixes,
255 ;; if there is one. 255 ;; if there is one.
256 (fill-common-string-prefix first-line-prefix 256 (fill-common-string-prefix first-line-prefix
257 second-line-prefix)))) 257 second-line-prefix))))
258 ;; If we get a fill prefix from a one-line paragraph, 258 ;; If we get a fill prefix from a one-line paragraph,
259 ;; maybe change it to whitespace, 259 ;; maybe change it to whitespace,
260 ;; and check that it isn't a paragraph starter. 260 ;; and check that it isn't a paragraph starter.
261 (if first-line-prefix 261 (if first-line-prefix
319 ;; Don't break after a period followed by just one space. 319 ;; Don't break after a period followed by just one space.
320 ;; Move back to the previous place to break. 320 ;; Move back to the previous place to break.
321 ;; The reason is that if a period ends up at the end of a 321 ;; The reason is that if a period ends up at the end of a
322 ;; line, further fills will assume it ends a sentence. 322 ;; line, further fills will assume it ends a sentence.
323 ;; If we now know it does not end a sentence, avoid putting 323 ;; If we now know it does not end a sentence, avoid putting
324 ;; it at the end of the line. 324 ;; it at the end of the line.
325 (and sentence-end-double-space 325 (and sentence-end-double-space
326 (save-excursion 326 (save-excursion
327 (skip-chars-backward ". ") 327 (skip-chars-backward ". ")
328 (looking-at "\\. \\([^ ]\\|$\\)"))) 328 (looking-at "\\. \\([^ ]\\|$\\)")))
329 ;; Another approach to the same problem. 329 ;; Another approach to the same problem.
338 (run-hook-with-args-until-success 'fill-nobreak-predicate)))) 338 (run-hook-with-args-until-success 'fill-nobreak-predicate))))
339 339
340 ;; Put `fill-find-break-point-function' property to charsets which 340 ;; Put `fill-find-break-point-function' property to charsets which
341 ;; require special functions to find line breaking point. 341 ;; require special functions to find line breaking point.
342 (dolist (pair '((katakana-jisx0201 . kinsoku) 342 (dolist (pair '((katakana-jisx0201 . kinsoku)
343 (chinese-gb2312 . kinsoku) 343 (chinese-gb2312 . kinsoku)
344 (japanese-jisx0208 . kinsoku) 344 (japanese-jisx0208 . kinsoku)
345 (japanese-jisx0212 . kinsoku) 345 (japanese-jisx0212 . kinsoku)
346 (chinese-big5-1 . kinsoku) 346 (chinese-big5-1 . kinsoku)
347 (chinese-big5-2 . kinsoku))) 347 (chinese-big5-2 . kinsoku)))
348 (put-charset-property (car pair) 'fill-find-break-point-function (cdr pair))) 348 (put-charset-property (car pair) 'fill-find-break-point-function (cdr pair)))
349 349
350 (defun fill-find-break-point (limit) 350 (defun fill-find-break-point (limit)
351 "Move point to a proper line breaking position of the current line. 351 "Move point to a proper line breaking position of the current line.
366 (setq func 366 (setq func
367 (get-charset-property charset 'fill-find-break-point-function))) 367 (get-charset-property charset 'fill-find-break-point-function)))
368 (if (and func (fboundp func)) 368 (if (and func (fboundp func))
369 (funcall func limit)))) 369 (funcall func limit))))
370 370
371 (defun fill-delete-prefix (from to prefix)
372 "Delete the fill prefix from every line except the first.
373 The first line may not even have a fill prefix.
374 Point is moved to just past the fill prefix on the first line."
375 (goto-char from)
376 (let ((fpre (and prefix (not (equal prefix ""))
377 (concat "[ \t]*"
378 (replace-regexp-in-string
379 "[ \t]+" "[ \t]*"
380 (regexp-quote prefix))
381 "[ \t]*"))))
382 (when fpre
383 (if (>= (+ (current-left-margin) (length prefix))
384 (current-fill-column))
385 (error "fill-prefix too long for specified width"))
386 (forward-line 1)
387 (while (< (point) to)
388 (if (looking-at fpre)
389 (delete-region (point) (match-end 0)))
390 (forward-line 1))
391 (goto-char from)
392 (if (looking-at fpre)
393 (goto-char (match-end 0)))
394 (setq from (point))))
395 ;; Remove indentation from lines other than the first.
396 (beginning-of-line 2)
397 (indent-region (point) to 0)
398 (goto-char from))
399
400 (defun fill-delete-newlines (from to justify nosqueeze squeeze-after)
401 (goto-char from)
402 ;; Make sure sentences ending at end of line get an extra space.
403 ;; loses on split abbrevs ("Mr.\nSmith")
404 (let ((eol-double-space-re (if colon-double-space
405 "[.?!:][])}\"']*$"
406 "[.?!][])}\"']*$")))
407 (while (re-search-forward eol-double-space-re to t)
408 (or (>= (point) to) (insert-and-inherit ?\ ))))
409
410 (goto-char from)
411 (if enable-multibyte-characters
412 ;; Delete unnecessay newlines surrounded by words. The
413 ;; character category `|' means that we can break a line
414 ;; at the character. And, charset property
415 ;; `nospace-between-words' tells how to concatenate
416 ;; words. If the value is non-nil, never put spaces
417 ;; between words, thus delete a newline between them.
418 ;; If the value is nil, delete a newline only when a
419 ;; character preceding a newline has text property
420 ;; `nospace-between-words'.
421 (while (search-forward "\n" to t)
422 (let ((prev (char-before (match-beginning 0)))
423 (next (following-char)))
424 (if (and (or (aref (char-category-set next) ?|)
425 (aref (char-category-set prev) ?|))
426 (or (get-charset-property (char-charset prev)
427 'nospace-between-words)
428 (get-text-property (1- (match-beginning 0))
429 'nospace-between-words)))
430 (delete-char -1)))))
431
432 (goto-char from)
433 (skip-chars-forward " \t")
434 ;; Then change all newlines to spaces.
435 (subst-char-in-region from to ?\n ?\ )
436 (if (and nosqueeze (not (eq justify 'full)))
437 nil
438 (canonically-space-region (or squeeze-after (point)) to)
439 (goto-char to)
440 (delete-horizontal-space)
441 (insert-and-inherit " "))
442 (goto-char from))
443
371 (defun fill-region-as-paragraph (from to &optional justify 444 (defun fill-region-as-paragraph (from to &optional justify
372 nosqueeze squeeze-after) 445 nosqueeze squeeze-after)
373 "Fill the region as one paragraph. 446 "Fill the region as one paragraph.
374 It removes any paragraph breaks in the region and extra newlines at the end, 447 It removes any paragraph breaks in the region and extra newlines at the end,
375 indents and fills lines between the margins given by the 448 indents and fills lines between the margins given by the
419 (not (and use-hard-newlines 492 (not (and use-hard-newlines
420 (get-text-property (1- (point)) 'hard)))) 493 (get-text-property (1- (point)) 'hard))))
421 (delete-backward-char 1) 494 (delete-backward-char 1)
422 (backward-char 1) 495 (backward-char 1)
423 (setq oneleft t))) 496 (setq oneleft t)))
424 (setq to (point)) 497 (setq to (copy-marker (point) t))
425 ;; ;; If there was no newline, and there is text in the paragraph, then 498 ;; ;; If there was no newline, and there is text in the paragraph, then
426 ;; ;; create a newline. 499 ;; ;; create a newline.
427 ;; (if (and (not oneleft) (> to from-plus-indent)) 500 ;; (if (and (not oneleft) (> to from-plus-indent))
428 ;; (newline)) 501 ;; (newline))
429 (goto-char from-plus-indent)) 502 (goto-char from-plus-indent))
434 (or justify (setq justify (current-justification))) 507 (or justify (setq justify (current-justification)))
435 508
436 ;; Never indent-according-to-mode with brain dead "indenting" functions. 509 ;; Never indent-according-to-mode with brain dead "indenting" functions.
437 (when (and fill-indent-according-to-mode 510 (when (and fill-indent-according-to-mode
438 (memq indent-line-function 511 (memq indent-line-function
439 '(indent-relative-maybe indent-relative 512 '(indent-relative-maybe indent-relative
440 indent-to-left-margin))) 513 indent-to-left-margin)))
441 (set (make-local-variable 'fill-indent-according-to-mode) nil)) 514 (set (make-local-variable 'fill-indent-according-to-mode) nil))
442 515
443 ;; Don't let Adaptive Fill mode alter the fill prefix permanently. 516 ;; Don't let Adaptive Fill mode alter the fill prefix permanently.
444 (let ((fill-prefix fill-prefix)) 517 (let ((fill-prefix fill-prefix))
445 ;; Figure out how this paragraph is indented, if desired. 518 ;; Figure out how this paragraph is indented, if desired.
446 (if (and adaptive-fill-mode 519 (when (and adaptive-fill-mode
447 (or (null fill-prefix) (string= fill-prefix ""))) 520 (or (null fill-prefix) (string= fill-prefix "")))
448 (setq fill-prefix (fill-context-prefix from to))) 521 (setq fill-prefix (fill-context-prefix from to))
522 ;; Ignore a white-space only fill-prefix
523 ;; if we indent-according-to-mode.
524 (when (and fill-prefix fill-indent-according-to-mode
525 (string-match "\\`[ \t]*\\'" fill-prefix))
526 (setq fill-prefix nil)))
449 527
450 (save-restriction 528 (save-restriction
451 (goto-char from) 529 (goto-char from)
452 (beginning-of-line) 530 (beginning-of-line)
453 (narrow-to-region (point) to) 531 (narrow-to-region (point) to)
454 532
455 (if (not justify) ; filling disabled: just check indentation 533 (if (not justify) ; filling disabled: just check indentation
456 (progn 534 (progn
457 (goto-char from) 535 (goto-char from)
458 (while (not (eobp)) 536 (while (< (point) to)
459 (if (and (not (eolp)) 537 (if (and (not (eolp))
460 (< (current-indentation) (current-left-margin))) 538 (< (current-indentation) (current-left-margin)))
461 (indent-to-left-margin)) 539 (indent-to-left-margin))
462 (forward-line 1))) 540 (forward-line 1)))
463 541
465 (remove-text-properties from (point-max) '(hard nil))) 543 (remove-text-properties from (point-max) '(hard nil)))
466 ;; Make sure first line is indented (at least) to left margin... 544 ;; Make sure first line is indented (at least) to left margin...
467 (if (or (memq justify '(right center)) 545 (if (or (memq justify '(right center))
468 (< (current-indentation) (current-left-margin))) 546 (< (current-indentation) (current-left-margin)))
469 (indent-to-left-margin)) 547 (indent-to-left-margin))
470 ;; Delete the fill prefix from every line except the first. 548 ;; Delete the fill-prefix from every line.
471 ;; The first line may not even have a fill prefix. 549 (fill-delete-prefix from to fill-prefix)
472 (goto-char from) 550 (setq from (point))
473 (let ((fpre (and fill-prefix (not (equal fill-prefix "")) 551
474 (concat "[ \t]*"
475 (regexp-quote fill-prefix)
476 "[ \t]*"))))
477 (and fpre
478 (progn
479 (if (>= (+ (current-left-margin) (length fill-prefix))
480 (current-fill-column))
481 (error "fill-prefix too long for specified width"))
482 (goto-char from)
483 (forward-line 1)
484 (while (not (eobp))
485 (if (looking-at fpre)
486 (delete-region (point) (match-end 0)))
487 (forward-line 1))
488 (goto-char from)
489 (if (looking-at fpre)
490 (goto-char (match-end 0)))
491 (setq from (point)))))
492 ;; Remove indentation from lines other than the first.
493 (beginning-of-line 2)
494 (indent-region (point) (point-max) 0)
495 (goto-char from)
496
497 ;; FROM, and point, are now before the text to fill, 552 ;; FROM, and point, are now before the text to fill,
498 ;; but after any fill prefix on the first line. 553 ;; but after any fill prefix on the first line.
499 554
500 ;; Make sure sentences ending at end of line get an extra space. 555 (fill-delete-newlines from to justify nosqueeze squeeze-after)
501 ;; loses on split abbrevs ("Mr.\nSmith")
502 (let ((eol-double-space-re (if colon-double-space
503 "[.?!:][])}\"']*$"
504 "[.?!][])}\"']*$")))
505 (while (re-search-forward eol-double-space-re nil t)
506 (or (eobp) (insert-and-inherit ?\ ))))
507
508 (goto-char from)
509 (if enable-multibyte-characters
510 ;; Delete unnecessay newlines surrounded by words. The
511 ;; character category `|' means that we can break a line
512 ;; at the character. And, charset property
513 ;; `nospace-between-words' tells how to concatenate
514 ;; words. If the value is non-nil, never put spaces
515 ;; between words, thus delete a newline between them.
516 ;; If the value is nil, delete a newline only when a
517 ;; character preceding a newline has text property
518 ;; `nospace-between-words'.
519 (while (search-forward "\n" nil t)
520 (let ((prev (char-before (match-beginning 0)))
521 (next (following-char)))
522 (if (and (or (aref (char-category-set next) ?|)
523 (aref (char-category-set prev) ?|))
524 (or (get-charset-property (char-charset prev)
525 'nospace-between-words)
526 (get-text-property (1- (match-beginning 0))
527 'nospace-between-words)))
528 (delete-char -1)))))
529
530 (goto-char from)
531 (skip-chars-forward " \t")
532 ;; Then change all newlines to spaces.
533 (subst-char-in-region from (point-max) ?\n ?\ )
534 (if (and nosqueeze (not (eq justify 'full)))
535 nil
536 (canonically-space-region (or squeeze-after (point)) (point-max))
537 (goto-char (point-max))
538 (delete-horizontal-space)
539 (insert-and-inherit " "))
540 (goto-char (point-min))
541 556
542 ;; This is the actual filling loop. 557 ;; This is the actual filling loop.
543 (let ((prefixcol 0) linebeg) 558 (let ((prefixcol 0) linebeg)
544 (while (not (eobp)) 559 (while (not (eobp))
545 (setq linebeg (point)) 560 (setq linebeg (point))
550 ;; at. We break the line between word or after/before 565 ;; at. We break the line between word or after/before
551 ;; the character which has character category `|'. We 566 ;; the character which has character category `|'. We
552 ;; search space, \c| followed by a character, or \c| 567 ;; search space, \c| followed by a character, or \c|
553 ;; following a character. If not found, place 568 ;; following a character. If not found, place
554 ;; the point at linebeg. 569 ;; the point at linebeg.
555 (if (re-search-backward " \\|\\c|.\\|.\\c|" linebeg 0) 570 (while
556 ;; In case of space, we place the point at next to 571 (when (re-search-backward "[ \t]\\|\\c|.\\|.\\c|" linebeg 0)
557 ;; the point where the break occurs acutually, 572 ;; In case of space, we place the point at next to
558 ;; because we don't want to change the following 573 ;; the point where the break occurs actually,
559 ;; logic of original Emacs. In case of \c|, the 574 ;; because we don't want to change the following
560 ;; point is at the place where the break occurs. 575 ;; logic of original Emacs. In case of \c|, the
561 (forward-char 1)) 576 ;; point is at the place where the break occurs.
562 ;; Don't break after a period followed by just one space. 577 (forward-char 1)
563 ;; Move back to the previous place to break. 578 (when (fill-nobreak-p) (skip-chars-backward " \t"))))
564 ;; The reason is that if a period ends up at the end of a line,
565 ;; further fills will assume it ends a sentence.
566 ;; If we now know it does not end a sentence,
567 ;; avoid putting it at the end of the line.
568 (while (and (> (point) linebeg)
569 (fill-nobreak-p)
570 (skip-chars-backward " \t"))
571 (if (re-search-backward " \\|\\c|.\\|.\\c|" linebeg 0)
572 (forward-char 1)))
573 ;; If the left margin and fill prefix by themselves 579 ;; If the left margin and fill prefix by themselves
574 ;; pass the fill-column. or if they are zero 580 ;; pass the fill-column. or if they are zero
575 ;; but we have no room for even one word, 581 ;; but we have no room for even one word,
576 ;; keep at least one word or a character which has 582 ;; keep at least one word or a character which has
577 ;; category `|'anyway . 583 ;; category `|'anyway .