Merge from origin/emacs-29

a722e7dd15 Merge branch 'emacs-29' of git.savannah.gnu.org:/srv/git/...
65f146cf1c ; * lisp/calculator.el (calculator-need-3-lines): Fix las...
9e8386bdac Support cons cell as value of ':line-width' box attribute
1d2ba6b363 ; * admin/notes/tree-sitter/treesit_record_change: Update.
02b6be892f Add missing calls to treesit_record_change in editfns.c
e982192e93 Call treesit_record_change in subst-char-in-region (bug#6...
ddbb11f565 ; * lisp/misc.el (duplicate-line-final-position): Fix las...
cecbe92d5d ; * lisp/misc.el (duplicate-line-final-position): doc pre...
042f0d6a14 ; Fix documentation of ':box' face attribute

# Conflicts:
#	etc/NEWS
This commit is contained in:
Eli Zaretskii 2023-07-01 06:29:52 -04:00
commit fbdc85b8f8
6 changed files with 226 additions and 22 deletions

View file

@ -3,10 +3,10 @@ NOTES ON TREESIT_RECORD_CHANGE
It is vital that Emacs informs tree-sitter of every change made to the
buffer, lest tree-sitter's parse tree would be corrupted/out of sync.
All buffer changes in Emacs are made through functions in insdel.c
(and casefiddle.c), I augmented functions in those files with calls to
treesit_record_change. Below is a manifest of all the relevant
functions in insdel.c as of Emacs 29:
Almost all buffer changes in Emacs are made through functions in
insdel.c (see below for exceptions), I augmented functions in insdel.c
with calls to treesit_record_change. Below is a manifest of all the
relevant functions in insdel.c as of Emacs 29:
Function Calls
----------------------------------------------------------------------
@ -43,8 +43,176 @@ insert_from_buffer but not insert_from_buffer_1. I also left a
reminder comment.
As for casefiddle.c, do_casify_unibyte_region and
EXCEPTIONS
There are a couple of functions that replaces characters in-place
rather than insert/delete. They are in casefiddle.c and editfns.c.
In casefiddle.c, do_casify_unibyte_region and
do_casify_multibyte_region modifies buffer, but they are static
functions and are called by casify_region, which calls
treesit_record_change. Other higher-level functions calls
casify_region to do the work.
casify_region to do the work.
In editfns.c, subst-char-in-region and translate-region-internal might
replace characters in-place, I made them to call
treesit_record_change. transpose-regions uses memcpy to move text
around, it calls treesit_record_change too.
I found these exceptions by grepping for signal_after_change and
checking each caller manually. Below is all the result as of Emacs 29
and some comment for each one. Readers can use
(highlight-regexp "^[^[:space:]]+?\\.c:[[:digit:]]+:[^z-a]+?$" 'highlight)
to make things easier to read.
grep [...] --color=auto -i --directories=skip -nH --null -e signal_after_change *.c
callproc.c:789: calling prepare_to_modify_buffer and signal_after_change.
callproc.c:793: is one call to signal_after_change in each of the
callproc.c:800: signal_after_change hasn't. A continue statement
callproc.c:804: again, and this time signal_after_change gets called,
Not code.
callproc.c:820: signal_after_change (PT - nread, 0, nread);
callproc.c:863: signal_after_change (PT - process_coding.produced_char,
Both are called in call-process. I dont think well ever use
tree-sitter in call-processs stdio buffer, right? I didnt check
line-by-line, but it seems to only use insert_1_both and del_range_2.
casefiddle.c:558: signal_after_change (start, end - start - added, end - start);
Called in casify-region, calls treesit_record_change.
decompress.c:195: signal_after_change (data->orig, data->start - data->orig,
Called in unwind_decompress, uses del_range_2, insdel function.
decompress.c:334: signal_after_change (istart, iend - istart, unwind_data.nbytes);
Called in zlib-decompress-region, uses del_range_2, insdel function.
editfns.c:2139: signal_after_change (BEGV, size_a, ZV - BEGV);
Called in replace-buffer-contents, which calls del_range and
Finsert_buffer_substring, both are ok.
editfns.c:2416: signal_after_change (changed,
Called in subst-char-in-region, which either calls replace_range (a
insdel function) or modifies buffer content by itself (need to call
treesit_record_change).
editfns.c:2544: /* Reload as signal_after_change in last iteration may GC. */
Not code.
editfns.c:2604: signal_after_change (pos, 1, 1);
Called in translate-region-internal, which has three cases:
if (nc != oc && nc >= 0) {
if (len != str_len) {
replace_range()
} else {
while (str_len-- > 0)
*p++ = *str++;
}
}
else if (nc < 0) {
replace_range()
}
replace_range is ok, but in the case where it manually modifies buffer
content, it needs to call treesit_record_change.
editfns.c:4779: signal_after_change (start1, end2 - start1, end2 - start1);
Called in transpose-regions. It just uses memcpys and doesnt use
insdel functions; needs to call treesit_record_change.
fileio.c:4825: signal_after_change (PT, 0, inserted);
Called in insert_file_contents. Uses insert_1_both (very first in the
function); del_range_1 and del_range_byte (the optimized way to
implement replace when decoding isnt needed); del_range_byte and
insert_from_buffer (the optimized way used when decoding is needed);
decode_coding_gap or insert_from_gap_1 (Im not sure the condition for
this, but anyway its safe). The function also calls memcpy and
memmove, but they are irrelevant: memcpy is used for decoding, and
memmove is moving stuff inside the gap for decode_coding_gap.
Id love someone to verify this function, since its so complicated
and large, but from what I can tell its safe.
fns.c:3998: signal_after_change (XFIXNAT (beg), 0, inserted_chars);
Called in base64-decode-region, uses insert_1_both and del_range_both,
safe.
insdel.c:681: signal_after_change (opoint, 0, len);
insdel.c:696: signal_after_change (opoint, 0, len);
insdel.c:741: signal_after_change (opoint, 0, len);
insdel.c:757: signal_after_change (opoint, 0, len);
insdel.c:976: signal_after_change (opoint, 0, PT - opoint);
insdel.c:996: signal_after_change (opoint, 0, PT - opoint);
insdel.c:1187: signal_after_change (opoint, 0, PT - opoint);
insdel.c:1412: signal_after_change. */
insdel.c:1585: signal_after_change (from, nchars_del, GPT - from);
insdel.c:1600: prepare_to_modify_buffer and never call signal_after_change.
insdel.c:1603: region once. Apart from signal_after_change, any caller of this
insdel.c:1747: signal_after_change (from, to - from, 0);
insdel.c:1789: signal_after_change (from, to - from, 0);
insdel.c:1833: signal_after_change (from, to - from, 0);
insdel.c:2223:signal_after_change (ptrdiff_t charpos, ptrdiff_t lendel, ptrdiff_t lenins)
insdel.c:2396: signal_after_change (begpos, endpos - begpos - change, endpos - begpos);
Ive checked all insdel functions. We can assume insdel functions are
all safe.
json.c:790: signal_after_change (PT, 0, inserted);
Called in json-insert, calls either decode_coding_gap or
insert_from_gap_1, both are safe. Calls memmove but its for
decode_coding_gap.
keymap.c:2873: /* Insert calls signal_after_change which may GC. */
Not code.
print.c:219: signal_after_change (PT - print_buffer.pos, 0, print_buffer.pos);
Called in print_finish, calls copy_text and insert_1_both, safe.
process.c:6365: process buffer is changed in the signal_after_change above.
search.c:2763: (see signal_before_change and signal_after_change). Try to error
Not code.
search.c:2777: signal_after_change (sub_start, sub_end - sub_start, SCHARS (newtext));
Called in replace_match. Calls replace_range, upcase-region,
upcase-initials-region (both calls casify_region in the end), safe.
Calls memcpy but its for string manipulation.
textprop.c:1261: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1272: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1283: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1458: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1652: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1661: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1672: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1750: before changes are made and signal_after_change when we are done.
textprop.c:1752: and call signal_after_change before returning if MODIFIED. */
textprop.c:1764: signal_after_change (XFIXNUM (start),
textprop.c:1778: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1791: signal_after_change (XFIXNUM (start), XFIXNUM (end) - XFIXNUM (start),
textprop.c:1810: signal_after_change (XFIXNUM (start),
We dont care about text property changes.
Grep finished with 51 matches found at Wed Jun 28 15:12:23

View file

@ -698,7 +698,7 @@ between these modes while the user is inputting a command by hitting
works like 'duplicate-line'. An active rectangular region is
duplicated on its right-hand side. The new user option
'duplicate-line-final-position' specifies where to move point
after duplicating the line.
after duplicating a line.
---
** Files with the ".eld" extension are now visited in 'lisp-data-mode'.

View file

@ -746,7 +746,8 @@ See the documentation for `calculator-mode' for more information."
;; use 3 lines
(let* ((bx (face-attribute 'mode-line :box))
(lh (plist-get bx :line-width)))
(and bx (or (not lh) (> lh 0))))
;; Value of `:line-width' can be either a number or a cons.
(and bx (or (not lh) (> (if (consp lh) (cdr lh) lh) 0))))
;; if the mode line has an overline, use 3 lines
(not (memq (face-attribute 'mode-line :overline)
'(nil unspecified)))))))

View file

@ -794,19 +794,25 @@ around them. If VALUE is nil, explicitly don't draw boxes. If
VALUE is t, draw a box with lines of width 1 in the foreground color
of the face. If VALUE is a string, the string must be a color name,
and the box is drawn in that color with a line width of 1. Otherwise,
VALUE must be a property list of the form `(:line-width WIDTH
:color COLOR :style STYLE)'. If a keyword/value pair is missing from
the property list, a default value will be used for the value, as
specified below. WIDTH specifies the width of the lines to draw; it
defaults to 1. If WIDTH is negative, the absolute value is the width
of the lines, and draw top/bottom lines inside the characters area,
not around it. COLOR is the name of the color to draw in, default is
the background color of the face for 3D boxes and `flat-button', and
the foreground color of the face for other boxes. STYLE specifies
whether a 3D box should be draw. If STYLE is `released-button', draw
a box looking like a released 3D button. If STYLE is `pressed-button'
draw a box that appears like a pressed button. If STYLE is nil,
`flat-button' or omitted, draw a 2D box.
VALUE must be a property list of the following form:
(:line-width WIDTH :color COLOR :style STYLE)
If a keyword/value pair is missing from the property list, a default
value will be used for the value, as specified below.
WIDTH specifies the width of the lines to draw; it defaults to 1.
If WIDTH is negative, the absolute value is the width of the lines,
and draw top/bottom lines inside the characters area, not around it.
WIDTH can also be a cons (VWIDTH . HWIDTH), which specifies different
values for the vertical and the horizontal line width.
COLOR is the name of the color to use for the box lines, default is
the background color of the face for 3D and `flat-button' boxes, and
the foreground color of the face for the other boxes.
STYLE specifies whether a 3D box should be drawn. If STYLE
is `released-button', draw a box looking like a released 3D button.
If STYLE is `pressed-button', draw a box that looks like a pressed
button. If STYLE is nil, `flat-button', or omitted, draw a 2D box.
`:inverse-video'

View file

@ -64,7 +64,7 @@ Also see the `duplicate-line' command."
(insert string)))
(defcustom duplicate-line-final-position 0
"Where to put point after duplicating the line with `duplicate-line'.
"Where to put point after `duplicate-line' or `duplicate-dwim'.
When 0, leave point on the original line.
When 1, move point to the first new line.
When -1, move point to the last new line.

View file

@ -55,6 +55,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef WINDOWSNT
# include "w32common.h"
#endif
#ifdef HAVE_TREE_SITTER
#include "treesit.h"
#endif
static void update_buffer_properties (ptrdiff_t, ptrdiff_t);
static Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool);
@ -2391,6 +2396,14 @@ Both characters must have the same length of multi-byte form. */)
if (NILP (noundo))
record_change (pos, 1);
for (i = 0; i < len; i++) *p++ = tostr[i];
#ifdef HAVE_TREE_SITTER
/* In the previous branch, replace_range() notifies
changes to tree-sitter, but in this branch, we
modified buffer content manually, so we need to
notify tree-sitter manually. */
treesit_record_change (pos_byte, pos_byte + len, pos_byte + len);
#endif
}
last_changed = pos + 1;
}
@ -2590,6 +2603,15 @@ It returns the number of characters changed. */)
*p++ = *str++;
signal_after_change (pos, 1, 1);
update_compositions (pos, pos + 1, CHECK_BORDER);
#ifdef HAVE_TREE_SITTER
/* In the previous branch, replace_range() notifies
changes to tree-sitter, but in this branch, we
modified buffer content manually, so we need to
notify tree-sitter manually. */
treesit_record_change (pos_byte, pos_byte + len,
pos_byte + len);
#endif
}
characters_changed++;
}
@ -4763,6 +4785,13 @@ ring. */)
adjust_markers_bytepos (start1, start1_byte, end2, end2_byte, 0);
}
#ifdef HAVE_TREE_SITTER
/* I don't think it's common to transpose two far-apart regions, so
amalgamating the edit into one should be fine. This is what the
signal_after_change below does, too. */
treesit_record_change (start1_byte, end2_byte, end2_byte);
#endif
signal_after_change (start1, end2 - start1, end2 - start1);
return Qnil;
}