These Weeks in Remacs III


Time for another Remacs update: lots of contributions, a wide range of features, and even a logo!

Contributing

Since the last update, we’ve seen contributions from lots of new people. We’ve added @brotzeit and @shanavas786, bringing us to seven wonderful people who can approve your PRs.

Speaking of PRs, we’ve merged an amazing 64 pull requests since the last update!

If you’re looking for a good feature for your first contribution, @brotzeit has been regularly adding new suggestions under the ‘good first issue’ label.

Features

Many Emacs features have now been ported to Rust, with new Rust APIs for accessing elisp datastructures.

Here’s an overview of the features that have landed.

Arithmetic: arithmetic, floating point, random number generation (using a Rust RNG!), and comparisons.

Symbols: symbol properties, interning, obarrays unbinding, keywords and indirect symbols.

Checksums: MD5sum (using a Rust MD5 crate!).

Windows: liveness check, type check, overlays and minibuffer, minibuffer check positions and margins.

Processes: accessing, type check, data structures and names.

Buffers: for the current thread, accessing, file names, size and modification.

Point: bobp, bolp, eolp, markers, point-min, point-max forward-point and goto-char.

Hash tables: copying and accessing.

Characters: multibyte conversions, character tables, category tables

Fonts: type checks.

Miscellaneous: prefix arguments and identity.

We’re also periodically pulling GNU Emacs features into Remacs, so all the features available GNU Emacs trunk are included in Remacs.

Idiomatic Rust in Remacs

Remacs has gradually developed a set of conventions for elisp data types. For each type Foo, we define a LispObject::as_foo, LispObject::as_foo_or_error and a FooRef when you know your elisp datatype is actually a Foo.

For example, here’s how overlay-start was implemented in C:

DEFUN ("overlay-start", Foverlay_start, Soverlay_start, 1, 1, 0,
       doc: /* Return the position at which OVERLAY starts.  */)
  (Lisp_Object overlay)
{
  CHECK_OVERLAY (overlay);

  return (Fmarker_position (OVERLAY_START (overlay)));
}

The C codebase makes heavy use of macros for checking types (CHECK_OVERLAY) and for accessing struct attributes (OVERLAY_START).

Here’s the Rust equivalent:

/// Return the position at which OVERLAY starts.
#[lisp_fn]
fn overlay_start(overlay: LispObject) -> LispObject {
    let marker = overlay.as_overlay_or_error().start();
    marker_position(marker)
}

We use procedural macros to simplify defining an elisp primitive function, and type checking is much more explicit.

(This example is from PR #298.)

Other exciting Rusty features include variadic macros to replace call1, call2 in C with just call! in Rust, and the ability to mock extern C functions so we can write unit tests.

Hash Maps

We’re not always able to leverage the Rust libraries available. @DavidDeSimone showed some amazing Rust-fu exploring using Rust’s FnvHashMap inside Remacs.

Sadly, we weren’t able to use the Rust hash map implementation. The C layer assumes that it can mutate hash table keys in place, and unexec does not play nicely with mmap. See the PR for the full details.

Finally, we’re discussing a logo for Remacs. We’ve had some great submissions:

You can join the logo discussion at PR #360.

As always, if you fancy writing some Rust in support of the world’s lispiest text editor, you can join us on GitHub!

Recent Posts

Difftastic, the Fantastic Diff

The Siren Song of Little Languages

How High Are Your Tests?

Helpful: One Year On

The Emacs Guru Guide to Key Bindings