Also thanks to the awesome Recurse Center for inviting me to speak and making the recording, and the audience for their great questions.
Also thanks to the awesome Recurse Center for inviting me to speak and making the recording, and the audience for their great questions.
Unfortunately Xi was quite laggy in the scrolling department. Slower than VSCode for example.
I’m in the process of learning Kakoune (1) which happens to have JSON-RPC API as well (2). Kak is fully terminal app which doesn’t give it any edge on latency (doing low latency terminals and shells seems to be a hard task). Hopefully Kak’s take on Vi’s commands as selection oriented language can be leveraged from within Xi editing framework in some capacity.
(1)[http://kakoune.org] (2)[https://github.com/mawww/kakoune/wiki/JSON-RPC]
How soon do you think it will be before more product-level thinking can be brought into the mix?
(Edit: I see I'm not the only one to ask a question along these lines.)
Textmate can bind shell scripts to shortcuts, but letter keys always insert letters, and the editor always shows the file's content.
Emacs can execute arbitrary code on arbitrary keys, which enables you to implement vim-style key bindings. Also, Emacs can display stuff that is not a file, which enables mail clients, git clients, and terminal emulators.
Thanks!
It's not clear to me how this relates to the question. Emacs and vim are native apps.
> In the most common case, both of these editors use the cross-platform "VT-100 UI Toolkit" (e.g. ansi escape codes in your terminal emulator), regardless of platform.
I daresay that the single most common way to deploy emacs is as an X11 editor, followed by a macOS editor, followed by a vt100 console editor. Emacs is a fully GUI programme, and has been for decades at this point.
I think that alone marks you as an unusual emacs user; the standard pattern for using emacs is to leave it running all the time (either in a window, or as a dæmon), not to launch new instances. But yes, it would be interesting to have numbers.
> Being useful in a terminal is a critical requirement for me.
Oh, certainly; in fact, I have 'vi' aliased to 'emacsclient -t' these days for just that reason. It's awesome to have a powerful, extensible editor available in the terminal.
I have EDITOR set to emacsclient (and some other aliases) and I find it far more convenient than an in-terminal editor, especially when combined with sudoedit.
I only use it for quick edits to files, when I don't want to turn my head from my terminal to my emacs window. Yeah, it's just a bit lazy …
Monolithic machine executable that fits into under a meg of RAM and comes up in a fraction of a second from a cold invocation.
The “classic example” of this would be Quake — a single binary implements both a server and a client, which communicate over a simple binary protocol.
Quickly scanning Emacs "NEWS" files, the first mention I found of emacsclient dates back to between '86 and '92. I'm pretty sure it's older. This was added as an option exactly because it is more efficient and leaner to start a separate UI than starting a separate editor instance each time, and adds very little bloat (on my system, emacsclient is a 23KB binary), and it adds so little latency as to not be noticeable.
1. Stability. I'm writing my own editor at the moment, and the text buffers are kept in a server process. Last time I updated the server process it'd been running continuously for a month despite extensive reworking of the frontend. The backed is trivially simple (~300 lines), and easy to keep stable. If the frontend crashes it doesn't take my open buffers with it.
2. Coming up in a fraction of a second with state most of the time. Most of the time I have a ton of buffers in RAM; rather than reloading a ton of files, most of the time when I bring up the frontend, the files I'm working on are already there. Re-establishing an IPC connection to the backend is not noticeable.
3. Faster starts over slow network connections - I can run the backend remotely and not have to transfer a big file other than what is needed to view the bits I care about.
4. Simplicity: I don't need to implement tabs or multiple windows - I got that for free from my window manager. Instead if I want to split the current buffer, I just spawn a new frontend that re-attaches to the same buffer from another process. There should be no need for an editor to re-implement its own window management.
A client-server design makes very little difference to memory usage and doesn't require a separate executable.
Lets look at firefox as an example. The fact that a vertical tabbar is more useful in this case due to screen shape and size and it being useful to be able to read a bit more of the text when you have a lot of tabs. This could in theory by done by your wm even though I've not seen one that does. Further tree style tabs shows a visual hierarchy of sorts that can't be replicated by your wm because it doesn't know what link was opened from what. Further you can perform operations on groups of tabs, like closing them, bookmarking them, reloading them. Its difficult to see how your wm could infer this hierarchy and how it could allow application specific operations like bookmarking even if it could. Further its useful to sometimes open a number of links in the background before switching to any of the above. This is trivially effected within the browser but challenging outside of it because the action of opening a link happens inside the browser.
Within my irc client various channels are arranged according to network and color coded according to activity. Right clicking on individual channels or networks allows specific actions regarding those networks or channels. None of the above would work with a bunch of stacked/tabbed windows.
I could make a list for emacs but the complaint is the same wm ends up being an unfixably poorer alternative to dealing with multiple documents in the app.
I use i3wm not because its awesome at managing multiple documents but because its simple and straightforward and 90% of workspaces, which span only a single monitor, have only 1-2 windows on them. Rarely 3 or 4 and never more.
Window managers are just unfixably mediocre in this respect because the UI doesn't have access to context and can't differ based on use.
When it comes to emacs, I don't agree - the multi-window support I added to my editor was something I added explicitly to mimic my Emacs usage with i3wm. It's very possible that it's down to how I use emacs - I tend to prefer to split with ^X+2 and ^X+3, and that pattern lends itself perfectly to doing window splits with a window manager. If anything, i3wm's support for tabs etc., selectively for any window, is more advanced than the buffer/frame management emacs offers.
> Window managers are just unfixably mediocre in this respect because the UI doesn't have access to context and can't differ based on use.
That's just not the case when you 1) have the source, and 2) are able to control the wm via an API that can provide additional context. To be clear: My current support for this is 100% tied to i3wm, and relies on i3-msg to let me choose which orientation to do the split and exec another instance, and my needs in that respect are simple.
It would be harder to get the same flexibility with a wm that lacks an equally trivial API to control placement. Again, a benefit of being able to fully control my own editor (I am slowly packaging up less opinionated parts of it as separate projects - my goal is that "my" personal part of the editor should be reduced to nothing more than instantiating various generic components) - because of the client-server approach, the grand total of my "multi window support" boils down to this ("term" in this case is a local alias for whatever my current preferred terminal is) :
182│ def split_vertical◂
183│ system("i3-msg 'split vertical; exec term e --buffer #{@buffer.buffer_id}'")◂
184│ end◂
185│
186│ def split_horizontal◂
187│ system("i3-msg 'split horizontal; exec term e --buffer #{@buffer.buffer_id}'")◂
188│ end◂Hardware rendering routinely breaks in Ubuntu (and probably other distros) because NVIDIA's driver still isn't packaged well enough to survive a kernel update, and doesn't work over ssh or on an many embedded systems anyway.
I have successfully integrated several interpreters/event loops into the same process (C++/Boost, Python, Tcl/Tk, Qt). It was a real pain to implement and felt very hacky but worked.
Using processes you can achieve something like a micro-service architecture. An example of where I've seen this kind of coupling is the custom transfer agents in Git LFS.
https://github.com/git-lfs/git-lfs/blob/master/docs/custom-t...
They use processes and line delimited JSON for communication.
I wonder, in the talk you say that you took some ideas from the design of Chrome; do you think that --in turn-- browsers could learn from the concepts in Xi?
And another question: you are using multiple languages. Doesn't that make it needlessly difficult to express the same operations in different (concurrent) parts of the system? E.g. a character update is rendered on the screen (in Swift), and simultaneously the operation is sent to the core (in Rust) to reconcile the change in the core data structures; both operations are essentially the same, but now they have to be written in a different language, which means more development work and increased likelihood of mistakes/inconsistencies (?)
PS: I'm not sure if this makes sense; I couldn't finish watching the talk but will watch the rest later!
I'd consider a different serialization format, but it doesn't seem to be on the critical path for either performance or functionality, so I feel there are a lot of other things ahead of it.
(I'm not sure how much practice there is behind that theory, currently, but that's the plan.)
I for one am glad they didn't go towards custom protocols with single complex implementations, towards something that can be assembled easily from standard components.
I found https://github.com/google/xi-editor/blob/master/doc/plugin.m... , but it doesn't have anything technical (or a tutorial).
Would you mind elaborating on this?
(IE it's not an experimental product, it's not a product at all. It's just raphlinus releasing some code)
The question begged is Why does Google own the code?
To have Google give you (the Google employee) full copyright of projects you work on while at Google, you need to go through a committee[1] that reviews the project to make sure it doesn't collide with some other project Google already is working on. As this is really hard to do for many projects, it's easier to just let Google keep copyright ownership of it and have it opensource under them.
Considering how protective most companies are of IP, I'm shocked Google even has a mechanism by which a person can take back things they've worked on in office at Google.
It's actually a remarkably painless process, which is good because there's actually quite a bit of neat stuff in that neighbourhood of github as a result.
(FWIW, I tried compiling Xi on OSx & opening a large file in it. To its credit, it worked, but there are issues; e.g. horizontal scrollbar is wrong, word wrapping is not working etc)
I'm curious about your reasoning for JSON, as compared to protocol buffers, flat-buffers, etc. I would imagine that accessibility and ease of use would be the main reason for choosing JSON, is that in fact the case?
Are there any other reasons you chose JSON over other wire formats/protocols?
I agree with your assertion in the video that this is not much overhead, but I struggle with this debate as I work to scrape every ounce of performance out of the architecture.
Edit: Asked and answered elsewhere https://news.ycombinator.com/item?id=16268332
I particularly like the "No change of state" meaning in "Z notation", apparently a formal language for specifying and modeling computer systems.
Edit: never mind, author beat me and debunked my overly-complicated analysis