Benoit J - My mostly tech blog

Emacs as My IDE - Part2: The Setup

Published on 2024-08-08

Categories: tech
Tags: Emacs IDE IntelliJ Java

This is part 2 of my series related to configuring Emacs to have similar features than IntelliJ.

You can read part1 here.

Elisp configuration can be found here.

In part2, I’ll go over the setup to be able to experiment, and capture my findings.

LSP or not?

The objective is to try to use Emacs for real professional development including for languages like Java, go, or Python. My field of work requires me to quickly switch to other languages, now or known.

Emacs is great for some languages, especially LISP, or c and c++. For other type of languages, Emacs basic language modes can’t offer the same level of support as Language specific IDEs from JetBrains or Eclipse.

Only with LSP does Emacs can offer better language support.

So LSP it is.

Eglot or lsp-mode?

There are two mature LSP client implementation for Emacs: Eglot and lsp-mode.

lsp-mode is the oldest of the two, has a lot of features, for a lot of languages. It is extended by lsp-treemacs, lsp-java, dap-mode, and consult-lsp. It’s UI is quite IDE like, and diverge a bit from Emacs native practices.

Eglot, is the newer kid on the block, simpler. It is extended by eglot-java, dape-mode and consult-eglot. I know it less, so maybe there are features that I get with lsp-mode that are missing.

Before dape-mode, the choice between Eglot and lsp-mode was much simpler (lsp-mode), now Eglot is a plausible choice.

I would like to use Eglot for a more natural UI, but at the same time, if an important feature is missing, I will use lsp-mode.

At this point, I cant chose one over the other, so I will evaluate both.

One realistic project

To try and demonstrate features from the various I need a realistic project.

Here are some of the criteria to pick a project:

  1. complex enough code base with many modules
  2. contains automated tests
  3. enough dependencies to test navigation and definitions
  4. back-end application, this is what I see the most
  5. Language I often see with enough complexity (Java)
  6. Using frameworks I often see

In my work, I often see back-end Java projects based on spring boot.

Spring project has the spring-petclinic, a spring boot example project. It contains both a web front-end and an API back-end. This should have plenty of code, tests, and dependencies I can use in a realistic way.

Configuration Setup

I will build two new configuration, one based on Eglot, one based on lsp-mode. You can find the code here.

Shared configuration, like completion framework, will go in shared.el which is loaded by both configuration.

The share configuration will be minimal, yet, complete enough to enable my regular coding workflows.

Shared configuration that will be included:

  1. navigation and editing helpers
  2. completion at point
  3. minibuffer completion
  4. Database and REST client

What it will not contains:

  1. org-mode configuration
  2. email configuration
  3. irc and other social network
  4. any other modules unrelated to my workflow in IntelliJ

I will build the shared configuration when needed.

Loading bookmark list on startup

Loading a dynamic UI at startup is not that trivial. It works as expected for file, static or generated buffers, but not so much for dynamic UI.

Here what works:

1
2
3
4
5
6
7
(setq inhibit-splash-screen t)

(add-hook 'after-init-hook
          #'(lambda ()
              (require 'bookmark)
              (bookmark-bmenu-list)))
(setq initial-buffer-choice (lambda () (get-buffer "*Bookmark List*")))

As you can see above, you must launch the command that generate buffer for initial-buffer-choice to work.

The bookmark list itself is hard-coded in the shared configuration by setting the value of the bookmark-alist variable.

How to distinguish both configuration?

I decided to simply use the provided modus dark theme in the eglot configuration, and modus light theme in the lsp-mode.

Also, the bookmark list is altered to only show the relevant configuration.

Other minimal UI tweaks

I’m only planning to prompting, and audible bell.

1
2
3
(setq use-dialog-box nil)   ; use message prompt instead of popup dialogs
(defalias 'yes-or-no-p 'y-or-n-p)
(setq visible-bell t)       ; flashes instead of beeping

What’s next

I’m quite excited to continue this series.

Here is some planned content to expect in future posts:

  1. Editing and navigation
  2. Documentation, linting
  3. Refactoring and code actions
  4. Runners: building, tests, application, and Debugging
  5. Supporting tools
  6. Framework support

craftering

For comments, use email or Mastodon

Don't forget to subscribe to my RSS feed!