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