Reputation: 1237
I'm trying to write an emacs LISP function to un-indent the region
(rigidly). I can pass prefix arguments to indent-code-rigidly
or
indent-rigidly
or indent-region and they all work fine, but I don't
want to always have to pass a negative prefix argument to shift things
left.
My current code is as below but it seems to do nothing:
(defun undent ()
"un-indent rigidly."
(interactive)
(list
(setq fline (line-number-at-pos (region-beginning)))
(setq lline (line-number-at-pos (region-end)))
(setq curIndent (current-indentation))
;;(indent-rigidly fline lline (- curIndent 1))
(indent-region fline lline 2)
;;(message "%d %d" curIndent (- curIndent 1))
)
)
I gather that (current-indentation)
won't get me the indentation of the first line
of the region, but of the first line following the region (so a second quesiton is
how to get that!). But even when I just use a constant for the column (as shown,
I don't see this function do any change.
Though if I uncomment the (message)
call, it displays reasonable numbers.
GNU Emacs 24.3.1, on Ubuntu. And in case it matters, I use
(setq-default indent-tabs-mode nil)
and (cua-mode)
.
I must be missing something obvious... ?
Upvotes: 0
Views: 313
Reputation: 916
All of what Tim X said is true, but if you just need something that works, or an example to show you what direction to take your own code, I think you're looking for something like this:
(defun unindent-rigidly (start end arg &optional interactive)
"As `indent-rigidly', but reversed."
(interactive "r\np\np")
(indent-rigidly start end (- arg) interactive))
All this does is call indent-rigidly
with an appropriately transformed prefix argument. If you call this with a prefix argument n
, it will act as if you had called indent-rigidly
with the argument -n
. If you omit the prefix argument, it will behave as if you called indent-rigidly
with the argument -1
(instead of going into indent-rigidly
's interactive mode).
Upvotes: 3
Reputation: 4235
There are a number of problems with your function, including some vary fundamental elisp requirements. Highly recommend reading the Emacs Lisp Reference Manual (bundled with emacs). If you are new to programming and lisp, you may also find An Introduction to Emacs Lisp useful (also bundled with Emacs).
A few things to read about which will probably help
Read the section on the command loop from the elisp reference. In particular, look at the node which describes how to define a new command and the use of 'interactive', which you will need if you want to bind your function to a key or call it with M-x.
Read the section on variables from the lisp reference and understand variable scope (local v global). Look at using 'let' rather than 'setq' and what the difference is.
Read the section on 'positions' in the elisp reference. In particular, look at 'save-excursion' and 'save-restriction'. Understanding how to define and use the region is also important.
It isn't clear if your writing this function just as a learning exercise or not. However, just in case you are doing it because it is something you need to do rather than just something to learn elisp, be sure to go through the Emacs manual and index. What you appear to need is a common and fairly well supported requirement. It can get a little complicated if programming modes are involved (as opposed to plain text). However, with emacs, if what you need seems like something which would be a common requirement, you can be fairly confident it is already there - you just need to find it (which can be a challenge at first).
A common convention is for functions/commands to be defined which act 'in reverse' when supplied with a negative or universal argument. Any command which has this ability can also be called as a function in elisp code with the argument necessary to get that behaviour, so understanding the inter-play between commands, functions and calling conventions is important.
Upvotes: 2