Thanks for contributing to Lem! Here are some guidelines that we follow in the codebase.
In general, we follow the Google guide: https://google.github.io/styleguide/lispguide.xml
Lem depends on alexandria
, so you can use if-let
, when-let
and similar functions.
You can :import-from
these symbols in your package definition, use the alexandria:
package prefix, and define a package-local nickname.
Try to not use new utility functions that you don't see in the codebase yet.
For instance, we won't use alexandria-2:line-up-first
.
Try to not use alexandria:curry
and prefer higher-order functions.
Avoid dynamic symbol calls (uiop:symbol-call
) but rething your architecture instead.
Use defvar
and defparameter
for user-facing variables, but avoid
using them as global variables that store state and that are used from
functions to functions. Have a more functional style, give explicit
arguments to functions.
Example:
;; avoid this
(defvar *var* 1)
(defun foo ()
*var*)
(let ((*var* 2))
(foo))
instead, have foo
take one argument.
Please take attention to compiler warnings.
If you change or delete a feature, if only a variable name, you must take care of deprecation warnings. A user should be notified that something changed. If possible, her old config file should not fail loading, or it should not fail without notice. Measures can vary. Ideas:
- don't delete or rename a
defvar
, adefparameter
or a function, but leave it and if it is used, signal a warning or an error. Add a;; DEPRECATED
comment with the date of the comment. - document the breaking change on the "next release changelog" issue (like lem-project#1027 or equivalent).
Write thorough docstrings to interactive commands (define-command
),
give meaningful documentation to important functions, give a
high-level overview in packages and comments (the "why", not the
"how"). Use the :documentation
option of packages, generic functions
and CLOS slots.
Please also contribute to Lem's website if you add or change a feature.
https://github.com/lem-project/lem-project.github.io/
or at least, open an issue about it so we don't forget to do it, thank you.
error
is for internal errors, and editor-error
is displayed nicely to the user.
Variables and parameters (defvar
, defparameter
) should be grouped
and appear near the top of the file, before conditions, classes and
functions.
Lem modes should define all their keybindings at the top of the file.
Please rebase and squash small commits together (you can do this with lem/legit ! ;) ).
When your changes are about a mode or a feature, we like the commit message to say it upfront, for example:
legit: add k to discard changes of unstaged files
Loop keywords are written as keywords, with the :
:
(loop :for key :in … )
Don't write long macros, use the "call-with-" pattern.
Don't define lists with backquote and comma, use the list
constructor.
Parameters that can be changed by the user should not have a "-p" suffix. Keep them for the functions' key arguments.
They can be saved and set-able with the lem:config
system.