Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

tab-to-tab-stop /backwards/

22 views
Skip to first unread message

Charles R Martin

unread,
Mar 31, 2002, 8:40:45 PM3/31/02
to

I _know_ this just has to be easy and I'm just having a brain-fault
finding it...

I have (reasonably enough) 'tab-to-tab-stop' bound to TAB.

I would like to have a 'backward-tab-to-tab-stop' to bind to
SHIFT-TAB.

I can't find one, or anything that can be made to easily serve. I
know this can't possibly be because no one else has ever needed it, so
I assume I'm just missing the right elisp function, but I sure can't
find one.

Help?

Please?

--
I once complained to my father that I didn't seem to be able to do things the
same way other people did. Dad's advice? 'Margo, don't be a sheep. People hate
sheep. They eat sheep.' -- Margo Kaufmann
_______________________________________________________________________________
Charles R (Charlie) Martin Broomfield, CO 40N 105W

lawrence mitchell

unread,
Mar 31, 2002, 9:03:12 PM3/31/02
to
Charles R. Martin wrote:
> I _know_ this just has to be easy and I'm just having a brain-fault
> finding it...
>
> I have (reasonably enough) 'tab-to-tab-stop' bound to TAB.
>
> I would like to have a 'backward-tab-to-tab-stop' to bind to
> SHIFT-TAB.
>
> I can't find one, or anything that can be made to easily serve. I
> know this can't possibly be because no one else has ever needed it,
> so I assume I'm just missing the right elisp function, but I sure
> can't find one.
>
> Help?
>
> Please?

I think the following function _almost_ does what you want, it doesn't
get back to column zero though, but its too late for me to try and
guess why. If you look, you'll see its very similar to
`tab-to-tab-stop' :-)

(defun backward-tab-to-tab-stop ()
"Go to the previous tab-stop.
This (almost) does the reverse of `tab-to-tab-stop'."
(interactive)
(and abbrev-mode (= (char-syntax (preceding-char)) ?w)
(expand-abbrev))
(let ((tabs (reverse tab-stop-list)))
(while (and tabs (<= (current-column) (car tabs)))
(setq tabs (cdr tabs)))
(if tabs
(let ((opoint (point)))
(skip-chars-backward " \t")
(delete-region (point) opoint)
(indent-to (car tabs)))
(insert ?\ ))))


--
lawrence mitchell <we...@gmx.li>

Hey!! Let's watch the' ELEVATOR go UP and DOWN at th' HILTON HOTEL!!

Charles R Martin

unread,
Apr 1, 2002, 11:46:01 AM4/1/02
to
lawrence mitchell <we...@gmx.li> writes:

> Charles R. Martin wrote:
> > I _know_ this just has to be easy and I'm just having a brain-fault
> > finding it...
> >
> > I have (reasonably enough) 'tab-to-tab-stop' bound to TAB.
> >
> > I would like to have a 'backward-tab-to-tab-stop' to bind to
> > SHIFT-TAB.
> >
> > I can't find one, or anything that can be made to easily serve. I
> > know this can't possibly be because no one else has ever needed it,
> > so I assume I'm just missing the right elisp function, but I sure
> > can't find one.
> >
> > Help?
> >
> > Please?
>
> I think the following function _almost_ does what you want, it doesn't
> get back to column zero though, but its too late for me to try and
> guess why. If you look, you'll see its very similar to
> `tab-to-tab-stop' :-)
>

If I have to code one myself, I think it'd be better (at least easier)
to use move-to-tab-stop as a model --

;; Untested code --
;; loop to find greatest tab stop less than point
(let (tabs (reverse (tab-stop-list)))
(while (and (<= (point) (car tabs)) tabs)
(setq tabs (cdr tabs)))
;; if tabs not nil, car tabs is that column
;; so go there
(cond (tabs (move-to-column (car tabs) t))
(nil (move-to-column 0 t))))

using the FORCE parameter of move-to-column to get EMACS to take care
of the tab characters (if any).

But it _seems_ like something that would be a primitive, and I hate to
recode something that some elisp weenie is going to point out is a
primitive six months from now.

lawrence mitchell

unread,
Apr 1, 2002, 12:00:36 PM4/1/02
to
Charles R. Martin wrote:

[...] backwards tab-to-tab-stop?

> If I have to code one myself, I think it'd be better (at least
> easier) to use move-to-tab-stop as a model --
>

I don't know, this one seems to work for me now:

(defun backward-tab-to-tab-stop ()
"Go to the previous tab-stop.

This does the reverse of `tab-to-tab-stop'."


(interactive)
(and abbrev-mode (= (char-syntax (preceding-char)) ?w)
(expand-abbrev))

(let ((tabs (reverse (add-to-list 'tab-stop-list 0))))


(while (and tabs (<= (current-column) (car tabs)))
(setq tabs (cdr tabs)))
(if tabs
(let ((opoint (point)))
(skip-chars-backward " \t")
(delete-region (point) opoint)
(indent-to (car tabs)))
(insert ?\ ))))

Though it doesn't move over lines, it does get to column zero.

[...] use move-to-tab-stop instead

I spose so, you're right that it seems that there ought to be a
builtin/predefined function to do this.
--
lawrence mitchell <we...@gmx.li>

Charles R Martin

unread,
Apr 1, 2002, 3:06:25 PM4/1/02
to
lawrence mitchell <we...@gmx.li> writes:

okay, so here's what I got. Notice that I had to reverse the order of
the while test to take advantage of short-circuiting, that (point) is
1 greater than the current column so I needed the (- (point) 1).

(defun backward-move-to-tab-stop ()
"Move point to previous (greatest less than point) tab-stop. The
variable `tab-stop-list' is a list of columns at which there are tab
stops. Use \\[edit-tab-stops] to edit tab stops interactively. This
is a move-backward version of \\[move-to-tab-stop]."
(interactive)


;; loop to find greatest tab stop less than point

(let ((tabs (reverse tab-stop-list)))
(while (and tabs (<= (- (point) 1) (car tabs)))
(setq tabs (cdr tabs)))
(princ tabs)


;; if tabs not nil, car tabs is that column
;; so go there
(cond (tabs (move-to-column (car tabs) t))

(t (move-to-column 0 t)))))


Anyone have comments on how it could be done better?

lawrence mitchell

unread,
Apr 1, 2002, 4:52:05 PM4/1/02
to
Charles R. Martin wrote:
> (while (and tabs (<= (- (point) 1) (car tabs)))
^^^^^^^^^^^
Doesn't this want to be "(current-column)"?

Since apart from in the first line (point) will almost always be greater
than (car tabs), hence you'll end up moving to the last tab stop on
the current line.
--
lawrence mitchell <we...@gmx.li>

I'm not available for comment..

Charles R Martin

unread,
Apr 1, 2002, 5:42:07 PM4/1/02
to
lawrence mitchell <we...@gmx.li> writes:

> Charles R. Martin wrote:
> > (while (and tabs (<= (- (point) 1) (car tabs)))
> ^^^^^^^^^^^
> Doesn't this want to be "(current-column)"?

Yes ... damned if I know why I didn't find that when I searched for
it. Thanks.

>
> Since apart from in the first line (point) will almost always be greater
> than (car tabs), hence you'll end up moving to the last tab stop on
> the current line.

Nope -- I've tested that code, it works. But note that the let loads
tabs with (reverse tab-stop-list).

Charles R Martin

unread,
Apr 1, 2002, 7:05:12 PM4/1/02
to
lawrence mitchell <we...@gmx.li> writes:

> Charles R. Martin wrote:
> > (while (and tabs (<= (- (point) 1) (car tabs)))
> ^^^^^^^^^^^
> Doesn't this want to be "(current-column)"?
>
> Since apart from in the first line (point) will almost always be greater
> than (car tabs), hence you'll end up moving to the last tab stop on
> the current line.

Okay, I've just posted this version to gnu.eamcs.sources:

;;; -*- emacs-lisp -*- Time-stamp: <2002-04-01 16:47>
;;; --------------------------------------------------
;;;
;;; Abstract:
;;; This routine provides something I would swear would be a
;;; primitive: moving _backwards_ to a tab stop. It's intended to
;;; allow binding it to SHIFT-TAB when TAB is bound to
;;; tab-to-tab-stop.
;;;
;;; Author: Charles R Martin <crma...@indra.com>
;;; Keyword: convenience
;;;

;;; Copyright (C) 2002 Charles R Martin

;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU General Public License as
;;; published by the Free Software Foundation; either version 2 of
;;; the License, or (at your option) any later version.

;;; This program is distributed in the hope that it will be
;;; useful, but WITHOUT ANY WARRANTY; without even the implied
;;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;; PURPOSE. See the GNU General Public License for more details.

;;; You should have received a copy of the GNU General Public
;;; License along with this program; if not, write to the Free
;;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
;;; MA 02111-1307 USA
;;;
;;; History:
;;; Written 2002-04-01 16:30
;;;
;;; with thanks to lawrence mitchell <we...@gmx.li> for pointing out
;;; current-column, which I had somehow missed.

(defun backward-move-to-tab-stop ()
"Move point to previous (greatest less than point) tab-stop. The
variable `tab-stop-list' is a list of columns at which there are tab
stops. Use \\[edit-tab-stops] to edit tab stops interactively. This
is a move-backward version of \\[move-to-tab-stop]."
(interactive)
;; loop to find greatest tab stop less than point
(let ((tabs (reverse tab-stop-list)))

(while (and tabs (<= (current-column) (car tabs)))
(setq tabs (cdr tabs)))

;; if tabs not nil, car tabs is that column

;; Otherwise, column should be 0.
;; So go there.

(cond (tabs (move-to-column (car tabs) t))
(t (move-to-column 0 t)))))

(provide 'backward-tab)

0 new messages