reddit / emacs

Help tracking down problem with text below the cursor moving with cc-mode/lsp

bhrgunatha · 2022-10-17 06:28
I need help to track down an issue but I don't know how to proceed. A specific combination of things makes `lsp-mode` (with `lsp-ui` and `lsp-ui-doc-mode`) cause lines below the cursor to move. Those circumstances are: * Using one of the themes from [Prot's package `ef-themes`](https://protesilaos.com/emacs/ef-themes) * `cc-mode` with `lsp-mode`, `lsp-ui` and `lsp-ui-doc-mode` There is no problem with the identical configuration using haskell/lsp-haskell or python/lsp-pyright or any other language. Nor is there a problem using a different theme e.g. `modus-vivendi` [This video shows 3 short clips to demonstrate the problem.](https://vimeo.com/760939376) 1. theme: `ef-dark`, editing a C file showing the unwanted movement 1. identical setup after using `counsel-load-theme` and choosing `modus-vivendi`- no unwanted movement 1. theme: `ef-dark`, but editing a haskell file again using `lsp-mode` with `lsp-ui` and `lsp-ui-doc-mode` - no unwanted movement I'm stuck now and looking for ideas to help me discover what could cause this and how to fix it. --- [Link to my configuration of cc-mode and lsp-mode](https://pastebin.com/WFGhtJjd) --- **SOLVED:** The issue is caused by the setting of font heights. I was using `:font "<font family name> 15"` (family name and height in pixels) for both `fixed-pitch` and `variable-pitch` faces and somewhere emacs was setting `variable-pitch` to `:height 151`. To fix it I now set face attributes using :family and :height explicitly. Example: (set-face-attribute 'fixed-pitch nil :family "DejaVu Sans Mono" :height 150) (set-face-attribute 'variable-pitch nil :family "Georgia" :height 150) (set-face-attribute 'default nil :family "DejaVu Sans Mono" :height 150)
[deleted] · 2022-10-17 08:06
[removed]
organic-bookworm · 2022-10-18 07:20
> This video shows 3 short clips to demonstrate the problem. > 1. theme: ef-dark, editing a C file showing the unwanted movement Looks like some `lsp-ui-sideline-*` face has large font size. In `modus-themes` these faces have [`:height 0.99`](https://git.sr.ht/~protesilaos/modus-themes/tree/main/item/modus-themes.el#L6061-6064) set, probably, to mitigate this issue. NB: I didn't try your config -- only thoughts based on demo.
bhrgunatha · 2022-10-18 10:07
Thanks, I think you're on to something. I can understand why that would be different for a different theme. * [ef-theme-dark](https://i.imgur.com/Uf8o6yS.png) * [modus-vivendi](https://i.imgur.com/oT0kkvm.png) I can't understand why it's different for the **same theme** with different languages though. * [ef-theme-dark with c](https://i.imgur.com/Vl0oLrH.png) * [ef theme with haskell](https://i.imgur.com/uwqIBsL.png) * [ef theme with python](https://i.imgur.com/xk8gYFW.png) The face for the box around the symbol (`lsp-ui-sideline-symbol`) has some extra padding at the top and so is slightly taller and the text is not aligned to the right either when the issue occurs. Perhaps padding and misalignment are related. `describe-face` for `'lsp-ui-sideline-symbol` doesn't help here it shows the same result. [Running `counsel-faces`](https://i.imgur.com/eXX2nhK.png) renders `lsp-ui-sideline-symbol` correctly - without the extra padding - so maybe the issue is with `lsp-ui-sideline`. I'm stuck again.
organic-bookworm · 2022-10-18 20:47
Does this hack help? (advice-add #'lsp-ui-sideline--compute-height :override #'ignore) Also, see [issue tracker](https://github.com/emacs-lsp/lsp-ui/issues?q=is%3Aissue+is%3Aopen+lsp-ui-sideline) (if you haven't already). There seem to be plenty of open font-related issues, including ones rooted in older Emacs bugs and specific fonts.
bhrgunatha · 2022-10-19 06:21
Interesting. Ignoring `lsp-ui-sideline--compute-height`[makes it even worse](https://i.imgur.com/frMyhbD.png). I changed the `:height` property of the sideline faces - using the fabulous `ef-themes-with-colour` macro and basically copying the code in modus you linked - but that didn't have any effect whatsoever. Even with :height 0.5. I've tried a combination of many different fonts and sizes and none of those prevented the problem. I found also that the built-in adwaita theme has the same problem, and some other themes do and some don't e.g. randomly choosing from the doom-themes package. Finally I found a work-around: (defun ui-sideline/fix-height (args) (when (bound-and-true-p ef-themes-post-load-hook) (if (eql 1 (cadr args)) '(height 0.87)) args)) (advice-add #'lsp-ui-sideline--compute-height :filter-return #'ui-sideline/fix-height) I arrived at 0.87 through trial and error (binary search ftw!) I'll add an issue to the tracker to see if there are any better suggestions there. Thanks for your advice and prompts, they were really useful.
organic-bookworm · 2022-10-19 06:54
Could you please also try these [two](https://github.com/emacs-lsp/lsp-ui/issues/561#issuecomment-1080363562) [hacks](https://github.com/emacs-lsp/lsp-ui/issues/561#issuecomment-1221417500), too? >I'll add an issue to the tracker to see if there are any better suggestions there. Thanks. I couldn't reproduce it with my setup. Just for the reference, I use [Doom `ba35f12be`](https://github.com/doomemacs/doomemacs/commit/ba35f12be43d4a93ea56cc5617a4a2543522e82e) with Emacs 29.0.50 `76b7a5936` on Debian 10. Specifically, [`lsp-mode` `68bdac0f8`](https://github.com/emacs-lsp/lsp-mode/commit/68bdac0f806789c064856a47d0e413b65a260e1e), [`lsp-ui` `d8cce7dc1`](https://github.com/emacs-lsp/lsp-ui/commit/d8cce7dc154aa3216c080dd5c6fb827bdba9a312). I use monospace [Iosevka](https://github.com/be5invis/Iosevka) TTF font for both italics and regular faces.
bhrgunatha · 2022-10-19 15:38
I updated lsp-mode today: lsp-mode: 20221018.1925 (from melpa) lsp-ui: 20220924.850 (from melpa) Redefining `lsp-ui-sideline--compute-height` and `lsp-ui-sideline--align` results in the [tallest height I've encountered yet](https://i.imgur.com/VVzEvh3.png) I'm not sure exactly where to apply `set-frame-font` so I added it to the end of my regular font setup: (defconst *FIXED-FONT* "FiraCode Nerd Font 15") (defconst *VARIABLE-FONT* "Bookerly Light 15") (defun b/set-ui-faces () (interactive) (set-face-attribute 'fixed-pitch nil :font *FIXED-FONT*) (set-face-attribute 'variable-pitch nil :font *VARIABLE-FONT*) (set-face-attribute 'default nil :font *FIXED-FONT*) (set-fontset-font t 'emoji (font-spec :name "JoyPixels") nil) (set-fontset-font t 'han (font-spec :name "MOESongUN") nil) ;; try to fix lsp-ui-sideline jumps (set-frame-font *FIXED-FONT* t t)) I didn't notice any difference after setting that. So far the only thing that's worked in intercepting the return value from `lsp-ui-sideline--compute-height`. I've run out of spare time today, so I'll post an issue to the github repo tomorrow. I really appreciate all your help, thanks.
bhrgunatha · 2022-10-20 08:27
**Got it**! Finally. I use both fixed pitch and variable pitch fonts. I set the attributes for faces `'fixed-pitch` and `'variable-pitch` using a shorthand of the :font property by adding the pixel height to the font-family names - "FiraCode Nerd Font 15" and "Bookerly Light 15". I discovered (`describe-face`) that the 'variable-pitch height is actually set at 151! My fix is to use just the font family name and set face heights explicitly. (defconst *FIXED-FONT* "FiraCode Nerd Font") (defconst *VARIABLE-FONT* "Bookerly Light") (defun b/set-ui-faces () (interactive) (set-face-attribute 'fixed-pitch nil :family *FIXED-FONT* :height 150) (set-face-attribute 'variable-pitch nil :family *VARIABLE-FONT* :height 150) (set-face-attribute 'default nil :family *FIXED-FONT* :height 150)) This fixes all my issues and I'm wondering if this could be the cause of some of the other `lsp-ui-sideline` font issues too? What do you think?
organic-bookworm · 2022-10-20 18:32
Neither `lsp-sideline-*` nor `font-lock-*` faces depend on `fixed-pitched` and `variablie-pitch` faces (unless face-remapped, which isn't the case by default). So changing font size there shouldn't affect sideline. However, I tried to mess my layout up with fonts you've specified. I've noticed in the first clip of [your demo](https://vimeo.com/760939376) the `param` and `function` tokens in the sideline seem to have the "Bookerly" font. The other clips seem to only use the "Fira Code" font. I think the answer to the magic combo conundrum is there. I only have signatures displayed and don't know where these `### param S1 === Type:` hints come from. So, I can't provide specific face to check, as well as tell why it uses `variable-pitch` font. You could e.g. check overlays (you want `after-string` property) [this way](https://emacs.stackexchange.com/a/35449) or debug `lsp-ui-sideline--make-display-string` function to find it out.
bhrgunatha · 2022-10-20 20:01
> So changing font size there shouldn't affect sideline. I only specify fonts for 3 faces - `default`, `variable-pitch` and `fixed-pitch` and nowhere else. They are the only ones used and they are used to display all the faces *somehow*. How emacs decides which fonts to use for which faces and how they end up in `lsp-ui-sideline` (which don't seem to reference any other faces) is unknown to me. ef-themes **does** use `variable-pitch` for faces `header-line`, `mode-line`, `tab-bar` and `tab-line` plus its own heading faces (which it uses for `org-mode` and `markdown-mode`). I can only guess `header-line` must be the source of `variable-pitch` within `lsp-ui` but I only see it in `lsp-ui-doc`, not `lsp-ui-sideline`. My lsp-ui settings are: (setq lsp-ui-doc-header t lsp-ui-doc-include-signature t lsp-ui-doc-show-with-cursor nil lsp-ui-doc-show-with-mouse nil lsp-ui-sideline-show-code-actions t lsp-ui-sideline-show-hover t lsp-ui-sideline-delay 0.05 lsp-ui-peek-always-show t lsp-ui-peek-fontify 'always) My gut feeling is the jumping was caused by the discrepancy between variable-pitch height ending up as 151 (instead of 150) to match the fixed-pitch and setting it explicitly to 150 avoids that. I have no knowledge to back that up though. > However, I tried to mess my layout up with fonts you've specified. I expect you set their height the same rather than 1 point different though :)
organic-bookworm · 2022-10-21 15:52
>My gut feeling is the jumping was caused by the discrepancy between variable-pitch height Yup. It's just that I can't get my sideline to use `variable-pitch`\-based faces. >`ef-themes` does use `variable-pitch` for faces I tried with `ef-themes-variable-pitch-ui` and `ef-themes-mixed-fonts` set to `t`. >I expect you set their height the same rather than 1 point different though :) I used `customize-face` command to edit faces interactively. Anyway, I think it's a good reference case. Cheers for solving the issue.
bhrgunatha · 2022-10-24 14:00
Sorry to [bang on about this](https://idioms.thefreedictionary.com/bang+on+about+(something\)). Thanks for your patience. I believe I have a definitive answer. I had some spare time to take your suggestion and debug `lsp-ui-sideline--make-display-string` The big thing that jumped out is the `info` argument includes markdown headings in its content. #("### function SwapSeqEntries " 0 3 (display "" face (lsp-ui-sideline-symbol-info markdown-header-delimiter-face default) markdown-heading-3-atx #1=(1 32 nil nil nil nil nil nil 1 5 5 30 30 32 #<killed buffer>) markdown-heading #2=(1 32 nil nil nil nil nil nil 1 5 5 30 30 32 #<killed buffer>)) 4 12 (face (lsp-ui-sideline-symbol-info markdown-header-face-3 default) markdown-heading-3-atx #1# markdown-heading #2#) 13 27 (face (lsp-ui-sideline-symbol-info markdown-inline-code-face markdown-header-face-3 default) markdown-heading-3-atx #1# markdown-heading #2#)) Although I mentioned `ef-themes` uses `variable-pitch` for org-mode and markdown headings, you need to configure it to do so. I guess you don't have that. In my config: (setq ef-themes-headings '((0 . (variable-pitch thin 1.3)) (1 . (variable-pitch 1.2)) (2 . (variable-pitch 1.1)) ;; setting more than 2 levels interferes with lsp-ui-sideline WTF??? (3 . (variable-pitch normal 1.2)) (4 . (variable-pitch 1.15)) (5 . (variable-pitch normal 1.17)) (6 . (variable-pitch normal 1.15)) (7 . (variable-pitch normal 1.1)) (t . (variable-pitch normal 1.05))) ef-themes-mixed-fonts t ef-themes-variable-pitch-ui t) Those are applied to the org and markdown heading level faces. One thing I didn't mention was that if I comment out levels 3 and higher [things were basically fine](https://i.imgur.com/gka5s1P.png), but when I uncomment them (as shown above) [some lines become mis-aligned](https://i.imgur.com/tv8Eleg.png). The jumping text has gone but not the weird alignment issue. Now if I remove `variable-pitch` from ef-themes-headings: (setq ef-themes-headings '((0 . (thin 1.3)) (1 . (1.2)) (2 . (1.1)) (3 . (normal 1.2)) (4 . (1.15)) (5 . (normal 1.17)) (6 . (normal 1.15)) (7 . (normal 1.1)) (t . (normal 1.05))) ef-themes-mixed-fonts t ef-themes-variable-pitch-ui t) [There's is no variable-pitch face and no mis-alignment](https://i.imgur.com/hRGYK8a.png). Now I feel happier that I understand what's happening and why.
organic-bookworm · 2022-10-25 20:06
Cool, you've pinpointed it. So `markdown-header-face-3` inherits from `ef-themes-heading-3` with 1.2 `:height` scale. I see, you get jumping due to variable height (> line height) and misalignment due to variable pitch. Probably the simplest fix would be to adjust the `lsp-ui-sideline-global` face to have font *specified*. (custom-set-faces '(lsp-ui-sideline-global ((t :inherit fixed-pitch)))) This way only sideline is affected. I think you may also ping Prot. There's "Notes on individual packages" section in the `modus-themes` manual for these kinds of quirks, and `modus-themes` are affected as well (`modus-themes-headings` user option).
organic-bookworm · 2022-10-25 20:06
BTW, I've also dug `lsp` code a bit. The sideline contents come from language server `textDocument/hover` response. The text is being font-locked according to language *defaulting to markdown* (`lsp--render-element`). Probably your server returns `### ...`, which is being treated as level 3 markdown headline (if you want to, you can see server JSON payload with `lsp-log-io` set to `t` in `*lsp-log:...*` buffers). For me `lsp-ui-sideline--make-display-string` returns this string with `ccls` server #(" int detail::test(int a) test " 0 1 (display (space :align-to (- right-fringe 32))) 1 3 (face (lsp-ui-sideline-global lsp-ui-sideline-symbol-info font-lock-type-face default) display (height 1)) 3 4 (face (lsp-ui-sideline-global lsp-ui-sideline-symbol-info font-lock-type-face default) c-type c-decl-id-start display (height 1)) 4 5 (face lsp-ui-sideline-global display (height 1)) ...)
bhrgunatha · 2022-10-27 14:28
Yes I'm using clangd and it's obviously returning markdown markup documentation. I had configured lsp-ui-doc **not** to show pop-up documentation (only sideline), but [changing that makes it very clear.](https://i.imgur.com/yyt19SA.png). I suppose the question is, what should `sideline` do with markdown markup? Here clangd is using headers, but who knows what other servers might send? Links to documentation for example. That explains why the other languages I tried behaved better - obviously no markdown headers. Interesting though that `sideline` is somehow rendering e.g. bold markdown text `*function-name*` and rendering that bold.