Niels Thykier: Language Server (LSP) support for debian/control
About a month ago, Otto Kek l inen asked for editor extensions for debian related
files on the debian-devel mailing list. In that thread, I concluded that what we
were missing was a "Language Server" (LSP) for our packaging files.
Last week, I started a prototype for such a LSP for the debian/control file as
a starting point based on the pygls
library. The initial prototype worked and I could do very basic diagnostics plus
completion suggestion for field names.
Current features
I got 4 basic features implemented, though I have only been able to test two of them in
emacs.
Despite its very limited feature set, I feel editing debian/control in emacs is now a much more pleasant experience. Coming back to the features that Otto requested, the above covers a grand total of zero. Sorry, Otto. It is not you, it is me.
- Diagnostics or linting of basic issues.
- Completion suggestions for all known field names that I could think of and values for some fields.
- Folding ranges (untested). This feature enables the editor to "fold" multiple lines. It is often used with multi-line comments and that is the feature currently supported.
- On save, trim trailing whitespace at the end of lines (untested). Might not be registered correctly on the server end.
Completion suggestions
For completion, all known fields are completed. Place the cursor at the start of the line
or in a partially written out field name and trigger the completion in your editor. In my
case, I can type R-R-R and trigger the completion and the editor will automatically
replace it with Rules-Requires-Root as the only applicable match. Your milage may
vary since I delegate most of the filtering to the editor, meaning the editor has the
final say about whether your input matches anything.
The only filtering done on the server side is that the server prunes out fields already used
in the paragraph, so you are not presented with the option to repeat an already used field,
which would be an error. Admittedly, not an error the language server detects at the moment,
but other tools will.
When completing field, if the field only has one non-default value such as Essential
which can be either no (the default, but you should not use it) or yes, then the
completion suggestion will complete the field along with its value.
This is mostly only applicable for "yes/no" fields such as Essential and Protected.
But it does also trigger for Package-Type at the moment.
As for completing values, here the language server can complete the value for simple fields
such as "yes/no" fields, Multi-Arch, Package-Type and Priority. I intend to add
support for Section as well - maybe also Architecture.
Diagnostics
On the diagnostic front, I have added multiple diagnostics:
Notable omission at this time:
- An error marker for syntax errors.
- An error marker for missing a mandatory field like Package or Architecture. This also includes Standards-Version, which is admittedly mandatory by policy rather than tooling falling part.
- An error marker for adding Multi-Arch: same to an Architecture: all package.
- Error marker for providing an unknown value to a field with a set of known values. As an example, writing foo in Multi-Arch would trigger this one.
- Warning marker for using deprecated fields such as DM-Upload-Allowed, or when setting a field to its default value for fields like Essential. The latter rule only applies to selected fields and notably Multi-Arch: no does not trigger a warning.
- Info level marker if a field like Priority duplicates the value of the Source paragraph.
- No errors are raised if a field does not have a value.
- No errors are raised if a field is duplicated inside a paragraph.
- No errors are used if a field is used in the wrong paragraph.
- No spellchecking of the Description field.
- No understanding that Foo and X[CBS]-Foo are related. As an example, XC-Package-Type is completely ignored despite being the old name for Package-Type.
- Quick fixes to solve these problems... :)
Trying it out
If you want to try, it is sadly a bit more involved due to things not being uploaded
or merged yet. Also, be advised that I will regularly rebase my git branches as I
revise the code.
The setup:
Obviously, the setup should get easier over time. The first three bullet points should eventually get resolved by merges and upload meaning you end up with an apt install command instead of them. For the editor part, I would obviously love it if we can add snippets for editors to make the automatically pick up the language server when the relevant file is installed.
- Build and install the deb of the main branch of pygls from https://salsa.debian.org/debian/pygls The package is in NEW and hopefully this step will soon just be a regular apt install.
- Build and install the deb of the rts-locatable branch of my python-debian fork from https://salsa.debian.org/nthykier/python-debian There is a draft MR of it as well on the main repo.
- Build and install the deb of the lsp-support branch of debputy from https://salsa.debian.org/debian/debputy
- Configure your editor to run debputy lsp debian/control as the language server for debian/control. This is depends on your editor. I figured out how to do it for emacs (see below). I also found a guide for neovim at https://neovim.io/doc/user/lsp. Note that debputy can be run from any directory here. The debian/control is a reference to the file format and not a concrete file in this case.
Using the debputy LSP in emacs
The guide I found so far relies on eglot. The guide below assumes you have the
elpa-dpkg-dev-el package installed for the debian-control-mode. Though it should
be a trivially matter to replace debian-control-mode with a different mode if you
use a different mode for your debian/control file.
In your emacs init file (such as ~/.emacs or ~/.emacs.d/init.el), you add the
follow blob.
Once you open the debian/control file in emacs, you can type M-x eglot to
activate the language server. Not sure why that manual step is needed and if someone
knows how to automate it such that eglot activates automatically on opening
debian/control, please let me know.
For testing completions, I often have to manually activate them (with C-M-i or
M-x complete-symbol). Though, it is a bit unclear to me whether this is an
emacs setting that I have not toggled or something I need to do on the language server
side.
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(debian-control-mode . ("debputy" "lsp" "debian/control"))))
From here
As next steps, I will probably look into fixing some of the "known missing" items under
diagnostics. The quick fix would be a considerable improvement to assisting users.
In the not so distant future, I will probably start to look at supporting other files
such as debian/changelog or look into supporting configuration, so I can cover
formatting features like wrap-and-sort.
I am also very much open to how we can provide integrations for this feature into
editors by default. I will probably create a separate binary package for specifically
this feature that pulls all relevant dependencies that would be able to provide editor
integrations as well.
For documentation, please have a look at:

One of the annoyances I had when I upgraded from Buster to Bullseye (yes, I m talking about an upgrade I did at the end of 2021) is that I ended up moving from Mailman 2 to Mailman 3. Which is fine, I guess, but it meant I could no longer use