1

I try 2 inline Elisp script.

$ emacs --batch -q --eval="(dolist (elm (list 1 2 3 4 5)) (princ (format \"%s, \" elm)) (sit-for 1))"
1, 2, 3, 4, 5,

$ emacs --batch -q --eval="(dolist (elm (list 1 2 3 4 5)) (princ (format \"%s, \\n\" elm)) (sit-for 1))"
1, 
2, 
3, 
4, 
5,

The former is output all at once with buffering, while the latter is output gradually every second. It seems that output buffering is done using line feed as a trigger. Is there a way to output without buffering in the former case?

I'm using Emacs-27.1.

Drew
  • 29,895
  • 7
  • 74
  • 104
Conao3
  • 171
  • 1
  • 3
  • 17
  • 1
    If you are on Linux, you may use [this method](https://stackoverflow.com/a/25548995/605276) for stting stdout buffer length to 0. – Juancho Mar 09 '21 at 18:47

1 Answers1

0

I haven't managed to find a prettier way to do this, but this works:

$ emacs --batch -q --eval="(dolist (elm (list 1 2 3 4 5)) \
                             (princ (format \"%s, \" elm)) \
                             (set-binary-mode 'stdout nil) \
                             (sit-for 1))"

set-binary-mode can be used to set output mode to either text, or binary. They are the same in POSIX shells, and we shouldn't be changing anything since we're just asking it to stay in text mode. But the important part is that if flushes pending output. From the elisp manual:

Function: set-binary-mode stream mode

Switch stream into binary or text I/O mode. If mode is non-nil, switch to binary mode, otherwise switch to text mode. The value of stream can be one of stdin, stdout, or stderr. This function flushes any pending output data of stream as a side effect, and returns the previous value of I/O mode for stream. On POSIX hosts, it always returns a non-nil value and does nothing except flushing pending output.

Leonardo Dagnino
  • 2,914
  • 7
  • 28
  • The problem exists at a lower level than emacs, so trying to solve it **in** emacs is bound to lead to kludges. See @Juancho's comment on how to solve it at the proper level. – NickD Mar 10 '21 at 19:08
  • I don't think `stdbuf`/`unbuffer` can really be called the proper level. It's a hackish solution using LD_PRELOAD. The actual 100% fix for this is for the application itself to have an option to not line-buffer; which is kind of what we're doing it on my response, forcing emacs to flush buffers. For this reason I consider this to be more "at the proper level" than using `stdbuf`. Doing that with a function called `set-binary-mode`, though, does also feel hackish. – Leonardo Dagnino Mar 10 '21 at 20:18