Formatting buffers with remote processes

Jordan Ellis Coppard <[email protected]> Mon, 10 Feb 2025 03:43:54 +0900
Newsgroups gmane.emacs.tramp
Message-ID <[email protected]>
Hi Michael,


I'm going to try and add support for remote formatting commands for this 
package: https://github.com/purcell/emacs-reformatter/issues/32

The entire package itself is ~350 lines of elisp with a majority of that 
being documentation comments. I wonder if you can advise me on the best 
approach to take here.

Imagine the scenario where a user is working on a remote project using 
Tramp and they want to run whatever their project's source-code 
formatting tool is. There are two possible cases:

1. The user just happens to have that same tool installed locally;
2. The user only has the tool installed remotely where their project is.

In (1)s case I imagine an on-save hook simply uses call-process to 
execute the formatting tool, the formatted contents replace the buffer, 
and when the buffer is saved Tramp handles copying the file to the 
remote -- effectively this is no different from _not_ using a formatting 
tool and saving a buffer which Tramp is going to copy to a remote anyway.

In (2)s case, and preferring asynchronous processes so as to not block 
Emacs, would you advise using make-pipe-process, make-process, 
start-file-process (or others)?

In the case the remote formatting command is given as an absolute path I 
imagine a pipe process could work best (no shell required, extra Tramp 
regex-matching, looking through $PATH to find the command executable); 
am I mistaken there or is that generally true?

My main goal here is to minimise round-trips (which do add up quickly 
and make even localhost "remote" saves take about 0.23 seconds). Is my 
understanding of the general flow for either approach correct?

For a shell-based remote asynchronous process:

--> save-buffer
   | --> tramp copies local file contents to remote
   | --> tramp executes formatting command on remote
   | --> formatting command has changed remote file
   | <-- tramp must copy from the remote back to local the new contents
<--

For a pipe-based remote asynchronous process:

--> save-buffer
   | --> tramp makes a remote pipe process
   | --> local buffer contents piped to formatting process
   | <-- formatting process spits to its stdout the formatted contents
   | --> tramp copies local file contents to remote
<--


/Jordan

P.S. I will get to trying out Eglot things within the next day or two 
wrt the other emails.