Subject: bug#8196: 23.1; Feature request with code: "C-x TAB" to understand tab-stop-list

From: Teemu Likonen <[email-masked]>
Date: Sun, 14 Jul 2013 17:41:14 +0300

Stefan Monnier [2013-07-13 16:02:35 -04:00] wrote:

> This said, there's another good default behavior for non-prefixed C-x
> TAB which is to enter an interactive loop that lets the user move the
> block left/right with the cursor keys. I think this would be a more
> useful change.

Sounds good. I wrote a quick example command "tl-edit-indentation". It
works like "indent-rigidly" expect that when there is no prefix argument
it sets a temporary repeatable overlay keyboard with the cursor keys for
editing indentation. Plain <left> and <right> would move by 1 column and
<S-left> and <S-right> move by tab stops. I like this feature.

(defun tl-region-indentation (beg end)
  "Return the smallest indentation in range from BEG to END.
Blank lines are ignored."
  (save-excursion
    (save-match-data
      (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-edit-indentation (start end arg)
  (interactive "r\nP")
  (if arg
      (indent-rigidly start end (prefix-numeric-value arg))
    (message "Edit region indentation with <left>, <right>, <S-left> \
and <S-right>.")
    (set-temporary-overlay-map

     (let ((map (make-sparse-keymap)))
       (define-key map (kbd "<left>")
         (lambda () (interactive)
           (indent-rigidly (region-beginning) (region-end) -1)))

       (define-key map (kbd "<right>")
         (lambda () (interactive)
           (indent-rigidly (region-beginning) (region-end) 1)))

       (define-key map (kbd "<S-right>")
         (lambda () (interactive)
           (let* ((beg (region-beginning))
                  (end (region-end))
                  (current (tl-region-indentation beg end))
                  (next (catch 'answer
                          (dolist (col tab-stop-list (1+ current))
                            (when (> col current)
                              (throw 'answer col))))))
             (indent-rigidly beg end (- next current)))))

       (define-key map (kbd "<S-left>")
         (lambda () (interactive)
           (let* ((beg (region-beginning))
                  (end (region-end))
                  (current (tl-region-indentation beg end))
                  (next (catch 'answer
                          (dolist (col (reverse tab-stop-list) 0)
                            (when (< col current)
                              (throw 'answer col))))))
             (indent-rigidly beg end (- next current)))))
       map)
     t)))