Eglot has landed on master: Emacs now has a built-in LSP client
lists.gnu.org
lists.gnu.org
- pushing branches to your own fork so that others can see your work while it's in draft form
- opening PRs against the main project, and writing a nice PR introduction describing the changes that you've made, their background, and motivation, drawbacks and hesitations, etc.
- participating in a feedback conversation with the maintainers and other developers with comments attached to specific lines in the code (at a specific revision), as well as attached at diff level
- having the project CI run against your branch to check that all tests pass, across a collection of different OSs and architectures. (You can also run their CI in your own fork to check it works there before even opening a PR).
- opening Issues, and discussing with other developers
- having the ability to write your text comments along with images, videos, and syntax-highlighted code fragments.
- and many other things
- Send the mailing list an email with a url for your repository. Request that they pull from it. We call this a “pull request”, rather than a “Pull Request”, but it’s the same thing.
- Send an email to the development mailing list, making sure to write a nice introduction describing the changes that you’ve made, their background, motivation, drawbacks, hesitations, and so on.
- participate in feedback conversations with the maintainers and other developers with comments situated next to quotations of specific lines of code from specific revisions or specific diff hunks.
- Just run “make check”. 99% of all of the code in Emacs is written in Emacs Lisp, which is platform–independent. If the tests pass on your own computer you can rest assured that they will pass on everyone else’s too.
- sending emails to ask questions and discuss them with other developers
- feel free to include any type of media in your emails, all but one participant in the mailing list can view them
- and many other things
This is the 'we have PRs at home' point of view.
It's not WRONG, but I think it does miss the point. 'Just do everything different from what tons of other folks are doing day in and day out' is not the best answer.
The project is well within it's rights to do so, but, there's a reason GitHub specifically is super popular, and it's mostly to provide structure and avoid the pain in the neck that the 'do it by email' and 'just use these different things' approach while collaborating.
Following the herd is definitely the wrong answer.
I recommend a client called Gnus, which can score messages based on their content, and then sort by that score. That way messages about things you are interested in (such as your own patches, features that you care about, etc) float to the top.
Gnus doesn't look very user friendly
I think the design goals of Gnus were not about allowing the user to get started quickly by having the same buttons as every other email client, but instead empowering the users to extend Gnus so that it does what they want. As a result, it may take longer to learn how to use Gnus but the ceiling is much, much higher.
However, for bulk sorting of email I should actually have mentioned Sieve. It’s a standardized configuration language you can use to tell your server how to sort your mail, so that it is already done before your email client even logs in. Most IMAP servers support it, and it is pretty easy for email provide access to it.
You can write simple rules like this:
if address :is "From" "bugzilla-daemon@mozilla.org"
{
fileinto :create "INBOX.Bugzilla";
}
elsif header :contains "list-id" "emacs-devel.gnu.org"
{
fileinto :create "INBOX.emacs-devel";
}
and so on until all of your mail is sorted how you want it. It’s not a full programming language, so it cannot do everything, but it’s quite capable and pretty well standardized so you can take your filter rules with you if you change email providers. I use it even for simple rules like this so that all I need to do is paste them in when I move to a new provider. One doesn’t need to do that very often, but it only takes seconds to do instead of minutes or hours to reenter every filtering rule in a new UI.My current email provider is Fastmail. I discovered after I signed up that most of their mail–filtering settings get turned into Sieve rules that are shown to you when you go to add your own rules. I really like this because you can see exactly how spam is handled, how your vacation responders are implemented, how email from blocked senders is discarded, etc, etc.
Gnus flow: signup for mail service that lets you use a bunch of other gnu tools and client side software you have to install on every machine you want to do any kind of collaborative work from, write some code to filter your email, etc., etc. and then figure out the individual mailing list nuances (patches go here, discussion here, etc. - they're all potentially unique and beautiful snowflakes!).
I'm not trying to yuck anyone's yum, but you being the only user you care about is specifically why GitHub has become what it has. They care about all the potential users :)
I've used Gnus. It's crazy powerful. But it is not simple to configure. Using notmuch + Python scripts for filtering is way easier, and even that is more than what 95% of developers are willing to do.
BTW, Sieve beats an ad–hoc Python script any day of the week :)
Not sure what feature parity would look like… Neovim has had a built-in LSP client for quite a while.
I do agree that the community around Neovim feels super inviting.
Fwiw I also think you’re missing the point about the increased barrier to entry. I suppose one could make arguments from first principles about which platform has the higher barrier to entry but actual people don’t start from first principles – they are much more likely to be familiar with GitHub (I have weaker priors for eglot contributors but I still expect potential new contributors to be more familiar with GitHub).
Also I wonder: if eglot is now part of Emacs, is there any incentive for the lsp-mode devs to keep working on lsp-mode?
I got quite weary of hacking on my Emacs so I switched to eglot and had zero trouble since.
Sorry for lack of context, I am not shilling for eglot at all, it's just that I have a huge "make it your own by hacking!" fatigue these days.
lsp-mode does 'more' (and there's also an auxiliary package, dap-mode, for debugging), but I guess is somewhat more brittle because of this. dap-mode I do use, by the way (for python mainly) - functionality-wise it's my favourite debugger available in Emacs.
eglot further has a single developer who already assigns copyright to the FSF (and developed other packages, like flymake, which are already part of emacs), so it has that going for it as well.
I spent some time to get lsp-mode working earlier this year. It took me more time to declutter the amount of stuff it put on screen than what it took to setup. In fact they have a page about this https://emacs-lsp.github.io/lsp-mode/tutorials/how-to-turn-o...
After turning off 2/3 of these, the experience has been stable and supports almost everything. I experienced clangd crashes, but lsp-mode was always able to recover. I'm not too fond of the reliance of treemacs (don't particularly like treemacs behavior in general).
I just tried briefly eglot. It worked right out of the box, and the default "output" on screen seems to match what I left enabled for lsp-mode, which seems sane to me. xref integration seems to highlight methods with cc-mode (lsp-mode doesn't).
Some lsp features are missing. For example I couldn't find an equivalent for "incoming call hierarchy". Not a show stopper.
I would need to spend some good time to see which one provides less overhead, for example.
Same.
lsp-mode is great if you want to use a distraction-filled UI that doesn't integrate with anything else in the Emacs world. My first thought on trying it was "you're showing me three epitexts by default and yet none of them are running through eldoc." A large number of people seem to want that, god help them.
lsp-signature-render-documentation nil ;ridiculously shows entire doc in mini
lsp-eldoc-render-all nil ; if t, shows all hover info in eldoc - too muchI just checked, and both are licensed as GPLv3. I guess it could be this copyright-assignment thing?
Either way because of this move, I decided to try eglot over lsp-mode.
First thing which happens is that eglot complains its can't find a language-server for the major-mode I'm working in now... And it does *not* offer to automatically install one.
Based on this alone, I would say for OOB experience lsp-mode still seems leaps and bounds better.
That was also my experience. Eglot wasn't able to use the installed vscode-json-languageserver for editing JSON instead insisted that typescript is is not installed.
lsp-mode worked worked without any configuration out of the box
> Also I wonder: if eglot is now part of Emacs, is there any incentive for the lsp-mode devs to keep working on lsp-mode?
I'm pretty sure that some people will stick to lsp-mode. There are a few builtin extensions which I replaced with more popular external packages (eg: projectile vs project.el). So, I think the lsp-mode devs should keep at it.
https://emacs-lsp.github.io/lsp-mode/page/installation/#vani...
Always curious of why you prefer one of the other. Any major thing you prefer projectile? (only ever used project.el here and was satisfied)
Similarly, I'm using ivy, first time I see vertico which looks similar.
Try `M-x ffap' whilst point is on an include directive's filename, or `M-x ff-find-other-file' to jump between C/H header files.
They will be stuck on older versions and experience those problems as current problems.
Version management in Emacs is hard but a) lots of the community runs Emacs versions much older than 1y old and at least few years of compatibility is (used to be?) a strong cultural norm, b) it's common to offer fallbacks to e.g. `locate-dominating-file` or similar primitive cases especially when using relatively new features, c) I don't think project.el is very good in general.
I switched from eglot back to lsp-mode a while ago, but I don’t quite remember why unfortunately. I think lsp-mode “did more” or something like that, and seemed to have changed for the better.
None of this is bad. These aren't critiques of lsp-mode. But they're definitely reasons why it would make sense to integrate Eglot, which prioritizes integrating with Emacs built-in libraries.
The actual critique of lsp-mode I would make is that I bounced from lsp-mode at least 3 times trying to get things working, and things would always be ok for like a couple days and then I'd lose 30 minutes to debugging and ultimately just turn it all off so I could get on with my day. I enabled Eglot once, with like 10 lines of use-package, and haven't touched it since.
I think that may be lsp-ui, not lsp-mode, but I might be mistaken.
I’ve never used anything but xref in lsp-mode, I rely on xref a lot. I wasn’t even aware that lsp-mode has, or had, something bespoke there.
I use flymake, not flycheck, I don’t think I had to configure that.
projectile is just my personal preference because I'm used to it, the manual says it integrates with either project.el or projectile.
I remember the weird popups you mention from my first lsp-mode trial. I don’t know where they’re gone, nowadays it’s just text in the buffer. (But I don’t know whether that’s ElDoc or not.)
gopls has staticcheck and govet warnings; they are quite useful as you're typing in your code. (Though sometimes a little aggressive. My favorite is highlighting an if statement as an "empty branch" before I've had time to type in any code. I'm working as fast as I can, Mr. Linter!)
eslint's flymake integration can do this without any language server commitments. LSP maybe offers some performance advantage - but IMO that says more about eslint than LSP or flymake.
Why do you think you need to involve an LSP for that?. ESLint, as most linters, can take their input from stdin. That is exactly how the eslint-flymake[0] works. Lint on buffer contents, not file on disk. No JSON RPC involved.
Landing into Emacs core was never a goal for lsp. So it wasnt a choice between eglot vs lsp. It was eglot, yay or nay.
I never tried Eglot simply because the name made me think it was less serious.
And major difference is eglot is slimmer compared to lsp-mode, integrates with and relies on built-ins more (xref etc) rather than inventing its own paradigm, is less cluttered by default and IME less buggier than lsp-mode cludge and now comes with emacs so doesn't need any other packages (other than language servers themselves, of course).
OTOH lsp-mode supports more than 1 active language server per buffer, generally support more features of the protocol than eglot and installs servers automatically (which may be a feature or bug depending on your system).
It comes down to utility and personal preference, but I've used lsp-mode before, found it quite buggy and cluttered, moved to eglot and have near zero LSP config now.
One of the things I love about lsp-mode is how it automatically installs any language server I need, when I need it.
I would rather install one package and be done, than use one built-in package, and have to manually hunt, download, and manually maintain language-servers for all the different languages I'm using in my programs, on all the machines I do programming on.
If eglot wants to become the defacto standard, it will need to solve this sooner rather than later.
But I suspect RMS will be opposed to having Emacs automatically download "non-free" (not GPLed) code?
Compared to that, I was done setting up Eglot + language server in 2 minutes flat, there was no config needed and it Just Worked!
What tooling would you install for that? What tooling does your system package-manager offer for that?
LSP-mode offering a “vertical” form of integration here (these major modes have been tested with these servers, and here’s how to install and invoke them) makes perfect sense to me as a user.
These two terms are not synonymous. Only proprietary software is "non-free". Software under free software licenses other than the GPL (whether copyleft or pushover/"permissive") is never considered "non-free".
He is very concerned about this, as you can see every time such a topic arises on the emacs-devel mailing-list.
Unsurprisingly RMS prefers GPL over pushover licenses, especially when it comes to Emacs and GCC, which he considers strategic tools in a fight against proprietary software. He has been opposed to depending on Clang when GCC is not suitable (again due to his fears that GCC would be used to build proprietary compilers), but this does not mean that he considers Clang to be non-free software.
for those editing html fes with css and javascript all in one file this is a showstopper
If LSP survives, I'm certain solving this in the editor rather than the server this will come to be seen as an anti-pattern.
// IJ knows that "executeQuery" only accepts SQL string literals
// and the string is both highlighted and checked that "count" and "thing" are legal
statement.executeQuery("SELECT count(1) FROM thing");
// the following line designates the inner language
// language=SQL
String someSql = "WITH thing AS (SELECT whatever) SELECT * FROM thing";
With a language server, I'm guessing it would have to take the 2nd route, since I don't think language servers get into the business of knowing the semantics of the libraries against which they are completingMy (limited, from trying to hack a language server for a custom C preprocessor I have and reading a few others) experience is that language servers are not very good at true arbitrary composition but even the most monolithic ones are at least somewhat "wrappable". So a normal Java LSP wrapped in something that recognizes `executeQuery` and knows how to run additional checks on its string argument is possible. However, that thing running the additional checks on the string could not itself easily be an arbitrary SQL language server unless it was expressly designed for doing so.
The bigger issue is that you usually want some kind of semantic knowledge to cross the boundary! For example in HTML If I look for the definition of a string '#foo' in JS I want to jump to the element with ID foo; if I want to find uses of a .foo CSS selector I want to find the HTML documents with class="foo" and the JSX components with className="foo", etc. Isolating the servers misses most of the potential. You need a language-server-protocol-server protocol that can pass typed identifiers between each other; and now you've got not just programming problems but ontological problems which are the worst kind to have.
For the ontological problem, I presume you're referring to how there are so many differing ideas of how to represent ASTs (apologies for mixing languages, these URLs were just handy):
* https://lisperator.net/uglifyjs/ast#nodes
* https://github.com/estree/estree#the-estree-spec
* ... likely others
which makes it hard for ls1 to ask ls2 about "the for-of iteration variable Node" because ls2 could be using UglifyJS or ESTree or their own(!) AST nomenclature?
And all of this is made worse by (e.g.) Java1.3 versus Java19 because languages are rarely static
It's odd, because vscode uses omnisharp over lsp and it is fast, powerful and reliable.
Direnv can automatically load an environment when you enter a directory, so it automatically "opens" virtualenvs/nix shells/etc. The Emacs direnv mode ensures that each buffer sees the direnv mode for its project directory.
I've found this to be a great compromise between automatic behavior on the one hand and transparency + control on the other—I get the right environment loaded automatically very consistently and, if something goes wrong, I can open a shell and poke around to see what's going on (is my nix shell messed up? is the right tool not loaded via direnv? etc). The only time I need to do anything manually is if I make a change to the environment and need to update Emacs about it, in which case I just run M-x direnv-update-environment.
Once I got this set up, I can just rely on executable-find to check for (and find) exactly the right tool on a per-project basis—no more worrying about global or seeing the wrong version of a tool. This also made it easy to do stuff like only run formatting if the corresponding tool is available: I add hooks to various programming language modes that only turn on lsp/formatting/etc if executable-find sees the corresponding executable.
Compared to the hassle I've had to go through helping my colleagues debug VSCode not seeing the right conda environment, virtualenv or the right version of various tools, Emacs + direnv has been a far nicer and more consistent experience.
[1]: https://direnv.net/
I use VS code for a couple days and I will already want to go back to Emacs, and having a good LSP experience is pretty important for either.
lsp-mode pretty much seems to do the right thing for Typescript projects without any configuration. At work we use React/TSX, for personal projects I use Svelte, and Emacs can find all the symbols, provide correct completions, and point out obvious mistakes. My only complaint is that I can never get Emacs's indentation to match what Prettier wants to do, so I'll type a bunch of code, prettier-on-save, and everything gets moved around. Not a big deal, but something I'd look into more deeply if I actually did Typescript full time. (I just occasionally change frontend stuff, but mostly program Go. gofmt and Emacs agree on formatting, but I think that's because Go is opinionated about formatting and so it's easier for multiple tools to have the same opinion. With Typescript, anything goes.)
TL;DR: despite the eglot marketing campaign and its overall cleaner design, lsp-mode might be the thing for you. I try eglot every 6 months and always switch back to lsp-mode. It has its quirks and WTFs, but doesn't get in my way too much.
I had this same issue, and it was annoying enough I continued to use https://github.com/editorconfig/editorconfig-emacs alongside prettier.
This does create another annoyance in having to configure editorconfig for new projects instead of relying on prettier alone.
This should enable us to create better, faster parsers for popular languages where the Emacs-support so far has not been that great.
So yeah I second that. Emacs 29 is going to be a great release!
https://www.masteringemacs.org/article/tree-sitter-complicat...
(And thank you for your wonderful book and website, they've both made my life in DevOps more enjoyable and effective)
That said, I've been running pgtk on GNOME Wayland on a hidpi screen and it's been great.
Technically you can run an Emacs server remotely, and connect to it with the UI client. But the setup is going to be much more involved.
Any pointers on how to get started with this?
I once tried to set up some hacked bash script instead of ssh which would set up environment variables and forward the Emacs daemon socket over ssh so that if I remotely attempted to edit a file, my local Emacs would open that remote file over tramp. But the whole thing was kinda nasty.
I do want a ‘thicker’ emacsclient though but mostly because of the end of X windows as I currently use Emacs remotely with X forwarding over ssh.
FTFY
Meanwhile I recommend just learning the vanilla defaults as best as possible. As long as you know how to open files, save things, switch between buffers, and quit, you're kind of good to go as far as immediate usability goes. Eventually you learn a few more key bindings to make navigation easier and faster, how to use macros, shell commands, etc. But you can learn these things on an as-needed basis.
But you can start using emacs with a handful of commands. Just typing puts characters into your buffer; c-f goes forward a character, c-b back a character, c-p goes the previous line, c-n goes to the next. c-x c-s saves the buffer into a file while c-x c-f finds a file by name and makes a buffer containing its contents. These commands have existed since I started using Emacs about 45 years ago!
Emacs is full of help. Press c-h for help -- it will prompt you for what you want help on. Every keystroke, every command, even "how did I get here" is in your help.
Over time you'll learn more commands, perhaps put something in your init file...and eventually it will be like a comfortable glove designed to fit your hands (which will stay on the keyboard, right?)
Since I tried Doom Emacs, I am really enjoying the experience, and it has seriously improved my workflow.
Now I can gradually learn things, improve my lisp, or try new work flows, etc.
Pre made distribution are a real improvement to the emacs ecosystem.
https://planet.emacslife.com is a great aggregator. https://reddit.com/r/emacs is handy too. https://www.youtube.com/c/SystemCrafters is an awesome channel. https://emacsrocks.com has some awesome demos. https://emacsrocks.com/e13.html is one of my all-time favorites (watch until the end, has a worthy finale).
Once you‘re comfortable with installing packages using Emacs‘ UI try watching the „Emacs from scratch“ series on YouTube and familiarize yourself with „use-package.el“ to build a clean, version controlled custom config.
If you do a lot of technical writing org-mode.el is pretty cool and also built-in. I am using it for live coding sessions.
I love emacs, but I really wish the out-of-the-box experience was better (eg. IIUC, even the default package repository is known obsolete, so why is it still the default?)
The on thing I would caution is Emacs creates backup files that can clutter. I find it is worth creating a dedicated back up folder. This does require configuration and there are tutorials on Youtube for this. I'd say about once or twice per year the backup files on every save have saved my bacon.
Finally, I prefer Emacs key binds to vi modes but that's just personal taste.
Whereas the mail in your link just shows that RMS wanted to discuss whether it should have a generic "LSP" name or not (i.e. retain the original eglot name), which is a valid concern.
My issue was your comment just pointed at RMS without specifying what he was being boneheaded about this time, which I thought was a little flamebaity.
This first is naming things
The second is getting emacs-lisp to hold hands with the rest of the world