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 [0x45070AD6]