From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Spencer Baugh Newsgroups: gmane.emacs.devel Subject: Teaching emacsclient to act as a pager, and more Date: Mon, 6 Jun 2016 21:25:01 -0400 Message-ID: <1465262706-5229-1-git-send-email-sbaugh@catern.com> NNTP-Posting-Host: plane.gmane.org X-Trace: ger.gmane.org 1465262799 13064 80.91.229.3 (7 Jun 2016 01:26:39 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Tue, 7 Jun 2016 01:26:39 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Jun 07 03:26:32 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1bA5mp-0003NN-Jl for ged-emacs-devel@m.gmane.org; Tue, 07 Jun 2016 03:26:31 +0200 Original-Received: from localhost ([::1]:46339 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bA5mo-0005Zw-J4 for ged-emacs-devel@m.gmane.org; Mon, 06 Jun 2016 21:26:30 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:51474) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bA5m1-0005ZU-SR for emacs-devel@gnu.org; Mon, 06 Jun 2016 21:25:43 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bA5lx-00023A-Kn for emacs-devel@gnu.org; Mon, 06 Jun 2016 21:25:40 -0400 Original-Received: from catern.com ([104.131.201.120]:38400 helo=mail.catern.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bA5lx-00022T-Fg for emacs-devel@gnu.org; Mon, 06 Jun 2016 21:25:37 -0400 Original-Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.catern.com (Postfix) with ESMTPSA id E7EA14F568 for ; Tue, 7 Jun 2016 01:25:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=catern.com; s=default; t=1465262730; bh=AazYCFw4ZiyosQWsxZ7l+q6LbTBkakehtSWkeWdIiRQ=; h=From:To:Subject:Date; b=D62QYKqL4qlAAPQ8ER7PekistfWvk7Uw83Wym/OyeV0P2+xa44xEb8iKG3Yh3uziI KuNg1Bp7jZyXNr73Qz6UDSY1alvx6xHHhJucRUqNuuFXEPrSZhUfnng0Job5j7SI4Y zzWeRmdbSeeqzJFQSXG1YDi0jt6mcnA/muowdNsc= X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] X-Received-From: 104.131.201.120 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:204217 Archived-At: 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.