I'm looking for a simple way of indenting paragraphs manually (in text
modes), and I've just read this node of the Emacs Manual: (info "(emacs)
Indentation"). It explains, among other things, the general behavior of
the <TAB> key in text modes:
In text modes, <TAB> inserts some combination of space and tab
characters to advance point to the next tab stop (*note Tab Stops).
If the region is active and spans multiple lines, it advances the first
character of each of those lines to the next tab stop (*note Using
Region). [...]
I'm used to that behavior in other editors, and I like it, but
is not what I currently see in Emacs. e.g.:
- Start Emacs (emacs -Q)
- Set text-mode in the *scratch* buffer. (text-mode).
- Set transient-mark-mode on. (transient-mark-mode 1).
- Select the first 3 lines.
- Type <TAB>
What I was expecting:
- The selected lines move to the next tab-stop.
- The region remains active, so that I can repeat the indentation
several times in a row.
What I see:
- The selected lines are not not moved at all.
- The region is deactivated.
Please, could someone explain this? Am I missing something? (I guess I
am, and that's why I'm posting to help-gnu-emacs instead of
bug-gnu-emacs)
TIA
---
Dani Moncayo
In GNU Emacs 24.0.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 2.22.0)
of 2011-02-26 on dani-P5PL2
Windowing system distributor `The X.Org Foundation', version 11.0.10900000
So you're misunderstanding the use of TAB in this case.
TAB indents, but "smartly", so it actually never really inserts a tab
(apart maybe some modes where this is the good thing to do)
What you want to do can be done with rectangle mode, so
- select the region you want
- C-x r t RET TAB
and you're done
> Am I missing something?
Yes: many new meanings of <TAB>. (I try not use it that often, so I
can't do what the documentation can: explain them.)
--
Greetings
Pete
Upgraded, adj.:
Didn't work the first time.
> So you're misunderstanding the use of TAB in this case.
> TAB indents, but "smartly", so it actually never really inserts a tab
> (apart maybe some modes where this is the good thing to do)
>
Skipping for a moment that you already showed a way to do this in
rectangle mode....
If one were to actually insert a TAB with C-q C-i... then should the
action this string describes work?:
> What I was expecting:
> - The selected lines move to the next tab-stop.
> - The region remains active, so that I can repeat the indentation
> several times in a row.
>
> What I see:
> - The selected lines are not not moved at all.
> - The region is deactivated.
>
> Please, could someone explain this? Am I missing something? (I guess I
> am, and that's why I'm posting to help-gnu-emacs instead of
> bug-gnu-emacs)
>
It certainly does seem like a bug to me. I would go ahead and report
it with M-x report-emacs-bug.
-PJ
On Fri, Mar 4, 2011 at 3:17 PM, Dani Moncayo <dmon...@gmail.com> wrote:
> What I was expecting:
> - The selected lines move to the next tab-stop.
> - The region remains active, so that I can repeat the indentation
> several times in a row.
> What I see:
> - The selected lines are not not moved at all.
> - The region is deactivated.
It certainly does seem like a bug to me. I would go ahead and reportit with M-x report-emacs-bug.
-PJ
That's the part that seemed like a bug to me: the region getting
deactivated as part of the command loop. The text *did* move when I
tried it, but in other editors it would be possible to move it by more
than one tab-stop by pressing TAB multiple times.
-PJ
Theres more strange (buggy?) behavior here.
I took the text (note flush left):
In text modes, <TAB> inserts some combination of space and tab
characters to advance point to the next tab stop (*note Tab Stops).
If the region is active and spans multiple lines, it advances the
first
character of each of those lines to the next tab stop (*note Using
Region). [...]
Then did the described action (except for turning transient-mode on)
At first it put 1 tab at start of each line
The second time it added 1 tab on 1st line,2 on second, 3 on third, 4
on fourth etc !!
> If the bug didn't exist, the region would still be deactivated as a part ofThat's the part that seemed like a bug to me: the region getting
> the command loop because you've modified the buffer.
deactivated as part of the command loop. The text *did* move when I
tried it, but in other editors it would be possible to move it by more
than one tab-stop by pressing TAB multiple times.
On Sat, Mar 5, 2011 at 21:26, Andrea Crotti <andrea....@gmail.com> wrote:
> So you're misunderstanding the use of TAB in this case.
> TAB indents, but "smartly", so it actually never really inserts a tab
> (apart maybe some modes where this is the good thing to do)
>
Based on the manual section I quoted before, What is exactly my
misunderstanding? I think it says that selecting multiple lines *in a
text mode buffer* and hitting <TAB> should produce an indentation of
every line. Isn't that right?
> What you want to do can be done with rectangle mode, so
> - select the region you want
> - C-x r t RET TAB
> and you're done
>
Yes, I know that way of indenting several lines, but IMO it's too
laborious. I'd like to have a more agile way.
--
Dani Moncayo
--
Dani Moncayo
> Based on the manual section I quoted before, What is exactly my
> misunderstanding? I think it says that selecting multiple lines *in a
> text mode buffer* and hitting <TAB> should produce an indentation of
> every line. Isn't that right?
The *scratch* buffer is not a text-mode buffer (it is meant for Elisp
code scratches, for testing programme code for GNU Emacs). Open <some
file>.txt and see again!
--
Greetings
Pete
The world would be a better place if Larry Wall had been born in
Iceland, or any other country where the native language actually has
syntax.
– Peter da Silva
My second step (after starting emacs) was to set text mode in the
scratch buffer, remember?.
I don't care about what buffer you are in, as long as you are in *text mode*.
--
Dani Moncayo
> Am 06.03.2011 um 12:47 schrieb Dani Moncayo:
>
>> Based on the manual section I quoted before, What is exactly my
>> misunderstanding? I think it says that selecting multiple lines *in a
>> text mode buffer* and hitting <TAB> should produce an indentation of
>> every line. Isn't that right?
>
>
> The *scratch* buffer is not a text-mode buffer (it is meant for Elisp
> code scratches, for testing programme code for GNU Emacs). Open <some
> file>.txt and see again!
As soon as you type M-x text-mode RET in the *scratch* buffer, it
becomes a text buffer.
--
__Pascal Bourguignon__ http://www.informatimago.com/
A bad day in () is better than a good day in {}.
As discussed in this thread this is a regression. It works in
Emacs 23.2. but not in Emacs 24.0.50 ... I filed a bug report:
24.0.50; Regression: TAB does not indent region
http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8187
> - The region is deactivated.
Regarding this issue I filed a wishlist bug:
indenting region with TAB deactivates region
http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8189
Ciao, Gregor
--
-... --- .-. . -.. ..--.. ...-.-
Thanks, let's see what the maintainers say.
--
Dani Moncayo
>> What I see:
>> - The selected lines are not not moved at all.
>> - The region is deactivated.
>>
>> Please, could someone explain this? Am I missing something? (I guess I
>> am, and that's why I'm posting to help-gnu-emacs instead of
>> bug-gnu-emacs)
The region getting deactivated is part of the design. Funny that nobody
seems to have mentioned it. Most operations that make use of the active
mark deactivate it. You have to activate it again if you want to repeat
some operation. C-xC-x is a good way of doing so.
The selected lines not moving seems to be a bug in the development
version. In the current release, 23.2, the lines are moving the first
time, but they are moving correctly a second time. So, that is buggy as
well. Sigh...
In any case, the traditional way of moving a region of text is to use
`indent-rigidly' (C-x TAB). You can give it a prefix argument, e.g.,
M-10, to say indent 10 spaces.
Cheers,
Uday
Ah, good. Thanks for the info.
The way you've mentioned works, but IMO it has two drawbacks:
- It is a bit cumbersome to type C-u _number_ C-x <TAB> each time you
want to indent a paragraph.
- It is not "interactive": i.e. Many times you don't know beforehand
the value of _number_. So,
it would be nice if you could make several indentations in a row
while seeing the new position
of the text at the end of each one.
Thus, I think it would be nice to have a way of indenting the active
region that didn't have the above drawbacks.
--
Dani Moncayo
C-u 3 C-x TAB C-x z z z z ...
indents 3 chars each time you hit z
> - It is not "interactive": i.e. Many times you don't know beforehand
> the value of _number_. So, it would be nice if you could make
> several indentations in a row while seeing the new position of the
> text at the end of each one.
If you don't know the number of chars to indent, then start with 1:
C-x TAB C-x z z z ...
It is easy to hold down `z', no?
And if you go too far, hit `C-- C-x z z z...' to come back.
Indeed, that is another solution, but IMO has it's own drawbacks:
- As shown, the indentation is made by steps of 1 space.
- If you use a prefix argument (to avoid the above problem), it
becomes cumbersome.
The complexity of this method is also higher than having a simple,
easy to type command that indents the region to the next tab stop and
can be repeated several times in a row.
--
Dani Moncayo
Thanks, Drew! (I have to find the time to learn elisp... :) )
You've implemented a solution for this problem, but what do you think
about my original question in this thread, i.e., the behavior of the
<TAB> key in text mode, in the current Emacs trunk? Do you understand
it? Does the manual describes it well?
--
Dani Moncayo
> Indeed, that is another solution, but IMO has it's own drawbacks:
> - As shown, the indentation is made by steps of 1 space.
> - If you use a prefix argument (to avoid the above problem), it
> becomes cumbersome.
>
> The complexity of this method is also higher than having a simple,
> easy to type command that indents the region to the next tab stop and
> can be repeated several times in a row.
Do you mean the the next tab stop according to tab-stop-list variable?
If the indentation of lines in the current region differs between lines,
which line should be indented to the next tab stop position? Maybe the
one with the smallest amount of indentation (excluding blank lines)?
Here's a quick example:
(defun my-region-indentation (beg end)
(let (indent)
(save-excursion
(goto-char beg)
(while (re-search-forward "^\\s-*[[:print:]]" end t)
(setq indent (min (or indent (current-indentation))
(current-indentation)))))
indent))
(defun my-indent-region-next-tab-stop (beg end)
"Indent region forward to the next tab stop."
(interactive "r")
(let* ((current (my-region-indentation beg end))
(next (catch 'answer
(dolist (i tab-stop-list 0)
(when (> i current)
(throw 'answer i))))))
(indent-rigidly beg end (- next current))))
(defun my-indent-region-previous-tab-stop (beg end)
"Indent region backward to the previous tab stop."
(interactive "r")
(let* ((current (my-region-indentation beg end))
(prev (catch 'answer
(dolist (i (reverse (append (list 0) tab-stop-list)) 0)
(when (< i current)
(throw 'answer i))))))
(indent-rigidly beg end (- prev current))))
(global-set-key [f5] #'my-indent-region-previous-tab-stop)
(global-set-key [f6] #'my-indent-region-next-tab-stop)
I haven't followed this thread. But reading your original post and trying Emacs
-Q (on Windows), I agree with you, PJ, and Le that this seems to be a bug. I
tried a few versions, none of which seem to have the currently documented
behavior:
Emacs 22 - but the behavior matches the then-documented behavior, so OK.
Emacs 23 and 24 - behavior is more or less as described except for this: the
region is deactivated, so you cannot hit TAB again to indent more (you must use
`C-x C-x' first). Le Wang already mentioned this.
I'm also not sure about the "advance...to next tab stop" thing. Different lines
in the region can get indented different amounts, especially if repeating TAB
(after C-x C-x) after the first TAB indents to align with the first
non-whitespace char of the previous line.
I suggest you file a bug. Emacs developers will let you know whether they agree
that it is a bug. If they agree, they will decide whether the behavior should
change to fit the doc, vice versa, or some combination. If they disagree, it
might still be the case that the doc could be improved to prevent
misunderstanding.
---
In general (not just for you or this thread), my advice is to not hesitate to
file a bug report. Better to discuss such things in a bug-report thread than
here. This list is for helping and getting help.
Obviously, if you are (i.e., one is) unsure what something should do then there
is a gray area, but there is no reason (IMHO) to hesitate to file a bug report.
If you have read the doc and are still unsure what the behavior should be, then
there's a good chance that at least the doc could be improved. Letting the
developers know what is unclear to you, no matter what your level, can help
everyone.
Yes, I know that way of indenting several lines, but IMO it's too
laborious. I'd like to have a more agile way.
(setq cua-enable-cua-keys 'emacs);; <kp-enter> rotates around the rectangle corners, if "RET" gets overriden(cua-selection-mode 1)
Sorry for missing your advice, Le.
Indeed your way works and it's ease to use.
Anyway, It seems that the behavior of <TAB> is broken in the trunk,
and also in Emacs 23, so that when that is fixed, we'll be able to
indent paragraphs (in text mode), the way I was expecting (and is
documented).
Thanks for your advice!
--
Dani Moncayo
> Do you mean the the next tab stop according to tab-stop-list variable?
> If the indentation of lines in the current region differs between
> lines, which line should be indented to the next tab stop position?
> Maybe the one with the smallest amount of indentation (excluding blank
> lines)? Here's a quick example:
I found that feature quite useful so I wrote a proper version. I bind it
to "C-x TAB" since this pretty much supersedes indent-rigidly. See the
command's documentation (below) for more info.
(global-set-key (kbd "C-c TAB") #'tl-indent-region)
(defun tl-region-indentation (beg end)
"Return the smallest indentation in range from BEG to END.
Blank lines are ignored."
(save-excursion
(let ((beg (progn (goto-char beg) (line-beginning-position)))
(end (progn (goto-char end) (line-end-position)))
indent)
(goto-char beg)
(while (re-search-forward "^\\s-*[[:print:]]" end t)
(setq indent (min (or indent (current-indentation))
(current-indentation))))
indent)))
(defun tl-indent-region-next-tab-stop (beg end)
(let* ((current (tl-region-indentation beg end))
(next (catch 'answer
(dolist (i tab-stop-list (or (car (last tab-stop-list)) 0))
(when (> i current)
(throw 'answer i))))))
(indent-rigidly beg end (- next current))))
(defun tl-indent-region-previous-tab-stop (beg end)
(let* ((current (tl-region-indentation beg end))
(prev (catch 'answer
(dolist (i (reverse (cons 0 tab-stop-list)) 0)
(when (< i current)
(throw 'answer i))))))
(indent-rigidly beg end (- prev current))))
(defun tl-indent-region-engine (beg end arg)
(interactive "r\nP")
(let ((current (tl-region-indentation beg end)))
(cond ((not arg)
(tl-indent-region-next-tab-stop beg end))
((eq arg '-)
(tl-indent-region-previous-tab-stop beg end))
(t
(indent-rigidly beg end (prefix-numeric-value arg))))))
(defun tl-indent-region (beg end arg)
"Indent region to a tab stop column or to a specified column.
Indent the region from BEG to END according to the command's
prefix argument ARG. If ARG is nil (i.e., there is no prefix
argument) indent the region to the next tab stop column in
`tab-stop-list'. If ARG is negative indent the region to the
previous tab stop column. If ARG is a positive or negative
integer indent the region by ARG columns (just like
`indent-rigidly' command) .
If this command is invoked by a multi-character key sequence, it
can be repeated by repeating the final character of the
sequence."
(interactive "r\nP")
(let ((repeat-message-function #'ignore))
(setq last-repeatable-command #'tl-indent-region-engine)
(repeat nil)))
(let ((repeat-message-function #'ignore))(setq last-repeatable-command #'tl-indent-region-engine)
(repeat nil)))
> Teemu, one bug in the code is that you need to call (require 'repeat)
> at the beginning, otherwise when it gets autoloaded later
> `repeat-message-function' doesn't get initialized properly because of
> the "(let ..." binding.
Thanks. I have made some other adjustments too, so here's a new version:
(defun tl-region-indentation (beg end)
"Return the smallest indentation in range from BEG to END.
Blank lines are ignored."
(save-excursion
(let ((beg (progn (goto-char beg) (line-beginning-position)))
indent)
(goto-char beg)
(while (re-search-forward "^\\s-*[[:print:]]" end t)
(setq indent (min (or indent (current-indentation))
(current-indentation))))
indent)))
(defun tl-indent-region-engine (beg end arg)
"Back-end function for `tl-indent-region'."
(interactive "r\nP")
(let* ((beg (save-excursion (goto-char beg) (line-beginning-position)))
(current (tl-region-indentation beg end))
(indent (cond ((not arg)
(- (catch 'answer
(dolist (col tab-stop-list (1+ current))
(when (> col current)
(throw 'answer col))))
current))
((eq arg '-)
(- (catch 'answer
(dolist (col (reverse tab-stop-list) 0)
(when (< col current)
(throw 'answer col))))
current))
(t (prefix-numeric-value arg)))))
(indent-rigidly beg end indent)))
(defun tl-indent-region (beg end arg)
"Indent region to a tab stop column or to a specified column.
Indent the region from BEG to END according to the command's
prefix argument ARG. If ARG is nil (i.e., there is no prefix
argument) indent the region to the next tab stop column in
`tab-stop-list'. If ARG is negative indent the region to the
previous tab stop column. If ARG is a positive or negative
integer indent the region by ARG columns (just like
`indent-rigidly' command) .
If this command is invoked by a multi-character key sequence, it
can be repeated by repeating the final character of the
sequence."
(interactive "r\nP")
(require 'repeat)
You're welcome. It dawned on me one day, and I've used it a lot ever since.
Actually, I define a repeatabilizer function like this:
(defun bmkp-repeat-command (command)
"Repeat COMMAND."
(let ((repeat-message-function 'ignore))
(setq last-repeatable-command command)
(repeat nil)))
Then I pass any number of ordinary, non-repeatable commands to that, to create
repeatable versions of them. Then I bind the repeatable ones. Example (from
Bookmark+):
(defun bmkp-next-bookmark-repeat (arg) ; `C-x p right', `C-x p f'
"Jump to the Nth-next bookmark in the bookmark navigation list.
This is a repeatable version of `bmkp-next-bookmark'.
N defaults to 1, meaning the next bookmark.
Plain `C-u' means start over at the first bookmark (and no repeat)."
(interactive "P")
(require 'repeat)
(bmkp-repeat-command 'bmkp-next-bookmark))
(define-key bookmark-map [right] 'bmkp-next-bookmark-repeat)
(define-key bookmark-map "f" 'bmkp-next-bookmark-repeat)
You can put a repeatable command on a prefix key, to save keys. For example, in
Bookmark+ `bookmark-map' is bound to the prefix key `C-x p' - it is available by
default for all bookmark commands.
There are several repeatable commands on this prefix key: `C-x p f', `C-x p
right', `C-x p down', etc. So you can use `C-x p f f f f f f f'... to cycle one
thing, `C-x p down down down'... to cycle another, etc., and still have lots of
other, non-repeatable keys on the same prefix `C-x p'.
You can even put (repeatable) mouse-wheel rotations on a prefix key:
(define-key bookmark-map (vector (list mouse-wheel-up-event))
'bmkp-next-bookmark-this-buffer-repeat)
Using a common prefix key gives users a quick way to see all of the related
default key bindings: `C-x p C-h'. (They can always define shortcut keys if
they want.)
Here is an example where `s' is both a prefix key and a suffix for the prefix
key (different keymap here):
(defun bmkp-bmenu-change-sort-order-repeat (arg) ; `s s'... in bookmark list
"Cycle to the next sort order.
With a prefix arg, reverse current sort order.
This is a repeatable version of `bmkp-bmenu-change-sort-order'."
(interactive "P")
(require 'repeat)
(bmkp-repeat-command 'bmkp-bmenu-change-sort-order))
(define-key bookmark-bmenu-mode-map "ss"
'bmkp-bmenu-change-sort-order-repeat)
Here is a related thread based on this idea of using a prefix key as its own
suffix:
http://lists.gnu.org/archive/html/emacs-devel/2009-08/msg01153.html
Yes, repeat.el needs to be loaded.
Teemu presumably got the code from my prior message, where the repeatable
command `incremental-tab' does indeed call (require 'repeat). He neglected to
copy that part. You've pointed out one reason it's needed.
Indeed, it sounds like a good improvement to the behavior of C-x TAB.
Maybe you could propose it for inclusion via M-x report-emacs-bug.
Stefan
Indeed, I will. Others may find it useful too.
> Better to discuss such things in a bug-report thread than
> here. This list is for helping and getting help.
I've enjoyed and learned about at least two commands
from this thread so this thread *is* helping others.
Its amazing to me... I've used emacs starting with Gosling's
(CCA) emacs and moving to GNU when it was first released
and I bet I know (or am aware of) far less than half of
what emacs can do out of the box.
pedz
Yes, of course. I meant only that the discussion of the bug itself is
appropriate for the bug list. As proof, note that the bug as finally reported
did not mention the particular doc section that is problematic etc., so the bug
thread eventually pointed to this help-gnu-emacs thread for clarification.
> Its amazing to me... I've used emacs starting with Gosling's
> (CCA) emacs and moving to GNU when it was first released
> and I bet I know (or am aware of) far less than half of
> what emacs can do out of the box.
Me too, on all accounts. We are all newbies wrt some things.