Huge code bases can be intimidating and it always takes some time to get familiar with a project. Don't be afraid to ask questions and to say your opinion. We want to encourage you to share your thoughts with us, so if you have an idea for a new feature or how we can improve the existing ones, feel free to open an issue.
You should start by reading our docs. This also allows you to start contributing by improving our docs. Since documentation is very important to get new contibutors on board, this helps us to grow the community.
Most of the additional functionality of emacs-ng are in
rust_src/. This is the root of the main crate, however the actual
code is in
rust_src/crates/, except the crates that are
only used for the build.
Some crates will only built if you activate the related features when
./configure. You can find the features that are used by
Cargo.toml.in. Some of them on by default. Take a look
configure.ac to see how they are activated during the build
We only apply changes to the emacs code if it's necessary for features that are defined in rust. This way there are less merge conflicts when we perform upstream merges.
Bug fixes that also affect emacs can be tracked by an issue, but should but fixed upstream.
We use bindgen to generate rust bindings for the functions defined in C. Those bindings are in the crate emacs and are used by other crates through importing them from the emacs crate.
The crate ng-bindgen holds the code that is responsible for generating the bindings.
There's an ongoing effort to explain how emacs-ng is built on top of emacs in handbook/build.md.
Since we use github actions, the ci related files are located at
.github/workflow. The main job(test.yml) is for building emacs-ng
on Linux and osx (including formatting with rustfmt). There's also
docs.yml that is responsible for generating and deploying our docs.
The remaining files are used to test if the nix build works and to
create the release build that runs once a week.
If you want to know how you can run tests, look at handbook/tests.md. The file also contains some test examples.
The emacs crate also contains most of the code that allows us to make
use of elisp types. One of the most important types is
which is the equivalent to the C type
In order to define lisp functions in rust you have to take a look at
lisp_fn. Compared to the C version
DEFUN it provides a
lot more flexibility(handbook/lisp-fn.md).
The rust ecosystem provides tons of possibilities to improve emacs. We intend to use make use of libgit through git2-rs to improve magit. It would also be cool if we would have a terminal emulator based on rust.
If you have any idea for a new feature you want to work on, just add a configure option and create a new crate. Do not hesitate to ask for help.
Logs and debugging#
If you configure with
--enable-rust-debug cargo will build a debug
build. We use tracing to
collect log output, and a handler (subscriber) is installed in
main() if cargo is building a debug build. (The subscriber is not
present in release builds, and hence logging is optimised out. Be
aware that emitting records can slow down emacs considerably.)
The default handler is configured with the
variable, in the format
target=level. Crate names are targets, so
to log for the
webrender crate (which is named
wrterm) at the info
EMACSNG_LOG=wrterm=info. Multiple filters can be
separated with a comma, and filters are capable of advanced filtering
with regexes. See the documentation for
env_logger for more details.