0

This could be a useful FAQ for non-emacs-programmers.

What should I put into .emacs.d/init.el in order to hard-code a specific shell filter that will replace the contents of the region?

For example, say I wanted to create an emacs command named uniqc that replaces the region with the output of uniq -c. This should presumably be based on shell-command-on-region... If I figure it out myself, I will post it tomorrow.

2

If I understand you properly, you're asking how to automate calling a command with a specific set of arguments. To do this, first take a look at the command in question: C-h f shell-command-on-region:

shell-command-on-region is an interactive compiled Lisp function in ‘simple.el’.

It is bound to M-|, .

(shell-command-on-region START END COMMAND &optional OUTPUT-BUFFER REPLACE ERROR-BUFFER DISPLAY-ERROR-BUFFER REGION-NONCONTIGUOUS-P)

...

This gives us the outline of the command we want to call. The part I've trimmed at the end explains the arguments in detail.

The command you actually want to call is:

(shell-command-on-region <beginning-of-region> <end-of-region> "uniq -c" nil t)

We need to replace the bits in <...> with actual elisp. The apropos command can help here: M-x apropos region beginning:

...
region-beginning Function: Return the integer value of point or mark, whichever is smaller.

...

That's handy. The same thing works for region end, although there are a few more things to work through.

That gets us the following:

(shell-command-on-region (region-beginning) (region-end) "uniq -c" nil t)

Now all we need to do is wrap that in an interactive function, aka a command, that we can call:

(defun uniqc ()
  (interactive)
  (shell-command-on-region (region-beginning) 
                           (region-end) "uniq -c" nil t))

Now we can test that out. Paste it in your scratch buffer, but the cursor after the end of the defun, and type C-j. Then set a region, and call M-x uniqc. Voila! It does what we want.

You can save that code directly in your .emacs, and then you'll have uniqc available everytime you start emacs. You can also bind it to a key if you want a shortcut; there are lots of questions here about keybindings.

Finally, there's a convenience for getting the region beginning and end that can make our function a little neater:

(defun uniqc (BEG END)
  (interactive "r")
  (shell-command-on-region BEG END "uniq -c" nil t))

See the elisp manual for a full explanation of how to use the interactive form.

| improve this answer | |
  • how to prevent replacement if the exit is an error code? – ivo Welch Jan 14 at 1:06
1
(defun my-filter (start end)
  (interactive "r")
  (shell-command-on-region start
                           end
                           "uniq -c"
                           1 ;; use current buffer
                           1 ;; replace the text region selected
                           nil
                           t
                           nil))
| improve this answer | |
  • how to prevent replacement if the exit is an error code? – ivo Welch Jan 14 at 1:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.