Add 2012 to FSF copyright years for Emacs files
[bpt/emacs.git] / lisp / textmodes / paragraphs.el
CommitLineData
55535639 1;;; paragraphs.el --- paragraph and sentence parsing
6594deb0 2
acaf905b 3;; Copyright (C) 1985-1987, 1991, 1994-1997, 1999-2012
36020642 4;; Free Software Foundation, Inc.
9750e079 5
4821e2af 6;; Maintainer: FSF
d7b4d18f 7;; Keywords: wp
bd78fa1d 8;; Package: emacs
4821e2af 9
a2535589
JA
10;; This file is part of GNU Emacs.
11
1fecc8fe 12;; GNU Emacs is free software: you can redistribute it and/or modify
a2535589 13;; it under the terms of the GNU General Public License as published by
1fecc8fe
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
a2535589
JA
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
1fecc8fe 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
a2535589 24
edbd2f74
ER
25;;; Commentary:
26
27;; This package provides the paragraph-oriented commands documented in the
28;; Emacs manual.
29
4821e2af 30;;; Code:
a2535589 31
e4550233
RS
32(defgroup paragraphs nil
33 "Paragraph and sentence parsing."
34 :group 'editing)
35
c28e534b 36(put 'use-hard-newlines 'permanent-local t)
07187d55 37(define-minor-mode use-hard-newlines
ac6c8639
CY
38 "Toggle distinguishing between hard and soft newlines.
39With a prefix argument ARG, enable the feature if ARG is
40positive, and disable it otherwise. If called from Lisp, enable
41it if ARG is omitted or nil.
42
43When enabled, the functions `newline' and `open-line' add the
965eb84a 44text-property `hard' to newlines that they insert, and a line is
55cc5677 45only considered as a candidate to match `paragraph-start' or
965eb84a 46`paragraph-separate' if it follows a hard newline.
55cc5677 47
ac6c8639
CY
48When enabling, if there are newlines in the buffer but no hard
49newlines, ask the user whether to mark as hard any newlines
50preceding a `paragraph-start' line. From a program, second arg
51INSERT specifies whether to do this; it can be `never' to change
52nothing, t or `always' to force marking, `guess' to try to do the
53right thing with no questions, nil or anything else to ask the
54user.
965eb84a
RS
55
56Newlines not marked hard are called \"soft\", and are always internal
57to paragraphs. The fill functions insert and delete only soft newlines."
eacd92dd 58 :group 'paragraphs
07187d55
SM
59 :extra-args (insert)
60 (when use-hard-newlines
965eb84a
RS
61 ;; Turn mode on
62 ;; Intuit hard newlines --
63 ;; mark as hard any newlines preceding a paragraph-start line.
64 (if (or (eq insert t) (eq insert 'always)
65 (and (not (eq 'never insert))
965eb84a
RS
66 (not (text-property-any (point-min) (point-max) 'hard t))
67 (save-excursion
68 (goto-char (point-min))
69 (search-forward "\n" nil t))
70 (or (eq insert 'guess)
71 (y-or-n-p "Make newlines between paragraphs hard? "))))
72 (save-excursion
73 (goto-char (point-min))
74 (while (search-forward "\n" nil t)
75 (let ((pos (point)))
76 (move-to-left-margin)
07187d55
SM
77 (when (looking-at paragraph-start)
78 (set-hard-newline-properties (1- pos) pos))
79 ;; If paragraph-separate, newline after it is hard too.
80 (when (looking-at paragraph-separate)
81 (set-hard-newline-properties (1- pos) pos)
82 (end-of-line)
83 (unless (eobp)
84 (set-hard-newline-properties (point) (1+ (point)))))))))))
55cc5677 85
07187d55 86(defcustom paragraph-start "\f\\|[ \t]*$" "\
85e17b4f 87Regexp for beginning of a line that starts OR separates paragraphs.
1f2007b3
RS
88This regexp should match lines that separate paragraphs
89and should also match lines that start a paragraph
90\(and are part of that paragraph).
a37669ec 91
55cc5677
BG
92This is matched against the text at the left margin, which is not necessarily
93the beginning of the line, so it should never use \"^\" as an anchor. This
94ensures that the paragraph functions will work equally well within a region
95of text indented by a margin setting.
96
1f2007b3 97The variable `paragraph-separate' specifies how to distinguish
a37669ec
RS
98lines that start paragraphs from lines that separate them.
99
3f5dc0b0 100If the variable `use-hard-newlines' is non-nil, then only lines following a
e4550233
RS
101hard newline are considered to match."
102 :group 'paragraphs
103 :type 'regexp)
f31b1257 104(put 'paragraph-start 'safe-local-variable 'stringp)
6503cec3 105
55cc5677
BG
106;; paragraph-start requires a hard newline, but paragraph-separate does not:
107;; It is assumed that paragraph-separate is distinctive enough to be believed
108;; whenever it occurs, while it is reasonable to set paragraph-start to
109;; something very minimal, even including "." (which makes every hard newline
110;; start a new paragraph).
111
e4550233 112(defcustom paragraph-separate "[ \t\f]*$"
85e17b4f 113 "Regexp for beginning of a line that separates paragraphs.
9d7c4eb5 114If you change this, you may have to change `paragraph-start' also.
a37669ec 115
55cc5677
BG
116This is matched against the text at the left margin, which is not necessarily
117the beginning of the line, so it should not use \"^\" as an anchor. This
118ensures that the paragraph functions will work equally within a region of
e4550233
RS
119text indented by a margin setting."
120 :group 'paragraphs
121 :type 'regexp)
f31b1257 122(put 'paragraph-separate 'safe-local-variable 'stringp)
6503cec3 123
629261c7 124(defcustom sentence-end-double-space t
85e17b4f 125 "Non-nil means a single space does not end a sentence.
629261c7
SM
126This is relevant for filling. See also `sentence-end-without-period'
127and `colon-double-space'.
128
32e40471 129This value is used by the function `sentence-end' to construct the
51d7369e
LT
130regexp describing the end of a sentence, when the value of the variable
131`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
629261c7
SM
132 :type 'boolean
133 :group 'fill)
f31b1257 134(put 'sentence-end-double-space 'safe-local-variable 'booleanp)
629261c7
SM
135
136(defcustom sentence-end-without-period nil
85e17b4f 137 "Non-nil means a sentence will end without a period.
629261c7 138For example, a sentence in Thai text ends with double space but
32e40471
JL
139without a period.
140
141This value is used by the function `sentence-end' to construct the
51d7369e
LT
142regexp describing the end of a sentence, when the value of the variable
143`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
629261c7
SM
144 :type 'boolean
145 :group 'fill)
f31b1257 146(put 'sentence-end-without-period 'safe-local-variable 'booleanp)
629261c7 147
9402a4b9 148(defcustom sentence-end-without-space
98819490 149 "。.?!"
85e17b4f 150 "String of characters that end sentence without following spaces.
32e40471
JL
151
152This value is used by the function `sentence-end' to construct the
51d7369e
LT
153regexp describing the end of a sentence, when the value of the variable
154`sentence-end' is nil. See Info node `(elisp)Standard Regexps'."
9402a4b9
KH
155 :group 'paragraphs
156 :type 'string)
f31b1257 157(put 'sentence-end-without-space 'safe-local-variable 'stringp)
9402a4b9 158
32e40471 159(defcustom sentence-end nil
85e17b4f 160 "Regexp describing the end of a sentence.
ac1470eb 161The value includes the whitespace following the sentence.
51534471
JB
162All paragraph boundaries also end sentences, regardless.
163
32e40471
JL
164The value nil means to use the default value defined by the
165function `sentence-end'. You should always use this function
166to obtain the value of this variable."
e4550233 167 :group 'paragraphs
32e40471 168 :type '(choice regexp (const :tag "Use default value" nil)))
f31b1257 169(put 'sentence-end 'safe-local-variable 'string-or-null-p)
32e40471 170
98819490 171(defcustom sentence-end-base "[.?!][]\"'”)}]*"
85e17b4f 172 "Regexp matching the basic end of a sentence, not including following space."
f4b80eb1
RS
173 :group 'paragraphs
174 :type 'string
175 :version "22.1")
f31b1257 176(put 'sentence-end-base 'safe-local-variable 'stringp)
f4b80eb1 177
32e40471
JL
178(defun sentence-end ()
179 "Return the regexp describing the end of a sentence.
180
181This function returns either the value of the variable `sentence-end'
182if it is non-nil, or the default value constructed from the
f4b80eb1
RS
183variables `sentence-end-base', `sentence-end-double-space',
184`sentence-end-without-period' and `sentence-end-without-space'.
185
186The default value specifies that in order to be recognized as the
187end of a sentence, the ending period, question mark, or exclamation point
188must be followed by two spaces, with perhaps some closing delimiters
189in between. See Info node `(elisp)Standard Regexps'."
32e40471 190 (or sentence-end
38cb7a93
RS
191 ;; We accept non-break space along with space.
192 (concat (if sentence-end-without-period "\\w[ \u00a0][ \u00a0]\\|")
f4b80eb1
RS
193 "\\("
194 sentence-end-base
32e40471 195 (if sentence-end-double-space
38cb7a93 196 "\\($\\|[ \u00a0]$\\|\t\\|[ \u00a0][ \u00a0]\\)" "\\($\\|[\t \u00a0]\\)")
f4b80eb1
RS
197 "\\|[" sentence-end-without-space "]+"
198 "\\)"
38cb7a93 199 "[ \u00a0\t\n]*")))
e4550233
RS
200
201(defcustom page-delimiter "^\014"
85e17b4f 202 "Regexp describing line-beginnings that separate pages."
e4550233
RS
203 :group 'paragraphs
204 :type 'regexp)
f31b1257 205(put 'page-delimiter 'safe-local-variable 'stringp)
e4550233
RS
206
207(defcustom paragraph-ignore-fill-prefix nil
85e17b4f 208 "Non-nil means the paragraph commands are not affected by `fill-prefix'.
e4550233
RS
209This is desirable in modes where blank lines are the paragraph delimiters."
210 :group 'paragraphs
211 :type 'boolean)
f31b1257 212(put 'paragraph-ignore-fill-prefix 'safe-local-variable 'booleanp)
77176e73 213
a2535589
JA
214(defun forward-paragraph (&optional arg)
215 "Move forward to end of paragraph.
94d63a23
RS
216With argument ARG, do it ARG times;
217a negative argument ARG = -N means move backward N paragraphs.
a2535589
JA
218
219A line which `paragraph-start' matches either separates paragraphs
220\(if `paragraph-separate' matches it also) or is the first line of a paragraph.
221A paragraph end is the beginning of a line which is not part of the paragraph
de24b077
SM
222to which the end of the previous line belongs, or the end of the buffer.
223Returns the count of paragraphs left to move."
2169fd55 224 (interactive "^p")
a2535589 225 (or arg (setq arg 1))
17cca868
GM
226 (let* ((opoint (point))
227 (fill-prefix-regexp
a2535589
JA
228 (and fill-prefix (not (equal fill-prefix ""))
229 (not paragraph-ignore-fill-prefix)
230 (regexp-quote fill-prefix)))
55cc5677
BG
231 ;; Remove ^ from paragraph-start and paragraph-sep if they are there.
232 ;; These regexps shouldn't be anchored, because we look for them
233 ;; starting at the left-margin. This allows paragraph commands to
234 ;; work normally with indented text.
235 ;; This hack will not find problem cases like "whatever\\|^something".
629261c7
SM
236 (parstart (if (and (not (equal "" paragraph-start))
237 (equal ?^ (aref paragraph-start 0)))
238 (substring paragraph-start 1)
239 paragraph-start))
240 (parsep (if (and (not (equal "" paragraph-separate))
241 (equal ?^ (aref paragraph-separate 0)))
242 (substring paragraph-separate 1)
243 paragraph-separate))
244 (parsep
a2535589 245 (if fill-prefix-regexp
629261c7 246 (concat parsep "\\|"
a2535589 247 fill-prefix-regexp "[ \t]*$")
629261c7 248 parsep))
55cc5677 249 ;; This is used for searching.
629261c7 250 (sp-parstart (concat "^[ \t]*\\(?:" parstart "\\|" parsep "\\)"))
eeb0f327 251 start found-start)
8a2a4ced 252 (while (and (< arg 0) (not (bobp)))
629261c7 253 (if (and (not (looking-at parsep))
a37669ec 254 (re-search-backward "^\n" (max (1- (point)) (point-min)) t)
629261c7 255 (looking-at parsep))
de24b077 256 (setq arg (1+ arg))
2be01738 257 (setq start (point))
8a2a4ced 258 ;; Move back over paragraph-separating lines.
a2535589 259 (forward-char -1) (beginning-of-line)
a37669ec 260 (while (and (not (bobp))
55cc5677 261 (progn (move-to-left-margin)
629261c7 262 (looking-at parsep)))
3f5dc0b0 263 (forward-line -1))
8a2a4ced
RS
264 (if (bobp)
265 nil
de24b077 266 (setq arg (1+ arg))
8a2a4ced
RS
267 ;; Go to end of the previous (non-separating) line.
268 (end-of-line)
269 ;; Search back for line that starts or separates paragraphs.
270 (if (if fill-prefix-regexp
629261c7 271 ;; There is a fill prefix; it overrides parstart.
2be01738 272 (let (multiple-lines)
55cc5677
BG
273 (while (and (progn (beginning-of-line) (not (bobp)))
274 (progn (move-to-left-margin)
629261c7 275 (not (looking-at parsep)))
55cc5677 276 (looking-at fill-prefix-regexp))
3f5dc0b0
SM
277 (unless (= (point) start)
278 (setq multiple-lines t))
55cc5677 279 (forward-line -1))
2be01738 280 (move-to-left-margin)
629261c7
SM
281 ;; This deleted code caused a long hanging-indent line
282 ;; not to be filled together with the following lines.
283 ;; ;; Don't move back over a line before the paragraph
284 ;; ;; which doesn't start with fill-prefix
285 ;; ;; unless that is the only line we've moved over.
286 ;; (and (not (looking-at fill-prefix-regexp))
287 ;; multiple-lines
288 ;; (forward-line 1))
2be01738 289 (not (bobp)))
629261c7 290 (while (and (re-search-backward sp-parstart nil 1)
eeb0f327 291 (setq found-start t)
55cc5677 292 ;; Found a candidate, but need to check if it is a
629261c7 293 ;; REAL parstart.
55cc5677
BG
294 (progn (setq start (point))
295 (move-to-left-margin)
629261c7
SM
296 (not (looking-at parsep)))
297 (not (and (looking-at parstart)
298 (or (not use-hard-newlines)
30857a61
LT
299 (bobp)
300 (get-text-property
301 (1- start) 'hard)))))
eeb0f327 302 (setq found-start nil)
55cc5677 303 (goto-char start))
eeb0f327 304 found-start)
de24b077
SM
305 ;; Found one.
306 (progn
8a2a4ced
RS
307 ;; Move forward over paragraph separators.
308 ;; We know this cannot reach the place we started
309 ;; because we know we moved back over a non-separator.
55cc5677
BG
310 (while (and (not (eobp))
311 (progn (move-to-left-margin)
629261c7 312 (looking-at parsep)))
8a2a4ced 313 (forward-line 1))
55cc5677
BG
314 ;; If line before paragraph is just margin, back up to there.
315 (end-of-line 0)
316 (if (> (current-column) (current-left-margin))
317 (forward-char 1)
318 (skip-chars-backward " \t")
319 (if (not (bolp))
320 (forward-line 1))))
8a2a4ced 321 ;; No starter or separator line => use buffer beg.
de24b077 322 (goto-char (point-min))))))
629261c7 323
8a2a4ced 324 (while (and (> arg 0) (not (eobp)))
de24b077
SM
325 ;; Move forward over separator lines...
326 (while (and (not (eobp))
327 (progn (move-to-left-margin) (not (eobp)))
328 (looking-at parsep))
329 (forward-line 1))
330 (unless (eobp) (setq arg (1- arg)))
331 ;; ... and one more line.
332 (forward-line 1)
a2535589 333 (if fill-prefix-regexp
629261c7 334 ;; There is a fill prefix; it overrides parstart.
a2535589 335 (while (and (not (eobp))
55cc5677 336 (progn (move-to-left-margin) (not (eobp)))
629261c7 337 (not (looking-at parsep))
a2535589
JA
338 (looking-at fill-prefix-regexp))
339 (forward-line 1))
629261c7 340 (while (and (re-search-forward sp-parstart nil 1)
55cc5677
BG
341 (progn (setq start (match-beginning 0))
342 (goto-char start)
4669fb3c
RS
343 (not (eobp)))
344 (progn (move-to-left-margin)
629261c7
SM
345 (not (looking-at parsep)))
346 (or (not (looking-at parstart))
55cc5677
BG
347 (and use-hard-newlines
348 (not (get-text-property (1- start) 'hard)))))
a37669ec
RS
349 (forward-char 1))
350 (if (< (point) (point-max))
de24b077 351 (goto-char start))))
7b462fc6
SM
352 (constrain-to-field nil opoint t)
353 ;; Return the number of steps that could not be done.
354 arg))
a2535589
JA
355
356(defun backward-paragraph (&optional arg)
357 "Move backward to start of paragraph.
94d63a23
RS
358With argument ARG, do it ARG times;
359a negative argument ARG = -N means move forward N paragraphs.
a2535589 360
23b34992 361A paragraph start is the beginning of a line which is a
2900c113
SM
362`paragraph-start' or which is ordinary text and follows a
363`paragraph-separate'ing line; except: if the first real line of a
23b34992
BP
364paragraph is preceded by a blank line, the paragraph starts at that
365blank line.
366
367See `forward-paragraph' for more information."
2169fd55 368 (interactive "^p")
a2535589
JA
369 (or arg (setq arg 1))
370 (forward-paragraph (- arg)))
371
94ed0931 372(defun mark-paragraph (&optional arg allow-extend)
a2535589 373 "Put point at beginning of this paragraph, mark at end.
f48b59a2
KG
374The paragraph marked is the one that contains point or follows point.
375
376With argument ARG, puts mark at end of a following paragraph, so that
377the number of paragraphs marked equals ARG.
378
379If ARG is negative, point is put at end of this paragraph, mark is put
cad113ae
KG
380at beginning of this or a previous paragraph.
381
94ed0931 382Interactively, if this command is repeated
3731a850 383or (in Transient Mark mode) if the mark is active,
94ed0931
RS
384it marks the next ARG paragraphs after the ones already marked."
385 (interactive "p\np")
be0d25b6
KG
386 (unless arg (setq arg 1))
387 (when (zerop arg)
388 (error "Cannot mark zero paragraphs"))
94ed0931
RS
389 (cond ((and allow-extend
390 (or (and (eq last-command this-command) (mark t))
391 (and transient-mark-mode mark-active)))
be0d25b6
KG
392 (set-mark
393 (save-excursion
394 (goto-char (mark))
395 (forward-paragraph arg)
396 (point))))
397 (t
398 (forward-paragraph arg)
399 (push-mark nil t t)
400 (backward-paragraph arg))))
a2535589
JA
401
402(defun kill-paragraph (arg)
403 "Kill forward to end of paragraph.
404With arg N, kill forward to Nth end of paragraph;
405negative arg -N means kill backward to Nth start of paragraph."
275cf1b2 406 (interactive "p")
8d6eaa00 407 (kill-region (point) (progn (forward-paragraph arg) (point))))
a2535589
JA
408
409(defun backward-kill-paragraph (arg)
410 "Kill back to start of paragraph.
411With arg N, kill back to Nth start of paragraph;
412negative arg -N means kill forward to Nth end of paragraph."
275cf1b2 413 (interactive "p")
17cca868 414 (kill-region (point) (progn (backward-paragraph arg) (point))))
a2535589
JA
415
416(defun transpose-paragraphs (arg)
36020642
GM
417 "Interchange the current paragraph with the next one.
418With prefix argument ARG a non-zero integer, moves the current
419paragraph past ARG paragraphs, leaving point after the current paragraph.
420If ARG is positive, moves the current paragraph forwards, if
421ARG is negative moves it backwards. If ARG is zero, exchanges
422the current paragraph with the one containing the mark."
a2535589
JA
423 (interactive "*p")
424 (transpose-subr 'forward-paragraph arg))
425
426(defun start-of-paragraph-text ()
427 (let ((opoint (point)) npoint)
428 (forward-paragraph -1)
429 (setq npoint (point))
430 (skip-chars-forward " \t\n")
b4e6c391
RS
431 ;; If the range of blank lines found spans the original start point,
432 ;; try again from the beginning of it.
433 ;; Must be careful to avoid infinite loop
434 ;; when following a single return at start of buffer.
435 (if (and (>= (point) opoint) (< npoint opoint))
a2535589
JA
436 (progn
437 (goto-char npoint)
438 (if (> npoint (point-min))
439 (start-of-paragraph-text))))))
440
441(defun end-of-paragraph-text ()
442 (let ((opoint (point)))
443 (forward-paragraph 1)
444 (if (eq (preceding-char) ?\n) (forward-char -1))
445 (if (<= (point) opoint)
446 (progn
447 (forward-char 1)
448 (if (< (point) (point-max))
449 (end-of-paragraph-text))))))
450
451(defun forward-sentence (&optional arg)
33127d1a
JB
452 "Move forward to next end of sentence. With argument, repeat.
453With negative argument, move backward repeatedly to start of sentence.
a2535589 454
23b34992
BP
455The variable `sentence-end' is a regular expression that matches ends of
456sentences. Also, every paragraph boundary terminates sentences as well."
2169fd55 457 (interactive "^p")
a2535589 458 (or arg (setq arg 1))
32e40471
JL
459 (let ((opoint (point))
460 (sentence-end (sentence-end)))
17cca868 461 (while (< arg 0)
ea2c6478 462 (let ((pos (point))
e488d29c
RS
463 par-beg par-text-beg)
464 (save-excursion
465 (start-of-paragraph-text)
466 ;; Start of real text in the paragraph.
467 ;; We move back to here if we don't see a sentence-end.
468 (setq par-text-beg (point))
469 ;; Start of the first line of the paragraph.
470 ;; We use this as the search limit
471 ;; to allow s1entence-end to match if it is anchored at
472 ;; BOL and the paragraph starts indented.
473 (beginning-of-line)
474 (setq par-beg (point)))
8f098516
RS
475 (if (and (re-search-backward sentence-end par-beg t)
476 (or (< (match-end 0) pos)
477 (re-search-backward sentence-end par-beg t)))
478 (goto-char (match-end 0))
e488d29c 479 (goto-char par-text-beg)))
17cca868
GM
480 (setq arg (1+ arg)))
481 (while (> arg 0)
482 (let ((par-end (save-excursion (end-of-paragraph-text) (point))))
8f098516
RS
483 (if (re-search-forward sentence-end par-end t)
484 (skip-chars-backward " \t\n")
485 (goto-char par-end)))
17cca868
GM
486 (setq arg (1- arg)))
487 (constrain-to-field nil opoint t)))
a2535589 488
d320a41d 489(defun repunctuate-sentences ()
d320a41d
RS
490 "Put two spaces at the end of sentences from point to the end of buffer.
491It works using `query-replace-regexp'."
279dffd6 492 (interactive)
d320a41d
RS
493 (query-replace-regexp "\\([]\"')]?\\)\\([.?!]\\)\\([]\"')]?\\) +"
494 "\\1\\2\\3 "))
495
496
a2535589
JA
497(defun backward-sentence (&optional arg)
498 "Move backward to start of sentence. With arg, do it arg times.
23b34992 499See `forward-sentence' for more information."
2169fd55 500 (interactive "^p")
a2535589
JA
501 (or arg (setq arg 1))
502 (forward-sentence (- arg)))
503
504(defun kill-sentence (&optional arg)
505 "Kill from point to end of sentence.
506With arg, repeat; negative arg -N means kill back to Nth start of sentence."
275cf1b2 507 (interactive "p")
8d6eaa00 508 (kill-region (point) (progn (forward-sentence arg) (point))))
a2535589
JA
509
510(defun backward-kill-sentence (&optional arg)
511 "Kill back from point to start of sentence.
512With arg, repeat, or kill forward to Nth end of sentence if negative arg -N."
275cf1b2 513 (interactive "p")
17cca868 514 (kill-region (point) (progn (backward-sentence arg) (point))))
a2535589
JA
515
516(defun mark-end-of-sentence (arg)
cad113ae
KG
517 "Put mark at end of sentence. Arg works as in `forward-sentence'.
518If this command is repeated, it marks the next ARG sentences after the
519ones already marked."
a2535589
JA
520 (interactive "p")
521 (push-mark
cad113ae
KG
522 (save-excursion
523 (if (and (eq last-command this-command) (mark t))
524 (goto-char (mark)))
525 (forward-sentence arg)
526 (point))
527 nil t))
a2535589
JA
528
529(defun transpose-sentences (arg)
36020642
GM
530 "Interchange the current sentence with the next one.
531With prefix argument ARG a non-zero integer, moves the current
532sentence past ARG sentences, leaving point after the current sentence.
533If ARG is positive, moves the current sentence forwards, if
534ARG is negative moves it backwards. If ARG is zero, exchanges
535the current sentence with the one containing the mark."
a2535589
JA
536 (interactive "*p")
537 (transpose-subr 'forward-sentence arg))
6594deb0 538
75538b71 539;; Local Variables:
98819490 540;; coding: utf-8
75538b71 541;; End:
cc4fe8d2 542
6594deb0 543;;; paragraphs.el ends here