Homepage: https://elpa.gnu.org/packages/sm-c-mode.html
Author: Stefan Monnier
Updated:
C major mode based on SMIE
This started as an experiment to see concretely where&how SMIE falls down
when trying to handle a language like C, to get an idea of maybe what it
would take to change SMIE to better support C-style syntax.
So, this does provide "SMIE-based indentation for C" and might even do it OK
in practice, but it really doesn't benefit much from SMIE:
- it does a lot of its own parsing by hand.
- its smie-rules-function also does a lot of indentation by hand.
Hopefully at some point, someone will find a way to extend SMIE such that
we can handle C without having to constantly work around SMIE, e.g.
it'd be nice to hook sm-c--while-to-do, sm-c--else-to-if, sm-c--boi,
sm-c--boe, ... into SMIE at some level.
This is not designed to supplant Emacs's built-in c-mode, which does a more
thorough job. It was not even meant to be used by anyone, really, but
I finally decided to release this because some users pointed out that on
slow machines it can be a worthy lightweigth alternative.
Known limitations:
- This mode makes no attempt to try and handle sanely K&R style function
definitions (i.e. where the type of arguments is given between the list of
arguments and the body). There are 2 good reasons for that: this old
syntax sucks and should be laid to rest, and it'd be a lot of extra work
to try and handle it.
Todo:
- This mode mostly limits itself to the C99 syntax, so it would be nice
to make it handle the syntactic constructs introduced since then.
- We "use but don't use" SMIE.
- CPP directives are treated as comments. To some extent this is OK, but in
many other cases it isn't. See for instance the comment-only-p advice.
- M-q in a comment doesn't do the right thing.
Benchmarks
This code can't be compared to CC-mode since its scope is much more limited
(only tries to handle the kind of code found in Emacs's source code, for
example; does not intend to be extensible to handle C++ or ObjC; does not
offer the same kind of customizability of indentation style, ...).
But in order to make sure it's doing a good enough job on the code for which
it was tuned, I did run some quick benchmarks against CC-mode:
Benchmarks: reindent emacs/src/*.[ch] (skipping macuvs.h and globals.h
because CC-mode gets pathologically slow on them).
(cd .../emacs/; git reset --hard; mv src/macuvs.h src/globals.h ./);
files=($(echo .../emacs/src/*.[ch]));
(cd .../emacs/; mv macuvs.h globals.h src/);
time make -j4 ${^${files}}.reindent EMACS="emacs24 -Q";
(cd .../emacs/; git diff|wc)
- Default settings:
diff|wc => 86800 379362 2879534
make -j4 191.57s user 1.77s system 334% cpu 57.78 total
- With (setq sm-c-indent-cpp-basic 0)
diff|wc => 59909 275415 2034045
make -j4 177.88s user 1.70s system 340% cpu 52.80 total
- For reference, CC-mode gets:
diff|wc => 79164 490894 3428542
make -j4 804.83s user 2.79s system 277% cpu 4:51.08 total
IOW, in this "best case" scenario, `sm-c-mode' indented almost as well
as `c-mode' does (as measured by diff|wc), and it did it about
4 times faster.
BEWARE: take this with a large grain of salt, since this is testing
`sm-c-mode' in the most favorable light (IOW it's a very strongly biased
benchmark).
All this says, is that sm-c-mode's indentation might actually be usable if
you use it on C code that is sufficiently similar to Emacs's.