1

I try to run several commands in a sequence in Emacs. None of the commands needs an argument (indent-region, untabify, and delete-trailing-whitespace). I tried to follow the older post on emacs-key-binding-for-multiple-commands and came up with the following solution:

(defun format-properly ()
    "Run `indent-region', `untabify' and `delete-trailing-whitespace' in sequence."
    (interactive)
    (indent-region)
    (untabify)
    (delete-trailing-whitespace))

(global-set-key (kbd "C-c a b c") 'format-properly)

This gives me the following error message when I try to run it: "Wrong number of arguments: (2 . 3), 0".

Since I have zero experience with lisp, I don't have any idea what to do and would be happy about any suggestion. :)

Thanks! Julie

Julie
  • 13
  • 3
  • 3
    When deciding whether a function needs one or more arguments, it is usually necessary to look up the function and examine the help window or visit the source code directly. `M-x describe-function RET indent-region RET` tells us that there are indeed arguments -- two mandatory and one additional that is optional. Read the doc-string for each function ... You may need things like `(when (region-active-p) ...)` and functions such as `region-beginning` and `region-end` ... To visit the source code directly, type `M-x find-function` – lawlist May 24 '17 at 05:46
  • Are you also aware of [keyboard macros](http://wikemacs.org/wiki/Keyboard_macros) ? They may be easier to setup. – Ehvince May 24 '17 at 23:49

1 Answers1

4

To build on lawlist's comment, interactive commands often take non-optional arguments, even when you don't explicitly supply them. There's a special way to declare an interactive command that takes the region: (interactive "r"), that will pass the region to the command automatically.

(defun format-properly (b e)
  "Run `indent-region', `untabify' and `delete-trailing-whitespace' in sequence."
  (interactive "*r")
  (when (use-region-p)
    (save-restriction
      (narrow-to-region b e)
      (indent-region (point-min) (point-max))
      (untabify (point-min) (point-max))
      (delete-trailing-whitespace (point-min) (point-max)))))

Try looking at the docs for interactive and any other functions or variables you're interested in with C-h o (describe-symbol).

jpkotta
  • 9,237
  • 3
  • 29
  • 34
  • Thanks a lot! That was exactly what I was looking for. It now does not raise an error when executed anymore and it runs the first command (indentation) properly. It however does not apply the subsequent "`untabify`" and "`delete-trailing-whitespace`" because I guess the "`indent-region`" itself destroys the region I've marked before running "`format-properly`". – Julie May 25 '17 at 14:49
  • @Julie Setting `deactivate-mark` to `nil` should force all of the functions should keep the region active. It works for me. Try it with `emacs -q`, which disables all customizations. – jpkotta May 25 '17 at 16:08
  • @jpkotta I actually don't use any other customization. Maybe the problem appears because I use Aquamacs and not "pure" emacs?! – Julie May 29 '17 at 21:47
  • @Julie yeah that's possible. Apparently Aquamacs bundles a lot of extras. You can try it with `emacs -Q`, which should disable both user and system customizations (I probably should have said that in the first place). If that doesn't work, try it with vanilla GNU Emacs. – jpkotta May 30 '17 at 15:27
  • @jpkotta `emacs -Q` also did not help. You mentioned that already before. :) – Julie May 31 '17 at 17:49
  • @jpkotta But I saw in another post [Making a region-indent-function keep the region marked](https://stackoverflow.com/questions/6529174/making-a-region-indent-function-keep-the-region-marked) that it seems that the problem is that _"[..] As of emacs 24.3.1 at least, indent-region' calls (deactivate-mark)` directly, without querying the deactivate-mark variable. Hence when changing indentation behaviour by setting the value of indent-line-function or indent-region-function, doesn't allow preserving highlighted region.[...]"_ – Julie May 31 '17 at 17:52
  • @Julie `emacs -Q` and `emacs -q` are different. I rewrote it to hopefully make it more robust. Now it shouldn't care about `deactivate-mark` or the fact that the region potentially changes as the functions are run. – jpkotta May 31 '17 at 21:30