[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Teaching emacsclient to act as a pager, and more
From: |
Spencer Baugh |
Subject: |
Teaching emacsclient to act as a pager, and more |
Date: |
Mon, 6 Jun 2016 21:25:01 -0400 |
Hi emacs-devel,
I've added the ability for emacsclient to act as a pager, such that
you can pipe data to emacsclient and page through it in the emacs
frame of your choice. The attached patches are on top of commit
549470fdf234acb4da7941e3bb9b28ed63a51876
Here is a video demo: https://catern.com/files/emacspager.webm
To do this, I've used the file descriptor passing feature of Unix
sockets, which allows a process to transmit a duplicate of any of its
open file descriptors over a Unix socket to another process. The other
process can then make full use of that file descriptor, including, of
course, reading and writing from it.
In the attached patches, I taught emacsclient to (when a new option
--pipeline/-l is passed) send its stdin/stdout/stderr to the emacs
server, and I taught the emacs server to accept those file descriptors
and make an Elisp process out of them. Then the process machinery does
the rest of the work of reading data from the Elisp process (which is
actually data coming in on emacsclient's stdin) and putting it in a
buffer.
This functionality is exposed to Elisp by simply directly passing
received file descriptor numbers to the process filter function (with
a new argument, to processes that have opted in with a new keyword
argument :ancillary). Those file descriptor numbers can be passed to a
new function make-fd-process.
I've written a function in Elisp, server-pager, which should be run
with emacsclient -l --eval (server-pager). I added a new dynamic
variable server-emacsclient-proc which is non-nil if we are currently
evaluating Lisp for an emacsclient, and holds the Elisp process
corresponding to that Emacsclient. server-pager uses this variable to
retrieve the file descriptors for the current emacs-client, invoke
make-fd-process, and pop-to-buffer the output buffer. server-pager
stores the Elisp process it creates in the plist of the corresponding
emacsclient, so when the Elisp process is killed, emacsclient is told
to exit (if it didn't also open frames). Likewise if emacsclient is
killed, the server-pager Elisp process is killed.
The primary issue here, it seems to me, is that this leads to huge
amounts of file descriptor leakage - if any passed-in file descriptor
is unused, it is eternally left open. I think a good way to fix this
is to add a native Elisp file descriptor type, so the file descriptor
can be closed on garbage collect. But perhaps there's a better
solution? In any case I would need guidance on how to create such a
new Elisp type - this is my first attempt to hack on the Emacs C
codebase.
I am sure that these patches are terrible style, not in keeping with
the Emacs coding conventions, and totally unportable (I wrote this on
GNU/Linux) - I just wanted to get out a quick proof of concept.
- Teaching emacsclient to act as a pager, and more,
Spencer Baugh <=
- [PATCH 3/5] emacsclient: support passing stdin/out/err to emacs, Spencer Baugh, 2016/06/06
- [PATCH 4/5] server: add pager tapping and show-active, Spencer Baugh, 2016/06/06
- [PATCH 5/5] emacsclient: add extra-quiet mode, Spencer Baugh, 2016/06/06
- [PATCH 1/5] process: add features for direct use of FDs, Spencer Baugh, 2016/06/06
- [PATCH 2/5] server.el: accept FDs from emacsclient, Spencer Baugh, 2016/06/06
- Re: Teaching emacsclient to act as a pager, and more, Tassilo Horn, 2016/06/08
- Re: Teaching emacsclient to act as a pager, and more, H. Dieter Wilhelm, 2016/06/09