Idiomatic batch processing of text in Emacs?

elisp, emacs

Solution

If you actually want batch processing of `stdin` and sending the result to `stdout`, you can use the --script command line option to Emacs, which will enable you to write code that reads from `stdin` and writes to `stdout` and `stderr`.

Here is an example program which is like `cat`, except that it reverses each line:

#!/usr/local/bin/emacs --script
;;-*- mode: emacs-lisp;-*-

(defun process (string)
  "just reverse the string"
  (concat (nreverse (string-to-list string))))

(condition-case nil
    (let (line)
      ;; commented out b/c not relevant for `cat`, but potentially useful
      ;; (princ "argv is ")
      ;; (princ argv)
      ;; (princ "\n")
      ;; (princ "command-line-args is" )
      ;; (princ command-line-args)
      ;; (princ "\n")

      (while (setq line (read-from-minibuffer ""))
        (princ (process line))
        (princ "\n")))
  (error nil))

Now, if you had a file named `stuff.txt` which contained

abcd
1234
xyz

And you invoked the shell script written above like so (assuming it is named `rcat`):

rcat < stuff.txt

you will see the following printed to stdout:

dcba
4321
zyx

So, contrary to popular belief, you can actually do batch file processing on `stdin` and not actually have to read the entire file in at once.

Problem

In Python, you might do something like ``` fout = open('out','w') fin = open('in') for line in fin: fout.write(process(line)+"\n") fin.close() fout.close() ``` (I think it would be similar in many other languages as well). In Emacs Lisp, would you do something like ``` (find-file 'out') (setq fout (current-buffer) (find-file 'in') (setq fin (current-buffer) (while moreLines (setq begin (point)) (move-end-of-line 1) (setq line (buffer-substring-no-properties begin (point)) ;; maybe (print (process line) fout) ;; or (save-excursion (set-buffer fout) (insert (process line))) (setq moreLines (= 0 (forward-line 1)))) (kill-buffer fin) (kill-buffer fout) ``` which I got inspiration (and code) from Emacs Lisp: Process a File line-by-line. Or should I try something entirely different? And how to remove the `""` from the print statement?

Original source

Related problems