aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2017-07-17 17:50:37 +0300
committerEli Zaretskii2017-07-17 17:50:37 +0300
commitd7f7fef1c1cdef206860a7075873de7d6c521d8d (patch)
treeabc7489210594cfdd4324404f1fe8155dfd58953
parent5e2ae74df54d4090c591c79ab13e7713c6654b9c (diff)
downloademacs-d7f7fef1c1cdef206860a7075873de7d6c521d8d.tar.gz
emacs-d7f7fef1c1cdef206860a7075873de7d6c521d8d.zip
Allow user control on what starts and ends a paragraph for bidi
* src/buffer.h (struct buffer): New members bidi_paragraph_separate_re_ and bidi_paragraph_start_re_. * src/buffer.c (bset_bidi_paragraph_start_re) (bset_bidi_paragraph_separate_re): New setters/ (Fbuffer_swap_text): Swap the values of bidi-paragraph-start-re and bidi-paragraph-separate-re. (init_buffer_once): Init the values of bidi-paragraph-start-re and bidi-paragraph-separate-re. (syms_of_buffer) <bidi-paragraph-start-re, bidi-paragraph-separate-re>: New per-buffer variables. * src/bidi.c (bidi_at_paragraph_end, bidi_find_paragraph_start): Support bidi-paragraph-start-re and bidi-paragraph-separate-re. (bidi_move_to_visually_next): Handle correctly the case when the separator matches an empty string. (Bug#27526) * doc/emacs/mule.texi (Bidirectional Editing): * doc/lispref/display.texi (Bidirectional Display): Document bidi-paragraph-start-re and bidi-paragraph-separate-re. * etc/NEWS: Mention bidi-paragraph-start-re and bidi-paragraph-separate-re.
-rw-r--r--doc/emacs/mule.texi40
-rw-r--r--doc/lispref/display.texi29
-rw-r--r--etc/NEWS6
-rw-r--r--src/bidi.c29
-rw-r--r--src/buffer.c59
-rw-r--r--src/buffer.h6
6 files changed, 145 insertions, 24 deletions
diff --git a/doc/emacs/mule.texi b/doc/emacs/mule.texi
index 8edf2640cfe..2f27b9aa0eb 100644
--- a/doc/emacs/mule.texi
+++ b/doc/emacs/mule.texi
@@ -1774,15 +1774,15 @@ Chars}).
1774@cindex bidirectional editing 1774@cindex bidirectional editing
1775@cindex right-to-left text 1775@cindex right-to-left text
1776 1776
1777 Emacs supports editing text written in scripts, such as Arabic and 1777 Emacs supports editing text written in scripts, such as Arabic,
1778Hebrew, whose natural ordering of horizontal text for display is from 1778Farsi, and Hebrew, whose natural ordering of horizontal text for
1779right to left. However, digits and Latin text embedded in these 1779display is from right to left. However, digits and Latin text
1780scripts are still displayed left to right. It is also not uncommon to 1780embedded in these scripts are still displayed left to right. It is
1781have small portions of text in Arabic or Hebrew embedded in an otherwise 1781also not uncommon to have small portions of text in Arabic or Hebrew
1782Latin document; e.g., as comments and strings in a program source 1782embedded in an otherwise Latin document; e.g., as comments and strings
1783file. For these reasons, text that uses these scripts is actually 1783in a program source file. For these reasons, text that uses these
1784@dfn{bidirectional}: a mixture of runs of left-to-right and 1784scripts is actually @dfn{bidirectional}: a mixture of runs of
1785right-to-left characters. 1785left-to-right and right-to-left characters.
1786 1786
1787 This section describes the facilities and options provided by Emacs 1787 This section describes the facilities and options provided by Emacs
1788for editing bidirectional text. 1788for editing bidirectional text.
@@ -1811,15 +1811,21 @@ directionality when they are displayed. The default value is
1811 1811
1812@cindex base direction of paragraphs 1812@cindex base direction of paragraphs
1813@cindex paragraph, base direction 1813@cindex paragraph, base direction
1814@vindex bidi-paragraph-start-re
1815@vindex bidi-paragraph-separate-re
1814 Each paragraph of bidirectional text can have its own @dfn{base 1816 Each paragraph of bidirectional text can have its own @dfn{base
1815direction}, either right-to-left or left-to-right. (Paragraph 1817direction}, either right-to-left or left-to-right. Text in
1816@c paragraph-separate etc have no influence on this? 1818left-to-right paragraphs begins on the screen at the left margin of
1817boundaries are empty lines, i.e., lines consisting entirely of 1819the window and is truncated or continued when it reaches the right
1818whitespace characters.) Text in left-to-right paragraphs begins on 1820margin. By contrast, text in right-to-left paragraphs is displayed
1819the screen at the left margin of the window and is truncated or 1821starting at the right margin and is continued or truncated at the left
1820continued when it reaches the right margin. By contrast, text in 1822margin. By default, paragraph boundaries are empty lines, i.e., lines
1821right-to-left paragraphs is displayed starting at the right margin and 1823consisting entirely of whitespace characters. To change that, you can
1822is continued or truncated at the left margin. 1824customize the two variables @code{bidi-paragraph-start-re} and
1825@code{bidi-paragraph-separate-re}, whose values should be regular
1826expressions (strings); e.g., to have a single newline start a new
1827paragraph, set both of these variables to @code{"^"}. These two
1828variables are buffer-local (@pxref{Locals}).
1823 1829
1824@vindex bidi-paragraph-direction 1830@vindex bidi-paragraph-direction
1825 Emacs determines the base direction of each paragraph dynamically, 1831 Emacs determines the base direction of each paragraph dynamically,
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 98940cbc996..5b8f58c1fd5 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -7456,6 +7456,35 @@ truncated or continued when the text reaches the right margin.
7456Right-to-left paragraphs are displayed beginning at the right margin, 7456Right-to-left paragraphs are displayed beginning at the right margin,
7457and are continued or truncated at the left margin. 7457and are continued or truncated at the left margin.
7458 7458
7459@cindex paragraph-start, and bidirectional display
7460@cindex paragraph-separate, and bidirectional display
7461 Where exactly paragraphs start and end, for the purpose of the Emacs
7462@acronym{UBA} implementation, is determined by the following two
7463buffer-local variables (note that that @code{paragraph-start} and
7464@code{paragraph-separate} have no influence on this). By default both
7465of these variables are @code{nil}, and paragraphs are bounded by empty
7466lines, i.e., lines that consist entirely of zero or more whitespace
7467characters followed by a newline.
7468
7469@defvar bidi-paragraph-start-re
7470If non-@code{nil}, this variable's value should be a regular
7471expression matching a line that starts or separates two paragraphs.
7472The regular expression is always matched after a newline, so it is
7473best to anchor it, i.e., begin it with a @code{"^"}.
7474@end defvar
7475
7476@defvar bidi-paragraph-separate-re
7477If non-@code{nil}, this variable's value should be a regular
7478expression matching a line separates two paragraphs. The regular
7479expression is always matched after a newline, so it is best to anch
7480it, i.e., begin it with a @code{"^"}.
7481@end defvar
7482
7483 If you modify any of these two variables, you should normally modify
7484both, to make sure they describe paragraphs consistently. For
7485example, to have each new line start a new paragraph for
7486bidi-reordering purposes, set both variables to @code{"^"}.
7487
7459 By default, Emacs determines the base direction of each paragraph by 7488 By default, Emacs determines the base direction of each paragraph by
7460looking at the text at its beginning. The precise method of 7489looking at the text at its beginning. The precise method of
7461determining the base direction is specified by the @acronym{UBA}; in a 7490determining the base direction is specified by the @acronym{UBA}; in a
diff --git a/etc/NEWS b/etc/NEWS
index dca562cb3b9..0c2db0c398b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -561,6 +561,12 @@ current buffer with the contents of the accessible portion of a
561different buffer while keeping point, mark, markers, and text 561different buffer while keeping point, mark, markers, and text
562properties as intact as possible. 562properties as intact as possible.
563 563
564+++
565** More user control of reordering bidirectional text for display.
566The two new variables, 'bidi-paragraph-start-re' and
567'bidi-paragraph-separate-re', allow customization of what exactly are
568paragraphs, for the purposes of bidirectional display.
569
564 570
565* Changes in Specialized Modes and Packages in Emacs 26.1 571* Changes in Specialized Modes and Packages in Emacs 26.1
566 572
diff --git a/src/bidi.c b/src/bidi.c
index e34da778ba0..763797488b0 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -1448,8 +1448,14 @@ bidi_at_paragraph_end (ptrdiff_t charpos, ptrdiff_t bytepos)
1448 Lisp_Object start_re; 1448 Lisp_Object start_re;
1449 ptrdiff_t val; 1449 ptrdiff_t val;
1450 1450
1451 sep_re = paragraph_separate_re; 1451 if (STRINGP (BVAR (current_buffer, bidi_paragraph_separate_re)))
1452 start_re = paragraph_start_re; 1452 sep_re = BVAR (current_buffer, bidi_paragraph_separate_re);
1453 else
1454 sep_re = paragraph_separate_re;
1455 if (STRINGP (BVAR (current_buffer, bidi_paragraph_start_re)))
1456 start_re = BVAR (current_buffer, bidi_paragraph_start_re);
1457 else
1458 start_re = paragraph_start_re;
1453 1459
1454 val = fast_looking_at (sep_re, charpos, bytepos, ZV, ZV_BYTE, Qnil); 1460 val = fast_looking_at (sep_re, charpos, bytepos, ZV, ZV_BYTE, Qnil);
1455 if (val < 0) 1461 if (val < 0)
@@ -1523,7 +1529,10 @@ bidi_paragraph_cache_on_off (void)
1523static ptrdiff_t 1529static ptrdiff_t
1524bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte) 1530bidi_find_paragraph_start (ptrdiff_t pos, ptrdiff_t pos_byte)
1525{ 1531{
1526 Lisp_Object re = paragraph_start_re; 1532 Lisp_Object re =
1533 STRINGP (BVAR (current_buffer, bidi_paragraph_start_re))
1534 ? BVAR (current_buffer, bidi_paragraph_start_re)
1535 : paragraph_start_re;
1527 ptrdiff_t limit = ZV, limit_byte = ZV_BYTE; 1536 ptrdiff_t limit = ZV, limit_byte = ZV_BYTE;
1528 struct region_cache *bpc = bidi_paragraph_cache_on_off (); 1537 struct region_cache *bpc = bidi_paragraph_cache_on_off ();
1529 ptrdiff_t n = 0, oldpos = pos, next; 1538 ptrdiff_t n = 0, oldpos = pos, next;
@@ -3498,10 +3507,16 @@ bidi_move_to_visually_next (struct bidi_it *bidi_it)
3498 if (sep_len >= 0) 3507 if (sep_len >= 0)
3499 { 3508 {
3500 bidi_it->new_paragraph = 1; 3509 bidi_it->new_paragraph = 1;
3501 /* Record the buffer position of the last character of the 3510 /* Record the buffer position of the last character of
3502 paragraph separator. */ 3511 the paragraph separator. If the paragraph separator
3503 bidi_it->separator_limit 3512 is an empty string (e.g., the regex is "^"), the
3504 = bidi_it->charpos + bidi_it->nchars + sep_len; 3513 newline that precedes the end of the paragraph is
3514 that last character. */
3515 if (sep_len > 0)
3516 bidi_it->separator_limit
3517 = bidi_it->charpos + bidi_it->nchars + sep_len;
3518 else
3519 bidi_it->separator_limit = bidi_it->charpos;
3505 } 3520 }
3506 } 3521 }
3507 } 3522 }
diff --git a/src/buffer.c b/src/buffer.c
index e0972aac33c..649ddbe1839 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -173,6 +173,16 @@ bset_bidi_display_reordering (struct buffer *b, Lisp_Object val)
173 b->bidi_display_reordering_ = val; 173 b->bidi_display_reordering_ = val;
174} 174}
175static void 175static void
176bset_bidi_paragraph_start_re (struct buffer *b, Lisp_Object val)
177{
178 b->bidi_paragraph_start_re_ = val;
179}
180static void
181bset_bidi_paragraph_separate_re (struct buffer *b, Lisp_Object val)
182{
183 b->bidi_paragraph_separate_re_ = val;
184}
185static void
176bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val) 186bset_buffer_file_coding_system (struct buffer *b, Lisp_Object val)
177{ 187{
178 b->buffer_file_coding_system_ = val; 188 b->buffer_file_coding_system_ = val;
@@ -2322,6 +2332,8 @@ results, see Info node `(elisp)Swapping Text'. */)
2322 swapfield_ (enable_multibyte_characters, Lisp_Object); 2332 swapfield_ (enable_multibyte_characters, Lisp_Object);
2323 swapfield_ (bidi_display_reordering, Lisp_Object); 2333 swapfield_ (bidi_display_reordering, Lisp_Object);
2324 swapfield_ (bidi_paragraph_direction, Lisp_Object); 2334 swapfield_ (bidi_paragraph_direction, Lisp_Object);
2335 swapfield_ (bidi_paragraph_separate_re, Lisp_Object);
2336 swapfield_ (bidi_paragraph_start_re, Lisp_Object);
2325 /* FIXME: Not sure what we should do with these *_marker fields. 2337 /* FIXME: Not sure what we should do with these *_marker fields.
2326 Hopefully they're just nil anyway. */ 2338 Hopefully they're just nil anyway. */
2327 swapfield_ (pt_marker, Lisp_Object); 2339 swapfield_ (pt_marker, Lisp_Object);
@@ -5121,6 +5133,8 @@ init_buffer_once (void)
5121 XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx; 5133 XSETFASTINT (BVAR (&buffer_local_flags, category_table), idx); ++idx;
5122 XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx; 5134 XSETFASTINT (BVAR (&buffer_local_flags, bidi_display_reordering), idx); ++idx;
5123 XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx; 5135 XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_direction), idx); ++idx;
5136 XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_separate_re), idx); ++idx;
5137 XSETFASTINT (BVAR (&buffer_local_flags, bidi_paragraph_start_re), idx); ++idx;
5124 XSETFASTINT (BVAR (&buffer_local_flags, buffer_file_coding_system), idx); 5138 XSETFASTINT (BVAR (&buffer_local_flags, buffer_file_coding_system), idx);
5125 /* Make this one a permanent local. */ 5139 /* Make this one a permanent local. */
5126 buffer_permanent_local_flags[idx++] = 1; 5140 buffer_permanent_local_flags[idx++] = 1;
@@ -5202,6 +5216,8 @@ init_buffer_once (void)
5202 bset_ctl_arrow (&buffer_defaults, Qt); 5216 bset_ctl_arrow (&buffer_defaults, Qt);
5203 bset_bidi_display_reordering (&buffer_defaults, Qt); 5217 bset_bidi_display_reordering (&buffer_defaults, Qt);
5204 bset_bidi_paragraph_direction (&buffer_defaults, Qnil); 5218 bset_bidi_paragraph_direction (&buffer_defaults, Qnil);
5219 bset_bidi_paragraph_start_re (&buffer_defaults, Qnil);
5220 bset_bidi_paragraph_separate_re (&buffer_defaults, Qnil);
5205 bset_cursor_type (&buffer_defaults, Qt); 5221 bset_cursor_type (&buffer_defaults, Qt);
5206 bset_extra_line_spacing (&buffer_defaults, Qnil); 5222 bset_extra_line_spacing (&buffer_defaults, Qnil);
5207 bset_cursor_in_non_selected_windows (&buffer_defaults, Qt); 5223 bset_cursor_in_non_selected_windows (&buffer_defaults, Qt);
@@ -5616,6 +5632,49 @@ This variable is never applied to a way of decoding a file while reading it. */
5616 &BVAR (current_buffer, bidi_display_reordering), Qnil, 5632 &BVAR (current_buffer, bidi_display_reordering), Qnil,
5617 doc: /* Non-nil means reorder bidirectional text for display in the visual order. */); 5633 doc: /* Non-nil means reorder bidirectional text for display in the visual order. */);
5618 5634
5635 DEFVAR_PER_BUFFER ("bidi-paragraph-start-re",
5636 &BVAR (current_buffer, bidi_paragraph_start_re), Qnil,
5637 doc: /* If non-nil, a regexp matching a line that starts OR separates paragraphs.
5638
5639The value of nil means to use empty lines as lines that start and
5640separate paragraphs.
5641
5642When Emacs displays bidirectional text, it by default computes
5643the base paragraph direction separately for each paragraph.
5644Setting this variable changes the places where paragraph base
5645direction is recomputed.
5646
5647The regexp is always matched after a newline, so it is best to
5648anchor it by beginning it with a "^".
5649
5650If you change the value of this variable, be sure to change
5651the value of `bidi-paragraph-separate-re' accordingly. For
5652example, to have a single newline behave as a paragraph separator,
5653set both these variables to "^".
5654
5655See also `bidi-paragraph-direction'. */);
5656
5657 DEFVAR_PER_BUFFER ("bidi-paragraph-separate-re",
5658 &BVAR (current_buffer, bidi_paragraph_separate_re), Qnil,
5659 doc: /* If non-nil, a regexp matching a line that separates paragraphs.
5660
5661The value of nil means to use empty lines as paragraph separators.
5662
5663When Emacs displays bidirectional text, it by default computes
5664the base paragraph direction separately for each paragraph.
5665Setting this variable changes the places where paragraph base
5666direction is recomputed.
5667
5668The regexp is always matched after a newline, so it is best to
5669anchor it by beginning it with a "^".
5670
5671If you change the value of this variable, be sure to change
5672the value of `bidi-paragraph-start-re' accordingly. For
5673example, to have a single newline behave as a paragraph separator,
5674set both these variables to "^".
5675
5676See also `bidi-paragraph-direction'. */);
5677
5619 DEFVAR_PER_BUFFER ("bidi-paragraph-direction", 5678 DEFVAR_PER_BUFFER ("bidi-paragraph-direction",
5620 &BVAR (current_buffer, bidi_paragraph_direction), Qnil, 5679 &BVAR (current_buffer, bidi_paragraph_direction), Qnil,
5621 doc: /* If non-nil, forces directionality of text paragraphs in the buffer. 5680 doc: /* If non-nil, forces directionality of text paragraphs in the buffer.
diff --git a/src/buffer.h b/src/buffer.h
index be270fe4823..46ca6aa7384 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -611,6 +611,12 @@ struct buffer
611 direction dynamically for each paragraph. */ 611 direction dynamically for each paragraph. */
612 Lisp_Object bidi_paragraph_direction_; 612 Lisp_Object bidi_paragraph_direction_;
613 613
614 /* If non-nil, a regular expression for bidi paragraph separator. */
615 Lisp_Object bidi_paragraph_separate_re_;
616
617 /* If non-nil, a regular expression for bidi paragraph start. */
618 Lisp_Object bidi_paragraph_start_re_;
619
614 /* Non-nil means do selective display; 620 /* Non-nil means do selective display;
615 see doc string in syms_of_buffer (buffer.c) for details. */ 621 see doc string in syms_of_buffer (buffer.c) for details. */
616 Lisp_Object selective_display_; 622 Lisp_Object selective_display_;