help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Can Emacs pipe a buffer through another one?


From: Marco Parrone
Subject: Re: Can Emacs pipe a buffer through another one?
Date: Thu, 17 Jun 2004 23:53:35 GMT
User-agent: Gnus/5.1006 (Gnus v5.10.6) Emacs/21.3 (gnu/linux)

J Krugman on Thu, 17 Jun 2004 21:09:47 +0000 (UTC) writes:

> Suppose I have two buffers A and B, not necessarily associated with
> a file on disk, and furthermore, suppose that B's content is a
> script (bash, perl, python, etc.) that prints to STDOUT a transform
> of whatever it reads from STDIN.  (Assume that the first line of
> B is a suitable shebang line.)  It would be really cool if, without
> leaving Emacs, and without creating any new files on disk, one
> could feed the contents of buffer A as STDIN to the script in buffer
> B, and take the resulting output and insert them in some other
> buffer C (possibly replacing some or all of C's contents).  (Of
> course, there should be no reason why these buffers should all be
> different from each other.  For instance, B could be a script that
> rewrites itself.)
>
> Even cooler would be if instead of using whole buffers for program
> and data as described above, one could use regions.
>
> Can one already do any of this in Emacs?  If not, can someone give
> me a clue about how to write such a thing in Emacs Lisp?

If creating a temporary file is not a problem, than it's not so hard.

A good way to do it is to try to do it interactively, then figuring
out what functions you have used (using `C-h k KEY'), and write an
elisp version with the help of the elisp manual and the help and
apropos functions.

However, a quick-and-dirty version follows:

(defun shbufwrap (scriptbuf inbuf outbuf)
  (let* ((prefix "/tmp/")
         (filename (concat "shbufwrap-" (number-to-string (random 1000))))
         (path (concat prefix filename)))
    (save-excursion
      (with-current-buffer scriptbuf
        (kill-ring-save (point-min) (point-max)))
      (find-file path)
      (with-current-buffer filename
        (yank)
        (save-buffer))
      (shell-command (concat "chmod +x " path))
      (with-current-buffer outbuf
        (kill-region (point-min) (point-max)))
      (with-current-buffer inbuf
        (shell-command-on-region (point-min) (point-max) path outbuf))
      (kill-buffer filename)
      (shell-command (concat "rm " path)))))

This requires that inbuf and outbuf are not the same buffer. To test it:

eval the previous defun (for example, copy it into the *scratch*
buffer, then do C-x C-e after the last closed paren), then

C-x 1
C-x b *a*
C-x 2
C-x b *b*
something     (text inserted in the *b* buffer)
C-x 2
C-x b *c*     (from here to M-: is text inserted in the *c* buffer)
#!/bin/sh

cat /dev/stdin | sed s,something,somethingelse,g
M-: (shbufwrap "*c*" "*b*" "*a*")

Then you should have "somethingelse" in the "*a*" buffer.

You can hack it to make it interactive (for example, you can modify it
so you can do M-x shbufwrap, and it asks the buffers names).

If you want to make it to replace the input buffer, you can replace

  (shell-command-on-region (point-min) (point-max) path outbuf)

with

  (shell-command-on-region (point-min) (point-max) path nil t)

and

  (defun shbufwrap (scriptbuf inbuf outbuf)

with

  (defun shbufwrap (scriptbuf inbuf)

and you remove

(with-current-buffer outbuf
        (kill-region (point-min) (point-max)))

in the above function (and call it using `M-: (shbufwrap "*c*" "*b*")').

However perhaps `C-u M-| COMMAND' is fine for you (it executes a shell
command on a region, replacing its content).

The `shbufwrap' version involving regions is more interesting, if I
will have it working I will post it in this thread.

-- 
Marco Parrone <marc0@autistici.org> [0x45070AD6]

Attachment: pgpgSS_ToNYnZ.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]