
Writing an editor in less than 1000 lines of code, just for fun - dwaxe
http://antirez.com/news/108
======
SwellJoe
Awesome. When I saw all the things it could do in so little code, I assumed a
higher level language would be used. But, nope...plain old C with the usual
standard libraries.

The parser for the syntax highlighting is super cool. Concise and declarative
definition of the syntax (well, the keywords, anyway), in HL_keywords, and
then maybe 150 lines of code for the parser. I doubt it would work well for a
much more complex language than C (say, JavaScript, or Perl), without a lot
more smarts. But, it works really well on the C I looked at. Colors are
handled in a cute way, too.

All around, I'm just astounded at how concise this is, while still being
entirely readable and comprehensible. This isn't clever/tricky golfing code,
this is actually human-readable C code.

Edit: Also, I'm struck by how nice/simple the editorProcessKeypress handling
is. Trying to do something like this in JavaScript/HTML5 is crazily more
complex and verbose. Seeing something like this reminds me how messy user
interaction still is in the browser, compared to old CLI and desktop
paradigms.

~~~
groovy2shoes
The syntax highlighter isn't really a parser, _per se_. It's just a lexer /
tokenizer / scanner / what-have-you, which tend to be fairly compact state
machines.

As an aside, I agree with your edit. As someone who started programming back
in the DOS days, whenever I do Web development, I'm always floored by how much
it feels like one step forward and two steps back. So many simple things just
_aren 't simple_ when it comes to the browser, and even certain protocols on
the backend like FastCGI seem way more complicated than they need to be (SCGI
seems pretty nice, though I feel it's missing a way to signal out-of-band
information to the Web server, the way you'd use stderr in CGI, for example
(though perhaps I'm missing something there)).

As much as I love the idea of sending semantic markup over the wire for
document transfer, I can't help but wonder if a more terminal-like protocol
would be better for application "delivery", the way we used to do with telnet
and BBSs in the 90s, with an upgrade for multimedia. But I digress...

~~~
nostrademons
FastCGI/SCGI were obsoleted by having app servers simply speak HTTP; the web
gateway just needs to function as a simple reverse proxy. HTTP is about as
simple as it gets to parse - you can write a passable (not quite production
quality, but works) parser in about 10 minutes.

A lot of the difficulty in webapps is because every webapp is inherently a
distributed system, which are always hard. Single-page apps with no connection
to a server are actually quite simple, but they're also about as commercially
viable as DOS programming (i.e. not at all).

~~~
voltagex_
A while back I'm sure I saw a HTTP state diagram posted here that showed
writing a HTTP parser is anything but simple. I guess if you _only_ have to be
a (reverse) proxy you might get away with it.

~~~
niftich
You're thinking of [https://github.com/for-GET/http-decision-
diagram](https://github.com/for-GET/http-decision-diagram)

~~~
jahewson
That's the state diagram for processing the full complement of HTTP requests.
Nothing to do with parsing. The parsing bit is trivial.

~~~
niftich
While you're correct that it's a state diagram processing HTTP semantics and
not parsing; parsing a text-based protocol is far from trivial. In fact, the
HTTP2 FAQ explicitly mentions [1] that reducing parsing complexity was a
motivation for going binary with HTTP2.

[1] [https://http2.github.io/faq/#why-is-
http2-binary](https://http2.github.io/faq/#why-is-http2-binary)

~~~
nostrademons
I've done perfectly adequate HTTP parsing with this Python 4-liner:

    
    
      headerText, body = text.split('\r\n\r\n', 1)
      headerLines = headerText.split('\r\n')
      method, path, protocol = headerLines[1].split(' ')
      headers = dict(line.split(':').map(str.strip) for line in lines[1:])
    

For production use you'd probably want something a bit faster & more robust
like Mongrel's HTTP parser (itself only 166 lines of Ragel), which powers
several million websites out there:

[https://github.com/mongrel/mongrel/blob/master/ext/http11/ht...](https://github.com/mongrel/mongrel/blob/master/ext/http11/http11_parser.rl)

~~~
niftich
That's a perfectly adequate 4-line HTTP/1.0 parser :) But for HTTP/1.1, which
must support chunked transfer coding [1], this won't work.

[1]
[https://tools.ietf.org/html/rfc7230#section-4.1](https://tools.ietf.org/html/rfc7230#section-4.1)

------
sudhirj
Off topic, but my biggest takeaway was that I could aspire to be someone who
isn't a twenty something, with a family, with superb work life balance, not
living in the valley, sitting in a garden without three 27 inch monitors, not
using the latest programming language or fad and still writing beautiful code
that a lot of the world runs on.

~~~
zaif
I agree. I LOVE how his post weaves in his normal life, having time for doing
things he actually loves outside of work, while still continuing to work on
passion projects. It just goes to show you that you don't need to always buy
into the cowboy coding hype that is often on display here.

------
cantrevealname
> Let’s say this again, “email client”. The notion of email client itself is
> gone at this point.

Really? Is it lame to be using an email clients these days?

I still use an email client (Thunderbird) because I can't stand the thought of
all my mail sitting forever on Goggle's or whoever's servers. Yes, I _know_
that they could have secretly archived all of my email the moment it was sent
or received, and that my privacy is not necessarily enhanced by downloading
and storing my mail offline.

That's my main reason, but I can think of many other reasons to prefer email
clients to a web interface.

I'm surprised by the sentiment that email clients are passé.

~~~
Sir_Cmpwn
I've actually been working on a new email client, and a terminal one at that.
Shameless plug:
[https://github.com/SirCmpwn/aerc](https://github.com/SirCmpwn/aerc)

~~~
Sidnicious
Very cool! Going by the acronym, are you trying to make a Stallman-ish IMAP
client that works well offline and only needs an occasional Internet
connection to sync?

~~~
Sir_Cmpwn
No, just that it does networking on a different thread. This is my main (but
not only) problem with mutt. I'm not opposed to going in the direction you
suggest, but think more mosh less stallman.

------
petercooper
_And yet I read, on Hacker News, a number of people writing how they were
often saved by the availability of nano on random systems_

All the time, but I even use nano all the time on OS X for full on
programming, mostly for quick edits or starting things off before I can be
bothered opening a full project in Sublime. (Sure, I can 'get around' in vi,
but I just don't seem to have the brain for it and nano is 90% fine. I grew up
on GWBASIC so anything is an improvement ;-))

That aside, this feels like it could be a kinda cool command line level
equivalent of ToDoMVC. Port this simple editor into Go, Rust, and a few
similar languages - see what the differences are, etc.

~~~
elsurudo
Nice thing about Nano is that they arrow keys always seem to do what they are
supposed to, no matter the system, shell, TTY, etc. Vi seems to have issues
sometimes, and needs extra config

~~~
savanaly
Presumably h, j, k, l will always get you around in vi?

~~~
IshKebab
Yeah but that is so much less usable. Quick, which one is up?

~~~
Someone
Just look at your keyboard :-)

([https://en.m.wikipedia.org/wiki/ADM-3A#Legacy](https://en.m.wikipedia.org/wiki/ADM-3A#Legacy))

I always _try to_ remember them by noting that the leftmost key moves left,
the rightmost key moves right (not too hard), and that 'K climbs' (using
alliteration to remember that). That leaves 'J' for cursor down.

In practice, though, I use the cursor keys. Luckily, they work on the
editors/systems I work on nowadays. Side effect is that I am very bad at
remembering those mnemonics.

~~~
robgough
I stole the following from a colleagues `.vimrc` which finally allowed me to
learn `hjkl`. Now I forget I have this set, and when I do accidentally use an
arrow key it makes me laugh.

    
    
        map <Left> :echo 'damnit!'<cr>
        map <Right> :echo 'you suck!'<cr>
        map <Up> :echo 'this is why you fail'<cr>
        map <Down> :echo 'nooooo!'<cr>

------
emilong
This is the kind of magic that got me excited about programming in the first
place.

I remember being in high school and one day, after class, a friend of mine
mentioned that the best programmer we knew had once written a breakout clone
with ANSI "graphics." We found him and he said he didn't have the source any
more, but we asked him how he did it. He then proceeded to rewrite the whole
thing, in Pascal, in about an hour, this time adding animations. Thanks
antirez for bringing back that feeling (and, oh yeah, for redis too ;))

PS. the "Low level terminal handling" is gold here.

------
Chris_Newton
I love seeing little projects like this, and I wish I were better at finding
time to do them myself. It’s all too easy when you’ve been programming
professionally for a long time, often working on the same projects every day
for months or years, to lose that sense of wonder at what we can achieve in a
few hours with a modest amount of code. Sometimes it’s good to just sit down
for a day or two and hack together a kind of program you’ve never written
before, whether that’s a text editor or a puzzle game or rendering a pretty 3D
fractal landscape or an IRC chat bot. It’s always nice to see someone else
who’s created something that way too, so thanks for sharing.

------
sdegutis
Honestly, this is the most exciting and inspiring project I've seen on HN in
years, by far. I love that it's a fully usable terminal-based text editor that
has _zero dependencies_. Just perusing the source code has been extremely
interesting and educational for me already, and it's only been 5 minutes.
Definitely gonna bookmark this project and hack on it! The TODO list looks
like a good start, especially the xterm-based feature.

~~~
oneeyedpigeon
You can tell it's going to be good when, on a Mac, you download the source and
compile it, and a) it compiles b) it doesn't give a single warning. It's nice
when portability actually works.

------
marssaxman
Yay, this is delightful.

I wrote a nano-inspired TTY-based editor, too, and have used it to do
virtually all of my coding work for the last couple of years. There's nothing
particularly noteworthy about it, technologically, but it does exactly what I
want in exactly the way I want it to, and that was enough to make the time
spent feel worth my while.

There's something really satisfying about the exercise of creating one's
tools. I think there is a lot of value in projects like this whether anyone
else ever uses them or not, as an exercise in software craftsmanship.

Looking at this project, I am inspired to see if I could simplify my editor's
codebase. I was never fully convinced that ncurses did enough good to justify
its complexity; it might be interesting to adopt this author's approach
instead.

------
Smerity
When I started programming, the basic digital world already existed for me. I
never had the experience of typing in a program from a magazine. This is one
of those odd experiences where you remember that self-hosting[1] can involve
far more components than just the compiler, spiraling an unexpectedly deep
path into the development stack.

I just used @antirez's 1k LOC kilo editor to edit his 1K LOC editor and it was
an oddly pleasurable experience :)

[1]: [https://en.wikipedia.org/wiki/Self-
hosting](https://en.wikipedia.org/wiki/Self-hosting)

------
voltagex_
This is the programming equivalent of a food blog post (technical details
interspersed with what's happening in the author's life). It's great and I
think there should be more of it!

------
_pmf_
Cool; now embed it into a 150 MB Electon app and you have a state of the art
editor (maybe introduce several arbitrary delays in the range 300 ms - 2 sec
for the authentic Atom feeling)!

------
fitzwatermellow
Wow! I love this!! Thanks for the post antirez, if just for introducing me to
this now indispensable tool ;)

asciinema - Record and share your term sessions

[https://asciinema.org/](https://asciinema.org/)

~~~
piokuc
Yes, asciinema is a wonderful thing I learned about from this blogpost too.
And another one from the asciinema.org: lolcat! Command line forever!

------
mej10
This is great! I love seeing how experienced programmers write small programs
like this, especially "from scratch".

------
gnuvince
Can anyone explain how to do a full-screen UI using only VT100 codes? If I had
to write a small editor, I'd probably reach for something like Termbox for
display.

~~~
destructionator
First, switch it to alternative screen mode... printf("\033?1047h"); then
clear and move and such with other similar prints. See the list here :
[http://invisible-island.net/xterm/ctlseqs/ctlseqs.html](http://invisible-
island.net/xterm/ctlseqs/ctlseqs.html)

It really is pretty simple. The big benefit of ncurses is if you want to
target terminals other than xterm compatible ones, and they are so rare
nowadays that you can really just ignore them....

Input is quite a pain though (however, ncurses sometimes get it wrong too),
but the same thing applies, you just need to switch to raw mode with tcsetattr
and then have some kind of select() loop or something to watch for escape
sequences then translate them into interesting key presses.

Mouse events are the same btw: you write out a sequence to turn them on, then
the terminal sends them as sequences to stdin.

I wrote a terminal library myself for the D programming language (and a
terminal emulator too!), it is kinda ugly code but it isn't hard.

~~~
voltagex_
I wonder if these codes work in cmd.exe now that Windows 10 TH2 supports (some
of) the features.

~~~
destructionator
I haven't checked but I kinda doubt it... and I kinda hope not - the windows
console API is so much nicer than the unix terminal system it would be a pity
to make it an ugly hybrid.

Of course, you can run a terminal emulator inside the windows console and
handle those sequences too! If I had to guess, I'd say that's what Microsoft
would have implemented.

------
ag_47
Pretty cool. Something like this would make for a nice school project, I would
have loved being assigned to write a simple editor back in uni

------
sscarduzio
@Antirez please please please let this thing have a future: there is a great
need for a modern, simple and usabile CLI editor.

~~~
_acme
Try vis: [https://github.com/martanne/vis](https://github.com/martanne/vis)

~~~
gnuvince
I find it funny that a person named _acme suggests vis :)

------
greglindahl
It would be fun to see this project replicated using some other underlying
data structures, e.g. the buffer-gap data structure used by emacs.[0] Does the
code become shorter/prettier? etc.

0:
[https://en.wikipedia.org/wiki/Gap_buffer](https://en.wikipedia.org/wiki/Gap_buffer)

------
Dagwoodie
What challenges might you have if you wanted to implement something like this
inside a game framework like Unity or MonoGame with C#, where it renders
everything via DirectX or OpenGL?

~~~
moron4hire
The main challenge is that, even now, in the year 2016, there is no
objectively good, fast, reliable way of rendering arbitrary text with
formatting in a texture. Hell, even just plain text is kind of a pain in the
ass.

And yes, I know about signed distance fields.

~~~
Dagwoodie
The nice thing about a framework like Unity is that they do have a textfield
object that behaves a lot like a standard text object in the .NET Framework.
It has a lot of shortcomings but rendering the text is the easy part.

~~~
badlogic
Unity only supports Unicode BMP. Unity doesn't support surrogates, RTL
rendering/input etc. Rendering the text performantly for none western scripts
is definitely not the easy part, especially on mobile (where Unity also fails
to behave properly).

~~~
moron4hire
Proper Unicode and RTL support is something Jonathan Blow recently spent a
_lot_ of time getting just right for The Witness. I wonder if he'd ever
consider open sourcing that work.

------
cyberferret
Nice work. I clearly remember writing a full screen editor in a few hundred
lines of Turbo Pascal back in '86 because I hated using EDLIN to edit .BAT
files in DOS... :D

------
Razengan
Anyone up for converting it to Swift (3) or Rust?

~~~
philippnagel
I am currently learning Rust, would be happy to give it a shot! My email can
be found in my profile

------
13of40
Back in the 90's I took a class in Visual Basic, where one of the assignments
was to write a rules-compliant tic-tac-toe game. The teacher apologized for
the amount of repetitive code we'd have to write to implement it in Windows
forms (or whatever it was called back then). I got it down to one printed
page.

~~~
AstroJetson
When I taught V that was a class assignment (along with create a 4 function
calculator). I don't remember any of the programs being that long.

For extra credit for people that had problems I'd allow a resubmission of an
assignment if you did the logic in a different way. One of the students did a
table that let them look up the current board and say what the new move was.

------
yati
> WARNING: Long pretty useless blog post

Antirez's posts are hardly ever really "useless" :) Awesome stuff, as always.

------
sdegutis
What's especially impressive to me is that _it even has syntax highlighting._

------
justinmk
> a text editor in less than 1000 lines of code that does not depend on
> ncurses and has support for syntax highlight and search feature.

Neovim also does not depend on ncurses. Vim optionally links to it for
termcap/terminfo access.

------
c-smile
Cool :)

But editor without undo/redo is a bit surprising these days, next release?

~~~
oneeyedpigeon
That's what git is for ;-p

------
asimuvPR
If antirez is reading:

How much time did this take? From start to finish. :)

~~~
martin_
The GitHub page states: "The project is in alpha stage and was written in just
a few hours taking code from my other two projects, load81 and linenoise."

[https://github.com/antirez/kilo](https://github.com/antirez/kilo)

~~~
asimuvPR
Yes, thanks for pointing that out. I'm more interested in total time. Not time
to write. :)

~~~
antirez
Hello! It was a few hours (probably 6-8) across a total of two weekends (so a
total span of 9 days where I did 2 "days" of work, 5 days of pause, 2 days of
work).

~~~
asimuvPR
Thanks for answering.

------
harel
I'm reading the code as a Primer. Fantastic stuff you don't see often.

------
exabrial
Id like to see people have competitions to write an editor in the most
readable amount of lines of code

------
ben_jones
Bonus points for being in C

------
vzhang
cough cough fewer than... cough cough...

~~~
lukeHeuer
He mentioned using cloc to get that metric, so not including comments,
formatting, etc.

~~~
_acme
I think you missed the point: the point is that the correct English usage is
"fewer than" when discussing quantifiable items (e.g., lines of code). The
title should be "...an editor in fewer than 1000 lines of code."

~~~
lukeHeuer
Thank you for clarifying. I thought for a second it could have been a
grammatical nitpick but discounted that since this thread is re: an Antirez
post. I personally would be very sad if his writing style became more forced
and began to feel like excerpts from The Elements of Style.

