unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* 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).