From b408df11e350941eb099cde87d83340e8e7e0378 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 29 Apr 2023 11:50:47 +0300 Subject: [PATCH 1/5] Optimize search for composable characters in redisplay * src/composite.c (composition_compute_stop_pos): Accept new argument INCLUDE_STATIC, and look for potential static compositions only if this argument is non-zero. * src/xdisp.c: * src/composite.c: * src/indent.c: All callers adjusted. * src/xdisp.c (compute_stop_pos): Don't search for static compositions. Search for automatic compositions only after the iterator gets past the composition stop_pos computed last time. Use a better position for limiting search for automatic compositions. (Bug#62780) --- src/composite.c | 16 +++++++++++----- src/composite.h | 2 +- src/indent.c | 8 ++++---- src/xdisp.c | 35 +++++++++++++++++++++++++---------- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/composite.c b/src/composite.c index 164eeb39598..34f369d167a 100644 --- a/src/composite.c +++ b/src/composite.c @@ -1040,7 +1040,9 @@ inhibit_auto_composition (void) composition closest to CHARPOS is found, set cmp_it->stop_pos to the last character of the composition. STRING, if non-nil, is the string (as opposed to a buffer) whose characters should be - tested for being composable. + tested for being composable. INCLUDE_STATIC non-zero means + consider both static and automatic compositions; if zero, look + only for potential automatic compositions. If no composition is found, set cmp_it->ch to -2. If a static composition is found, set cmp_it->ch to -1. Otherwise, set @@ -1050,7 +1052,7 @@ inhibit_auto_composition (void) void composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t endpos, - Lisp_Object string) + Lisp_Object string, bool include_static) { ptrdiff_t start, end; int c; @@ -1084,8 +1086,10 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, cmp_it->stop_pos = endpos; if (charpos == endpos) return; + /* Look for static compositions. */ /* FIXME: Bidi is not yet handled well in static composition. */ - if (charpos < endpos + if (include_static + && charpos < endpos && find_composition (charpos, endpos, &start, &end, &prop, string) && start >= charpos && composition_valid_p (start, end, prop)) @@ -1106,6 +1110,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos, bytepos = string_char_to_byte (string, charpos); } + /* Look for automatic compositions. */ start = charpos; if (charpos < endpos) { @@ -1285,7 +1290,8 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, { if (cmp_it->ch == -2) { - composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string); + composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string, + true); if (cmp_it->ch == -2 || cmp_it->stop_pos != charpos) /* The current position is not composed. */ return 0; @@ -1424,7 +1430,7 @@ composition_reseat_it (struct composition_it *cmp_it, ptrdiff_t charpos, } if (cmp_it->reversed_p) endpos = -1; - composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string); + composition_compute_stop_pos (cmp_it, charpos, bytepos, endpos, string, true); return 0; } diff --git a/src/composite.h b/src/composite.h index e81465d90cc..0f791c1ea62 100644 --- a/src/composite.h +++ b/src/composite.h @@ -348,7 +348,7 @@ extern bool find_automatic_composition (ptrdiff_t, ptrdiff_t, ptrdiff_t, extern void composition_compute_stop_pos (struct composition_it *, ptrdiff_t, ptrdiff_t, ptrdiff_t, - Lisp_Object); + Lisp_Object, bool); extern bool composition_reseat_it (struct composition_it *, ptrdiff_t, ptrdiff_t, ptrdiff_t, struct window *, signed char, struct face *, Lisp_Object); diff --git a/src/indent.c b/src/indent.c index 08d2bf5ea28..16285ce84e2 100644 --- a/src/indent.c +++ b/src/indent.c @@ -616,7 +616,7 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, memset (&cmp_it, 0, sizeof cmp_it); cmp_it.id = -1; - composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil); + composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, Qnil, true); /* Scan forward to the target position. */ while (scan < end) @@ -681,7 +681,7 @@ scan_for_column (ptrdiff_t *endpos, EMACS_INT *goalcol, { cmp_it.id = -1; composition_compute_stop_pos (&cmp_it, scan, scan_byte, end, - Qnil); + Qnil, true); } else cmp_it.from = cmp_it.to; @@ -1290,7 +1290,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos, prev_tab_offset = tab_offset; memset (&cmp_it, 0, sizeof cmp_it); cmp_it.id = -1; - composition_compute_stop_pos (&cmp_it, pos, pos_byte, to, Qnil); + composition_compute_stop_pos (&cmp_it, pos, pos_byte, to, Qnil, true); unsigned short int quit_count = 0; @@ -1600,7 +1600,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos, { cmp_it.id = -1; composition_compute_stop_pos (&cmp_it, pos, pos_byte, to, - Qnil); + Qnil, true); } else cmp_it.from = cmp_it.to; diff --git a/src/xdisp.c b/src/xdisp.c index 76d6592bf00..18ea042e212 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -4056,7 +4056,7 @@ compute_stop_pos (struct it *it) { register INTERVAL iv, next_iv; Lisp_Object object, limit, position; - ptrdiff_t charpos, bytepos; + ptrdiff_t charpos, bytepos, cmp_limit_pos = -1; if (STRINGP (it->string)) { @@ -4126,7 +4126,10 @@ compute_stop_pos (struct it *it) } } if (found) - pos--; + { + pos--; + cmp_limit_pos = pos; + } else if (it->stop_charpos < endpos) pos = it->stop_charpos; else @@ -4184,14 +4187,25 @@ compute_stop_pos (struct it *it) } } - if (it->cmp_it.id < 0) + if (it->cmp_it.id < 0 + && (STRINGP (it->string) + || ((!it->bidi_p || it->bidi_it.scan_dir >= 0) + && it->cmp_it.stop_pos <= IT_CHARPOS (*it)))) { ptrdiff_t stoppos = it->end_charpos; + /* If we found, above, a buffer position that cannot be part of + an automatic composition, limit the search of composable + characters to that position. */ if (it->bidi_p && it->bidi_it.scan_dir < 0) stoppos = -1; + else if (cmp_limit_pos > 0) + stoppos = cmp_limit_pos; + /* Force composition_compute_stop_pos avoid the costly search + for static compositions, since those were already found by + looking at text properties, above. */ composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, - stoppos, it->string); + stoppos, it->string, false); } eassert (STRINGP (it->string) @@ -7716,7 +7730,7 @@ reseat_to_string (struct it *it, const char *s, Lisp_Object string, if (endpos > it->end_charpos) endpos = it->end_charpos; composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos, - it->string); + it->string, true); } CHECK_IT (it); } @@ -8404,7 +8418,7 @@ set_iterator_to_next (struct it *it, bool reseat_p) where to stop. */ stop = -1; composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), - IT_BYTEPOS (*it), stop, Qnil); + IT_BYTEPOS (*it), stop, Qnil, true); } } else @@ -8435,7 +8449,8 @@ set_iterator_to_next (struct it *it, bool reseat_p) if (it->bidi_it.scan_dir < 0) stop = -1; composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it), - IT_BYTEPOS (*it), stop, Qnil); + IT_BYTEPOS (*it), stop, Qnil, + true); } } eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it))); @@ -8591,7 +8606,7 @@ set_iterator_to_next (struct it *it, bool reseat_p) composition_compute_stop_pos (&it->cmp_it, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it), stop, - it->string); + it->string, true); } } else @@ -8628,7 +8643,7 @@ set_iterator_to_next (struct it *it, bool reseat_p) composition_compute_stop_pos (&it->cmp_it, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it), stop, - it->string); + it->string, true); } } } @@ -8879,7 +8894,7 @@ get_visually_first_element (struct it *it) if (it->bidi_it.scan_dir < 0) stop = -1; composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop, - it->string); + it->string, true); } } From e0e93f7eecca4fc12ba898a9bc923566ff45c646 Mon Sep 17 00:00:00 2001 From: Wilhelm H Kirschbaum Date: Thu, 27 Apr 2023 11:39:39 +0200 Subject: [PATCH 2/5] Add bitstring indentation and navigation for elixir-ts-mode * lisp/progmodes/elixir-ts-mode.el (elixir-ts--sexp-regexp): Add bistring. (elixir-ts--indent-rules): Handle bitstring indentation. (Bug#63109) * test/lisp/progmodes/elixir-ts-mode-resources/indent.erts: Add test case. --- lisp/progmodes/elixir-ts-mode.el | 4 +++- .../progmodes/elixir-ts-mode-resources/indent.erts | 12 ++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el index c58854c41c3..47f53043af3 100644 --- a/lisp/progmodes/elixir-ts-mode.el +++ b/lisp/progmodes/elixir-ts-mode.el @@ -89,7 +89,7 @@ (rx bol (or "call" "stab_clause" "binary_operator" "list" "tuple" "map" "pair" "sigil" "string" "atom" "alias" "arguments" "identifier" - "boolean" "quoted_content") + "boolean" "quoted_content" "bitstring") eol)) (defconst elixir-ts--test-definition-keywords @@ -231,6 +231,7 @@ ((node-is "^]$") ,'elixir-ts--parent-expression-start 0) ((node-is "^}$") ,'elixir-ts--parent-expression-start 0) ((node-is "^)$") ,'elixir-ts--parent-expression-start 0) + ((node-is "^>>$") ,'elixir-ts--parent-expression-start 0) ((node-is "^else_block$") grand-parent 0) ((node-is "^catch_block$") grand-parent 0) ((node-is "^rescue_block$") grand-parent 0) @@ -250,6 +251,7 @@ ,'elixir-ts--argument-indent-anchor ,'elixir-ts--argument-indent-offset) ((parent-is "^pair$") parent ,offset) + ((parent-is "^bitstring$") parent ,offset) ((parent-is "^map_content$") parent-bol 0) ((parent-is "^map$") ,'elixir-ts--parent-expression-start ,offset) ((node-is "^stab_clause$") parent-bol ,offset) diff --git a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts index 9ad604e5198..4eb6e768b96 100644 --- a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts @@ -79,6 +79,18 @@ def foo() do end =-=-= +Name: Bitstring mulitline + +=-= +<<12, 22, +22, 32 + >> +=-= +<<12, 22, + 22, 32 +>> +=-=-= + Name: Block assignments =-= From e03cfec0a455dd8c496d33c422c8edb9ac5a4005 Mon Sep 17 00:00:00 2001 From: Wilhelm H Kirschbaum Date: Thu, 27 Apr 2023 12:13:25 +0200 Subject: [PATCH 3/5] Improve call indentation for elixir-ts-mode * lisp/progmodes/elixir-ts-mode.el (elixir-ts--indent-rules): Change match order. (Bug#63110) * test/lisp/progmodes/elixir-ts-mode-resources/indent.erts: Add test case. --- lisp/progmodes/elixir-ts-mode.el | 2 +- .../progmodes/elixir-ts-mode-resources/indent.erts | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el index 47f53043af3..7175fe4bff8 100644 --- a/lisp/progmodes/elixir-ts-mode.el +++ b/lisp/progmodes/elixir-ts-mode.el @@ -257,7 +257,6 @@ ((node-is "^stab_clause$") parent-bol ,offset) ((query ,elixir-ts--capture-operator-parent) grand-parent 0) ((node-is "^when$") parent 0) - ((node-is "^keywords$") parent-bol ,offset) ((parent-is "^body$") (lambda (node parent _) (save-excursion @@ -272,6 +271,7 @@ ,'elixir-ts--argument-indent-anchor ,'elixir-ts--argument-indent-offset) ;; Handle incomplete maps when parent is ERROR. + ((node-is "^keywords$") parent-bol ,offset) ((n-p-gp "^binary_operator$" "ERROR" nil) parent-bol 0) ;; When there is an ERROR, just indent to prev-line. ((parent-is "ERROR") prev-line ,offset) diff --git a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts index 4eb6e768b96..1f855d3c977 100644 --- a/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/elixir-ts-mode-resources/indent.erts @@ -193,7 +193,19 @@ tuple = { } =-=-= -Name: Spec and method +Name: Call with keywords + +=-= +def foo() do + bar(:one, + :two, + one: 1, + two: 2 + ) +end +=-=-= + +Name: Call with @spec =-= @spec foobar( From c604cb6a8a5ac4ca1cfb5e839ca6d7ad1d77b5b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sat, 29 Apr 2023 20:46:12 +0100 Subject: [PATCH 4/5] Eglot: unbreak for Emacs 26 Emacs 26 doesn't have newer progress-reporter-update. I think I'll start using compat.el soon. * lisp/progmodes/eglot.el (eglot--apply-text-edits): Unbreak for Emacs 26 which doesn't have newer progress-reporter-update. --- lisp/progmodes/eglot.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 6ae27a13845..53bc25a1b7e 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2237,7 +2237,7 @@ COMMAND is a symbol naming the command." ((eq (car pr) 'eglot--mode-line-reporter) (setcdr (cddr pr) (list msg pcnt)) (force-mode-line-update t)) - (pr (progress-reporter-update pr pcnt msg))))) + (pr (eglot--reporter-update pr pcnt msg))))) (eglot--dbind ((WorkDoneProgress) kind title percentage message) value (pcase kind ("begin" @@ -3341,7 +3341,7 @@ Returns a list as described in docstring of `imenu--index-alist'." (save-restriction (narrow-to-region beg end) (replace-buffer-contents temp))) - (progress-reporter-update reporter (cl-incf done))))))) + (eglot--reporter-update reporter (cl-incf done))))))) (mapcar (eglot--lambda ((TextEdit) range newText) (cons newText (eglot--range-region range 'markers))) (reverse edits))) From 30892cbd330ace125454a056ca86d85e2a860bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sat, 29 Apr 2023 20:47:24 +0100 Subject: [PATCH 5/5] Eglot: bump to 1.15 * lisp/progmodes/eglot.el (Version): Bump to 1.15 * etc/EGLOT-NEWS: Update. --- etc/EGLOT-NEWS | 26 ++++++++++++++++++++++++++ lisp/progmodes/eglot.el | 2 +- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index 7369b3bf545..27796adef4b 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -17,6 +17,32 @@ This refers to https://github.com/joaotavora/eglot/issues/. That is, to look up issue github#1234, go to https://github.com/joaotavora/eglot/issues/1234. + +* Changes in Eglot 1.15 (29/4/2023) + +** Fix LSP "languageId" detection + +Many servers today support multiple languages, meaning they can handle +more than one file type in the same connection. This relies on the +client supplying a ':languageId' string. Previously, Eglot calculated +this string based on an imperfect heuristic and was often wrong. See +github#1206. + +** Fix problems with missing signature documentation (bug#62687) + +** Reworked 'eglot-imenu' + +Eglot's Imenu backend (used for M-x imenu among other extensions), has +been reworked. Most newer servers respond to +'textDocument/documentSymbol' with a vector of 'DocumentSymbol', not +'SymbolInformation'. It's not worth it trying to make the two formats +resemble each other. This also lays groundwork supporting a +forthcoming "breadcrumb" feature of bug#58431. + +** New command 'eglot-update' + +This allows users to easily update to the latest version of Eglot. + * Changes in Eglot 1.14 (3/4/2023) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 53bc25a1b7e..1e0bcd30485 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2018-2023 Free Software Foundation, Inc. -;; Version: 1.14 +;; Version: 1.15 ;; Author: João Távora ;; Maintainer: João Távora ;; URL: https://github.com/joaotavora/eglot