* bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook @ 2023-07-22 5:06 Tassilo Horn 2023-07-22 6:11 ` Eli Zaretskii 0 siblings, 1 reply; 6+ messages in thread From: Tassilo Horn @ 2023-07-22 5:06 UTC (permalink / raw) To: 64784 I'm in a rust-ts-mode buffer and ran eglot. When I hit RET (bound to newline), I get the following error: Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p return) eglot--post-self-insert-hook() self-insert-command(1) newline(nil 1) funcall-interactively(newline nil 1) call-interactively(newline nil nil) command-execute(newline) In GNU Emacs 30.0.50 (build 56, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version 1.17.8) of 2023-07-21 built on thinkpad-t440p Repository revision: c55e67081e9873a32b6e665e44f3e5a9c301255f Repository branch: master System Description: Arch Linux Configured using: 'configure --with-tree-sitter --with-pgtk --with-modules' Configured features: ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBSYSTEMD LIBXML2 MODULES NOTIFY INOTIFY PDUMPER PGTK PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP XIM GTK3 ZLIB Important settings: value of $LC_MONETARY: de_DE.utf8 value of $LC_NUMERIC: de_DE.utf8 value of $LC_TIME: de_DE.utf8 value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Rust Minor modes in effect: eglot-inlay-hints-mode: t eglot--managed-mode: t flymake-mode: t display-fill-column-indicator-mode: t display-line-numbers-mode: t hexl-follow-ascii: t cargo-minor-mode: t editorconfig-mode: t debbugs-browse-mode: t hl-todo-mode: t global-aggressive-indent-mode: t aggressive-indent-mode: t pdf-occur-global-minor-mode: t diredfl-global-mode: t mu4e-modeline-mode: t which-key-mode: t highlight-parentheses-mode: t yas-global-mode: t yas-minor-mode: t global-git-commit-mode: t magit-auto-revert-mode: t server-mode: t bug-reference-prog-mode: t corfu-history-mode: t global-corfu-mode: t corfu-mode: t vertico-mode: t marginalia-mode: t minibuffer-depth-indicate-mode: t switchy-window-minor-mode: t electric-pair-mode: t recentf-mode: t pixel-scroll-precision-mode: t pixel-scroll-mode: t override-global-mode: t repeat-mode: t save-place-mode: t savehist-mode: t puni-global-mode: t puni-mode: t tooltip-mode: t global-eldoc-mode: t eldoc-mode: t show-paren-mode: t electric-indent-mode: t mouse-wheel-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t column-number-mode: t line-number-mode: t transient-mark-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t Load-path shadows: ~/Repos/el/mu/mu4e/mu4e hides ~/Repos/el/mu/build/mu4e/mu4e ~/Repos/el/mu/mu4e/mu4e-modeline hides ~/Repos/el/mu/build/mu4e/mu4e-modeline ~/Repos/el/mu/mu4e/mu4e-context hides ~/Repos/el/mu/build/mu4e/mu4e-context ~/Repos/el/mu/mu4e/mu4e-main hides ~/Repos/el/mu/build/mu4e/mu4e-main ~/Repos/el/mu/mu4e/mu4e-vars hides ~/Repos/el/mu/build/mu4e/mu4e-vars ~/Repos/el/mu/mu4e/mu4e-window hides ~/Repos/el/mu/build/mu4e/mu4e-window ~/Repos/el/mu/mu4e/mu4e-speedbar hides ~/Repos/el/mu/build/mu4e/mu4e-speedbar ~/Repos/el/mu/mu4e/mu4e-view hides ~/Repos/el/mu/build/mu4e/mu4e-view ~/Repos/el/mu/mu4e/mu4e-thread hides ~/Repos/el/mu/build/mu4e/mu4e-thread ~/Repos/el/mu/mu4e/mu4e-bookmarks hides ~/Repos/el/mu/build/mu4e/mu4e-bookmarks ~/Repos/el/mu/mu4e/mu4e-org hides ~/Repos/el/mu/build/mu4e/mu4e-org ~/Repos/el/mu/mu4e/mu4e-lists hides ~/Repos/el/mu/build/mu4e/mu4e-lists ~/Repos/el/mu/mu4e/mu4e-actions hides ~/Repos/el/mu/build/mu4e/mu4e-actions ~/Repos/el/mu/mu4e/mu4e-helpers hides ~/Repos/el/mu/build/mu4e/mu4e-helpers ~/Repos/el/mu/mu4e/mu4e-search hides ~/Repos/el/mu/build/mu4e/mu4e-search ~/Repos/el/mu/mu4e/mu4e-server hides ~/Repos/el/mu/build/mu4e/mu4e-server ~/Repos/el/mu/mu4e/mu4e-obsolete hides ~/Repos/el/mu/build/mu4e/mu4e-obsolete ~/Repos/el/mu/mu4e/mu4e-update hides ~/Repos/el/mu/build/mu4e/mu4e-update ~/Repos/el/mu/mu4e/mu4e-draft hides ~/Repos/el/mu/build/mu4e/mu4e-draft ~/Repos/el/mu/mu4e/mu4e-message hides ~/Repos/el/mu/build/mu4e/mu4e-message ~/Repos/el/mu/mu4e/mu4e-compose hides ~/Repos/el/mu/build/mu4e/mu4e-compose ~/Repos/el/mu/mu4e/mu4e-headers hides ~/Repos/el/mu/build/mu4e/mu4e-headers ~/Repos/el/mu/mu4e/mu4e-query-items hides ~/Repos/el/mu/build/mu4e/mu4e-query-items ~/Repos/el/mu/mu4e/mu4e-notification hides ~/Repos/el/mu/build/mu4e/mu4e-notification ~/Repos/el/mu/mu4e/mu4e-contacts hides ~/Repos/el/mu/build/mu4e/mu4e-contacts ~/Repos/el/mu/mu4e/mu4e-icalendar hides ~/Repos/el/mu/build/mu4e/mu4e-icalendar ~/Repos/el/mu/mu4e/mu4e-mark hides ~/Repos/el/mu/build/mu4e/mu4e-mark ~/Repos/el/mu/mu4e/mu4e-contrib hides ~/Repos/el/mu/build/mu4e/mu4e-contrib ~/Repos/el/mu/mu4e/mu4e-folders hides ~/Repos/el/mu/build/mu4e/mu4e-folders ~/Repos/el/mu/mu4e/mu4e-mime-parts hides ~/Repos/el/mu/build/mu4e/mu4e-mime-parts /home/horn/.emacs.d/elpa/transient-20230602.2121/transient hides /home/horn/Repos/el/emacs/lisp/transient Features: (shadow face-remap so-long view emacsbug shortdoc comp comp-cstr help-fns radix-tree cl-print cus-start cape-keyword cape eglot external-completion jsonrpc flymake-proc flymake ert debug backtrace tramp-cmds rust-ts-mode c-ts-common puni pulse display-fill-column-indicator display-line-numbers ef-cherie-theme generic totp-widget totp hexl bindat yaml-mode fish-mode cargo xref project cargo-process web-mode disp-table preview-latex tex-site editorconfig editorconfig-core editorconfig-core-handle editorconfig-fnmatch elfeed-show elfeed-search vc-hg vc-bzr vc-src vc-sccs vc-svn vc-cvs vc-rcs log-view debbugs-browse elfeed-csv elfeed elfeed-curl elfeed-log elfeed-db elfeed-lib avl-tree generator url-queue xml-query hl-todo aggressive-indent rainbow-mode pdf-occur tablist tablist-filter semantic/wisent/comp semantic/wisent semantic/wisent/wisent semantic/util-modes semantic/util semantic semantic/tag semantic/lex semantic/fw mode-local cedet pdf-isearch pdf-misc pdf-tools pdf-view jka-compr pdf-cache pdf-info tq pdf-util pdf-macs image-mode exif vc-git vc-dir ewoc epa-file diredfl dired-x mu4e-icalendar gnus-icalendar icalendar diary-lib diary-loaddefs mu4e mu4e-org mu4e-notification notifications mu4e-main mu4e-view mu4e-mime-parts mu4e-headers mu4e-thread mu4e-compose mu4e-draft mu4e-actions org-capture org-refile org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro org-src ob-comint org-pcomplete org-list org-footnote org-faces org-entities ob-emacs-lisp ob-core ob-eval org-cycle org-table ol org-fold org-fold-core org-keys oc org-loaddefs find-func cal-menu calendar cal-loaddefs org-compat org-version org-macs smtpmail mu4e-search mu4e-lists mu4e-bookmarks mu4e-mark mu4e-message flow-fill mule-util hl-line mu4e-contacts mu4e-update mu4e-folders mu4e-context mu4e-query-items mu4e-server mu4e-modeline mu4e-vars mu4e-helpers mu4e-config mu4e-window magit-bookmark bookmark ido mu4e-obsolete hippie-exp auto-dictionary flyspell ispell tramp-smb which-key highlight-parentheses restclient yasnippet forge-list forge-commands forge-semi forge-bitbucket buck forge-gogs gogs forge-gitea gtea forge-gitlab glab forge-github ghub-graphql treepy gsexp ghub let-alist forge-notify forge-revnote forge-pullreq forge-issue forge-topic yaml forge-post markdown-mode thingatpt noutline outline forge-repo forge forge-core forge-db closql emacsql-sqlite-common emacsql emacsql-compiler eieio-base magit-submodule magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit magit-sequence magit-notes magit-worktree magit-tag magit-merge magit-branch magit-reset magit-files magit-refs magit-status magit magit-repos magit-apply magit-wip magit-log which-func imenu magit-diff smerge-mode diff diff-mode git-commit log-edit pcvs-util add-log magit-core magit-autorevert autorevert filenotify magit-margin magit-transient magit-process with-editor server magit-mode magit-git magit-base magit-section cursor-sensor crm dash visual-filename-abbrev rg vc vc-dispatcher rg-info-hack advice rg-menu transient rg-ibuffer rg-result wgrep-rg wgrep rg-history rg-header ibuf-ext ibuffer ibuffer-loaddefs grep compile debbugs soap-client url-http url-auth url-gw nsm warnings rng-xsd rng-dt rng-util xsd-regexp bug-reference kind-icon svg-lib color corfu-history corfu vertico marginalia icomplete mb-depth use-package-diminish switchy-window compat elec-pair recentf tree-widget pixel-scroll cua-base edmacro kmacro use-package-bind-key bind-key diminish repeat treesit saveplace tramp-sh savehist smiley gnus-art mm-uu mml2015 mm-view mml-smime smime gnutls dig gnus-sum shr pixel-fill kinsoku url-file svg dom gnus-group gnus-undo gnus-start gnus-dbus dbus xml gnus-cloud nnimap nnmail mail-source utf7 nnoo gnus-spec gnus-int gnus-range message sendmail yank-media puny dired dired-loaddefs rfc822 mml mml-sec epa derived epg rfc6068 epg-config mm-decode mm-bodies mm-encode mail-parse rfc2231 rfc2047 rfc2045 ietf-drums mailabbrev gmm-utils mailheader gnus-win gnus nnheader gnus-util text-property-search mm-util mail-prsvr mail-utils range ef-themes cl-extra help-mode use-package-ensure use-package-core finder-inf tramp rx tramp-loaddefs trampver tramp-integration files-x tramp-compat xdg shell pcomplete comint ansi-osc ring parse-time iso8601 time-date format-spec ansi-color cus-edit pp cus-load icons wid-edit aggressive-indent-autoloads auto-dictionary-autoloads cape-autoloads cargo-autoloads clojure-mode-autoloads corfu-autoloads csv-mode-autoloads debbugs-autoloads diminish-autoloads diredfl-autoloads editorconfig-autoloads ef-themes-autoloads elfeed-autoloads ement-autoloads expand-region-autoloads fish-mode-autoloads forge-autoloads closql-autoloads emacsql-autoloads ghub-autoloads highlight-parentheses-autoloads hl-todo-autoloads kind-icon-autoloads magit-autoloads pcase git-commit-autoloads marginalia-autoloads markdown-mode-autoloads mastodon-autoloads pdf-tools-autoloads persist-autoloads plz-autoloads puni-autoloads easy-mmode rainbow-mode-autoloads rcirc-color-autoloads request-autoloads restclient-autoloads rg-autoloads svg-lib-autoloads symbol-overlay-autoloads tablist-autoloads taxy-magit-section-autoloads taxy-autoloads magit-section-autoloads totp-autoloads transient-autoloads treepy-autoloads ts-autoloads s-autoloads dash-autoloads vertico-autoloads visual-filename-abbrev-autoloads web-mode-autoloads wgrep-autoloads which-key-autoloads with-editor-autoloads info compat-autoloads yaml-autoloads yaml-mode-autoloads yasnippet-autoloads package browse-url url url-proxy url-privacy url-expand url-methods url-history url-cookie generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/pgtk-win pgtk-win term/common-win pgtk-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic indonesian philippine cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget keymap hashtable-print-readable backquote threads dbusbind inotify dynamic-setting system-font-setting font-render-setting cairo gtk pgtk lcms2 multi-tty move-toolbar make-network-process emacs) Memory information: ((conses 16 817006 172619) (symbols 48 55210 5) (strings 32 241804 7684) (string-bytes 1 6997482) (vectors 16 99513) (vector-slots 8 1205973 165006) (floats 8 713 2345) (intervals 56 2394 475) (buffers 984 22)) ^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook 2023-07-22 5:06 bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook Tassilo Horn @ 2023-07-22 6:11 ` Eli Zaretskii 2023-07-22 9:33 ` João Távora 0 siblings, 1 reply; 6+ messages in thread From: Eli Zaretskii @ 2023-07-22 6:11 UTC (permalink / raw) To: Tassilo Horn, João Távora, Stefan Monnier; +Cc: 64784 > From: Tassilo Horn <thorn@fastmail.fm> > Date: Sat, 22 Jul 2023 07:06:58 +0200 > > > I'm in a rust-ts-mode buffer and ran eglot. When I hit RET (bound to > newline), I get the following error: > > Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p return) > eglot--post-self-insert-hook() > self-insert-command(1) > newline(nil 1) > funcall-interactively(newline nil 1) > call-interactively(newline nil nil) > command-execute(newline) This is because eglot--post-self-insert-hook assumes last-input-event is a character: (defun eglot--post-self-insert-hook () "Set `eglot--last-inserted-char', maybe call on-type-formatting." (setq eglot--last-inserted-char last-input-event) (let ((ot-provider (eglot--server-capable :documentOnTypeFormattingProvider)) ;; transform carriage return into line-feed (adjusted-ie (if (= last-input-event 13) 10 last-input-event))) ^^^^^^^^^^^^^^^^^^^^^^^ But in this case we get the symbol 'newline' as the value. The easy way out is to use characterp before comparing with =, but I actually think there's a deeper problem here, because the code which uses this post-self-insert-hook _wants_ to process inserted newlines. So I think a better fix here would be to use last-command-event, not last-input-event. All the other post-self-insert-hook implementations use that, AFAICT. Stefan, am I right? Can last-command-event, when accessed from post-self-insert-hook, ever be something other than a character? ^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook 2023-07-22 6:11 ` Eli Zaretskii @ 2023-07-22 9:33 ` João Távora 2023-07-22 14:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-07-23 7:21 ` Tassilo Horn 0 siblings, 2 replies; 6+ messages in thread From: João Távora @ 2023-07-22 9:33 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Tassilo Horn, Stefan Monnier, 64784 Eli Zaretskii <eliz@gnu.org> writes: >> From: Tassilo Horn <thorn@fastmail.fm> >> Date: Sat, 22 Jul 2023 07:06:58 +0200 >> >> >> I'm in a rust-ts-mode buffer and ran eglot. When I hit RET (bound to >> newline), I get the following error: >> >> Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p return) >> eglot--post-self-insert-hook() >> self-insert-command(1) >> newline(nil 1) >> funcall-interactively(newline nil 1) >> call-interactively(newline nil nil) >> command-execute(newline) > > This is because eglot--post-self-insert-hook assumes last-input-event > is a character: > > (defun eglot--post-self-insert-hook () > "Set `eglot--last-inserted-char', maybe call on-type-formatting." > (setq eglot--last-inserted-char last-input-event) > (let ((ot-provider (eglot--server-capable :documentOnTypeFormattingProvider)) > ;; transform carriage return into line-feed > (adjusted-ie (if (= last-input-event 13) 10 last-input-event))) > ^^^^^^^^^^^^^^^^^^^^^^^ > > But in this case we get the symbol 'newline' as the value. > > The easy way out is to use characterp before comparing with =, but I > actually think there's a deeper problem here, because the code which > uses this post-self-insert-hook _wants_ to process inserted newlines. > So I think a better fix here would be to use last-command-event, not > last-input-event. All the other post-self-insert-hook implementations > use that, AFAICT. > > Stefan, am I right? Can last-command-event, when accessed from > post-self-insert-hook, ever be something other than a character? Even before Stefan answers, 'last-command-event' sounds right to me. In latest master, I've replaced the previous hacky solution with a simplified one based on this 'last-command-event' and it doesn't need any translation and works correctly on both TTY and GUI Emacs. Tassilo, can you test? João ^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook 2023-07-22 9:33 ` João Távora @ 2023-07-22 14:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-07-23 7:21 ` Tassilo Horn 1 sibling, 0 replies; 6+ messages in thread From: Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-07-22 14:05 UTC (permalink / raw) To: João Távora; +Cc: Eli Zaretskii, Tassilo Horn, 64784 >> Stefan, am I right? Can last-command-event, when accessed from >> post-self-insert-hook, ever be something other than a character? In theory it's possible, but in practice, `last-command-event` is what `self-insert-command` uses as "the char to insert", so it's definitely more correct than `last-input-event`. Stefan ^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook 2023-07-22 9:33 ` João Távora 2023-07-22 14:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-07-23 7:21 ` Tassilo Horn 2023-07-23 10:20 ` bug#64784: LSP vs Emacs indentation [Was: bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook] João Távora 1 sibling, 1 reply; 6+ messages in thread From: Tassilo Horn @ 2023-07-23 7:21 UTC (permalink / raw) To: João Távora; +Cc: Eli Zaretskii, Stefan Monnier, 64784 João Távora <joaotavora@gmail.com> writes: Hi João, > Even before Stefan answers, 'last-command-event' sounds right to me. > In latest master, I've replaced the previous hacky solution with a > simplified one based on this 'last-command-event' and it doesn't need > any translation and works correctly on both TTY and GUI Emacs. > > Tassilo, can you test? I can say at least that the error is gone. Thank you! (The below isn't actually related to the bug but to the feature the code is providing.) And now I also looked what that code is actually doing: you do eglot-format after some trigger characters which seem to be queried from the LS. In my case of rust-analyzer, that seems to be (:firstTriggerCharacter "=" :moreTriggerCharacter ["." ">" "{"]) eglot-format works good in that buffer and seems to do exactly what rustfmt also does. Here I have a problem with rust-ts-mode which seems to have a sightly different idea about the indentation of some constructs, e.g., eglot-format and rustfmt say this is "correct" fn is_prev_next_window_variant(&self) -> bool { matches!( self, SwayrCommand::NextWindow { .. } | SwayrCommand::PrevWindow { .. } | SwayrCommand::NextTiledWindow { .. } | SwayrCommand::PrevTiledWindow { .. } | SwayrCommand::NextTabbedOrStackedWindow { .. } | SwayrCommand::PrevTabbedOrStackedWindow { .. } | SwayrCommand::NextFloatingWindow { .. } | SwayrCommand::PrevFloatingWindow { .. } | SwayrCommand::NextWindowOfSameLayout { .. } | SwayrCommand::PrevWindowOfSameLayout { .. } | SwayrCommand::NextMatchingWindow { .. } | SwayrCommand::PrevMatchingWindow { .. } ) } while rust-ts-mode prefers this: fn is_prev_next_window_variant(&self) -> bool { matches!( self, SwayrCommand::NextWindow { .. } | SwayrCommand::PrevWindow { .. } | SwayrCommand::NextTiledWindow { .. } | SwayrCommand::PrevTiledWindow { .. } | SwayrCommand::NextTabbedOrStackedWindow { .. } | SwayrCommand::PrevTabbedOrStackedWindow { .. } | SwayrCommand::NextFloatingWindow { .. } | SwayrCommand::PrevFloatingWindow { .. } | SwayrCommand::NextWindowOfSameLayout { .. } | SwayrCommand::PrevWindowOfSameLayout { .. } | SwayrCommand::NextMatchingWindow { .. } | SwayrCommand::PrevMatchingWindow { .. } ) } I actually like the rust-ts-mode variant better but don't find a (stable) knob in the rustfmt.config to make it agree. Anyway, I have no strong preference but frequently produce such needless whitespace changes during editing (which, of course, cargo fmt will "repair"). So is there a way to stop the indentation wars? Maybe if I could make it so that return and tab would also be considered as trigger characters for eglot-format? Bye, Tassilo ^ permalink raw reply [flat|nested] 6+ messages in thread
* bug#64784: LSP vs Emacs indentation [Was: bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook] 2023-07-23 7:21 ` Tassilo Horn @ 2023-07-23 10:20 ` João Távora 0 siblings, 0 replies; 6+ messages in thread From: João Távora @ 2023-07-23 10:20 UTC (permalink / raw) To: Tassilo Horn; +Cc: Eli Zaretskii, Stefan Monnier, emacs-devel Tassilo Horn <tsdh@gnu.org> writes: >> Tassilo, can you test? > I can say at least that the error is gone. Thank you! In that case, I'm closing, but we should keep chatting because this matter interests me as well. In fact, let's move this to Emacs-devel. > So is there a way to stop the indentation wars [between LSP and Emacs's]? There's quite a bit of overlap in indentation functionality, yes. For example, in non-ts c++-mode, there are a lot of indentation knobs, and they can probably do all this. But configuring them is difficult (for me), and I'm not sure I haven't seen at a bug or two. In practice, I've accepted I'll never get them to match my team's .clang-format completely. A way to "stop" the war is to get one of the sides to surrender. To make the LSP side lose, just add symbols to 'eglot-ignored-server-capabilities', like ':documentOnTypeFormattingProvider'. > Maybe if I could make it so that return and tab would also be > considered as trigger characters for eglot-format? If your aim is to make the LSP side "win", I don't think you should use the "trigger character" technique specifically. But in Emacs you can of course bind keys to commands that invoke 'eglot-format' synchronously. Even better, I think the most correct way is to buffer-locally set 'indent-line-function' and 'indent-region-function', so you can keep the familiar feeling of TAB. I've tested this: * Setting 'indent-region-function' simply to 'eglot-format' apparently works. (Not in cc-mode, which has a tendency for wheel-reinvention. Or who knows original invention... but in any case it's probably time for me to move on to c++-ts-mode) * As to 'indent-line-function', there's no Eglot command that's exactly compatible with the protocol, but it's pretty easy to make one: (defun eglot-indent-line () (eglot-format (line-beginning-position) (line-end-position))) After setting 'indent-line-function' and 'indent-region-function' like this, things seem to work well at first. But simple things like RET ('newline') fail. I haven't investigated. Maybe it's becasue of electric-indent-mode? Or maybe just because of the fact that `eglot-format` asks the language server to do more than just indenting, namely it also inserts newlines. Or maybe I'm just not passing in the correct range. And then there are the annoying messages in the echo area about edits successfully applied, but that's easily solved. I hope you (and/or others) can give this approach (or variations thereof) some testing. Maybe with other LSP servers and/or style files. The reason I find this interesting it that it would IMO not only solve the indentation wars, it solves fundamental problems of limited-context indenters such as c++-ts-mode. Consider the C/C++ textual preprocessor macros: probably no tree-sitter mode can know exactly what they mean and how to indent the surrounding code, but a sufficiently smart project-knowing LSP can. Are there drawbacks to this "LSP-wins" approach to indentation? Probably. Chief among them LSP is very slow when compared things in the same address space, like an Elisp function or a dynamically linked C library. My early impression is that this fact almost certainly matters for LSP-driven fontification, but not for indentation. In summary, if we can get a successful approach that feels right for Emacs users (mostly regarding TAB, newline and region-indenting), maybe we can enshrine LSP-powered indentation in Eglot-managed buffers just like we do for Xref, Flymake, Imenu, etc... João ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-07-23 10:20 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-07-22 5:06 bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook Tassilo Horn 2023-07-22 6:11 ` Eli Zaretskii 2023-07-22 9:33 ` João Távora 2023-07-22 14:05 ` Stefan Monnier via Bug reports for GNU Emacs, the Swiss army knife of text editors 2023-07-23 7:21 ` Tassilo Horn 2023-07-23 10:20 ` bug#64784: LSP vs Emacs indentation [Was: bug#64784: 30.0.50; Eglot: Lisp error: (wrong-type-argument number-or-marker-p return) in eglot--post-self-insert-hook] João Távora
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).