mle is a small, flexible console text editor written in C.
View more demos here.
View large-file startup benchmark here.
- Keep codebase small
- Require minimal dependencies
- Make extensibile and configurable
- Favor simplicity over portability
- Use shell commands to enhance functionality (e.g., grep, tree)
- Enjoy writing C
- Annoy world with another text editor
- Small codebase (~10k sloc)
- Only 1 out-of-repo dependency (pcre)
- Full UTF-8 support
- Syntax highlighting
- Stackable key maps (modes)
- Extensible via stdio
- Scriptable rc file
- Built-in text editing language (lel)
- Key macros
- Multiple splittable windows
- Regex search and replace
- Large file support
- Incremental search
- Linear undo and redo
- Multiple cursors
- Smart indent
- Headless mode
- Navigation via ctags
- Movement via less
- Fuzzy file search via fzf
- File browsing via tree
- File grep via grep
$ git clone --recursive https://github.com/adsr/mle.git
$ cd mle
$ sudo apt-get install libpcre3-dev # or `yum install pcre-devel`, `pacman -S pcre`, etc
$ make
You can run make mle_static instead to build a static binary.
To install to /usr/bin:
$ make install
To install to a custom directory, supply DESTDIR, e.g.:
$ DESTDIR=/usr/local/bin make install
(The following assumes default configuration.)
Run mle to start editing a new text file. Type to type, use directional keys
to navigate, Ctrl+F to search, Ctrl+T for search-and-replace, Ctrl+S to
save, and Ctrl+X to exit. Press F2 for full help.
Run mle existing-file to edit an existing file. To edit multiple files try
mle file1 file2 and use Alt+n and Alt+p to switch between them. Press
Alt+c to close a file. You can also specify mle file.c:100 to start the
editor at a certain line number.
mle is customized via command line options. Run mle -h to view all cli
options.
To set default options, make an rc file named ~/.mlerc (or /etc/mlerc). The
contents of the rc file are any number of cli options separated by newlines.
Lines that begin with a semi-colon are interpretted as comments.
If ~/.mlerc is executable, mle executes it and interprets the resulting stdout
as described above. For example, consider the following snippet from an
executable ~/.mlerc PHP script:
<?php if (file_exists('.git')): ?>
-kcmd_grep,M-q,git grep --color=never -P -i -I -n %s 2>/dev/null
<?php endif; ?>
This overrides the normal grep command with git grep if .git exists in the
current working directory.
mle is extensible via any program capable of standard I/O. A simple line-based request/response protocol enables user scripts to register commands and invoke internal editor functions in order to perform complex editing tasks. All messages are URL-encoded and end with a newline.
Example exchange between a user script (usx) and mle:
usx -> mle method=editor_register_cmd¶ms%5B%5D=hello&id=57cc98bb168ae
mle -> usx result%5Brc%5D=0&id=57cc98bb168ae
...
mle -> usx method=hello¶ms%5Bmark%5D=76d6e0¶ms%5Bstatic_param%5D=&id=0x76d3a0-0
usx -> mle method=mark_insert_before¶ms%5B%5D=76d6e0¶ms%5B%5D=hello%3F¶ms%5B%5D=5&id=57cc98bb6ab3d
mle -> usx result%5Brc%5D=0&id=57cc98bb6ab3d
usx -> mle result%5Brc%5D=0&error=&id=0x76d3a0-0
In the example above, the user script registers a command called hello at
startup, and mle replies with success. Later, the end-user invokes the hello
command, so mle sends a request to the user script. The user script receives the
request and sends a sub-request invoking mark_insert_before, to which mle
replies with success. Finally the user script returns overall success for the
hello command.
Currently, mle only accepts requests from user scripts while a request to the
user script itself is pending. (In other words, mle enforces an "only do stuff
if I ask you to" policy.) The exception to this is editor_register_cmd which
can be invoked by user scripts at startup time.
For end-users, user scripts are loaded via the -x cli option. Commands
registered by user scripts can be mapped to keys as normal via -k.
mle comes with a built-in text editing language called lel, inspired by the
sam command language. lel
commands can be entered manually at a prompt, or bound to any key via
-kcmd_lel,<key>,<lelcmd>.
See README.lel.md for lel command reference.
mle provides support for non-interactive editing which may be useful for using the editor as a regular command line tool. In headless mode, mle reads stdin into a buffer, applies a startup macro if specified, and then writes the buffer contents to stdout. For example:
$ echo -n hello | mle -M 'test C-e space w o r l d enter' -p test
hello world
If stdin is a pipe, mle goes into headless mode automatically. Headless mode can
be explicitly enabled or disabled with the -H option.
The following programs will enable or enhance certain features of mle if they
exist in PATH.
- bash (tab completion)
- fzf (fuzzy file search)
- grep (file grep)
- less (less integration)
- readtags (ctags integration)
- tree (file browsing)
- Multi-line style rules don't work properly when overlapped/staggered.
- There's a segfault lurking in the window split code. I can't reliably reproduce it.
Also check out eon, a fork of mle with some cool features.
mle makes extensive use of the following libraries.