unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* Re: Browse skeleton positions
       [not found] <87vfqnygi7.fsf@newsguy.com>
@ 2003-10-17 20:42 ` Stefan Monnier
  2003-10-18 17:58   ` Ian Zimmerman
  0 siblings, 1 reply; 7+ messages in thread
From: Stefan Monnier @ 2003-10-17 20:42 UTC (permalink / raw)


>     (define-key kmap [ return ] 'skeleton-position-exit)

Please use [?\C-m] (or "\C-m"), unless you really mean that this binding
should not work in a tty.

> (defsubst turn-on-skeleton-position-mode ()

I recommend you use `defun' here, since it's unlikely that the advantages
of defsubst will outweigh its disadvantages in this case.

> (defvar skeleton-position-marker-list nil
>   "Global list of markers pointing to skeleton positions.")
> (make-variable-buffer-local 'skeleton-position-marker-list)

"Global" for a defvarred variable in elisp generally means "non-local
to any buffer".

> (defvar skeleton-position-push-mark nil
>   "\\<skeleton-position-mode-map>\
> When set, causes \\[skeleton-position-next] and \\[skeleton-position-prev] \
> in Skeleton Position mode to push a mark at point.")

Instead of using this state variable, you could maybe push the mark
directly when you enter skeleton-position-mode ?

> (defvar skeleton-position-current nil
>   "\\<skeleton-position-mode-map>\
> The last position visited by \\[skeleton-position-next] or \\[skeleton-position-prev] \
> in Skeleton Position mode, as a pointer into `skeleton-position-marker-list'.")

Maybe it would be better to just use (point) instead, and when you do
`next' or `prev', go through the list looking for the nearest marker in the
requested direction ?

> (unless (featurep 'skelposn)
>   (add-hook 'skeleton-end-hook
>             (lambda ()
>               (setq skeleton-position-marker-list
>                     (append
>                      (nreverse
>                       (mapcar
>                        (lambda (p) (set-marker (make-marker) p))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                         'copy-marker

>                        skeleton-positions))
>                      skeleton-position-marker-list))
>               (when (and skeleton-position-marker-list
>                          (null skeleton-position-current))
>                 (setq skeleton-position-push-mark t))))

It's generally preferable to only add function symbols onto hooks, so it's
easier to remove and so there's less/no risk of adding it a second time.

As for the behavior, the above has the nasty side effect that just loading
"skelposn" into your Emacs will cause all your skeleton positions to
accumulate in the form of markers (at least until you finally call
skeleton-position-exit which will likely be never if you don't actually use
skelposn).  This can lead to a significant slowdown because of the way
markers are implemented.

Maybe it's better to process skeleton-positions only when requested,
i.e. in skeleton-position-mode (or maybe in skeleton-position-next
if you want to do it JIT-style).

How about a less in-yuor-face mode that lets you edit the text at the same
time as you navigate between the different markers ?


        Stefan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Browse skeleton positions
  2003-10-17 20:42 ` Browse skeleton positions Stefan Monnier
@ 2003-10-18 17:58   ` Ian Zimmerman
  2003-10-19 23:36     ` Stefan Monnier
  0 siblings, 1 reply; 7+ messages in thread
From: Ian Zimmerman @ 2003-10-18 17:58 UTC (permalink / raw)



>> (define-key kmap [ return ] 'skeleton-position-exit)

Stefan> Please use [?\C-m] (or "\C-m"), unless you really mean that this
Stefan> binding should not work in a tty.

Good point.

>> (defsubst turn-on-skeleton-position-mode ()

Stefan> I recommend you use `defun' here, since it's unlikely that the
Stefan> advantages of defsubst will outweigh its disadvantages in this
Stefan> case.

I think both advantages and disadvantages are small here, but I'll take
your recommendation.

>> (defvar skeleton-position-marker-list nil "Global list of markers
>> pointing to skeleton positions.")  (make-variable-buffer-local
>> 'skeleton-position-marker-list)

Stefan> "Global" for a defvarred variable in elisp generally means
Stefan> "non-local to any buffer".

Yes, this is a typo; I have changed the code, but not the doc :-)
Thanks for spotting it.

>> (defvar skeleton-position-push-mark nil
>> "\\<skeleton-position-mode-map>\ When set, causes
>> \\[skeleton-position-next] and \\[skeleton-position-prev] \ in
>> Skeleton Position mode to push a mark at point.")

Stefan> Instead of using this state variable, you could maybe push the
Stefan> mark directly when you enter skeleton-position-mode ?

Yes, but it isn't exactly the same.  That way it would be pushed even if
users never move to any of the points.

>> (defvar skeleton-position-current nil
>> "\\<skeleton-position-mode-map>\ The last position visited by
>> \\[skeleton-position-next] or \\[skeleton-position-prev] \ in
>> Skeleton Position mode, as a pointer into
>> `skeleton-position-marker-list'.")

Stefan> Maybe it would be better to just use (point) instead, and when
Stefan> you do `next' or `prev', go through the list looking for the
Stefan> nearest marker in the requested direction ?

Hmmmm.  Again, interesting suggestion, but the behavior could be
significantly different in case there are multiple overlapping skeletons.

Stefan> It's generally preferable to only add function symbols onto
Stefan> hooks, so it's easier to remove and so there's less/no risk of
Stefan> adding it a second time.

Stefan> As for the behavior, the above has the nasty side effect that
Stefan> just loading "skelposn" into your Emacs will cause all your
Stefan> skeleton positions to accumulate in the form of markers (at
Stefan> least until you finally call skeleton-position-exit which will
Stefan> likely be never if you don't actually use skelposn).  This can
Stefan> lead to a significant slowdown because of the way markers are
Stefan> implemented.

Note the kill-buffer-hook.

Stefan> Maybe it's better to process skeleton-positions only when
Stefan> requested, i.e. in skeleton-position-mode (or maybe in
Stefan> skeleton-position-next if you want to do it JIT-style).

Won't do.  Much editing can happen between inserting the skeleton and
starting to browse, and then the positions will be all wrong.  In
particular, I fully intend to keep _multiple_ preceding skeletons'
positions available until explicitly discarded.

Stefan> How about a less in-yuor-face mode that lets you edit the text
Stefan> at the same time as you navigate between the different markers ?

But then you'd need more complicated, harder to type (and to retype, in
particular) keybindings.  This is a general dilemma which I have
resolved for myself in favor of special modes like this one.  See also
wmanip.el which I have posted some time ago, similar idea.

-- 
Wer Schoenheit angeschaut mit Augen, hat dem Tode schon Anheim gegeben.
Von Platen.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Browse skeleton positions
  2003-10-18 17:58   ` Ian Zimmerman
@ 2003-10-19 23:36     ` Stefan Monnier
  2003-10-30 23:57       ` Ian Zimmerman
  0 siblings, 1 reply; 7+ messages in thread
From: Stefan Monnier @ 2003-10-19 23:36 UTC (permalink / raw)


Stefan> Maybe it would be better to just use (point) instead, and when
Stefan> you do `next' or `prev', go through the list looking for the
Stefan> nearest marker in the requested direction ?

> Hmmmm.  Again, interesting suggestion, but the behavior could be
> significantly different in case there are multiple overlapping skeletons.

Darn!

Stefan> As for the behavior, the above has the nasty side effect that
Stefan> just loading "skelposn" into your Emacs will cause all your
Stefan> skeleton positions to accumulate in the form of markers (at
Stefan> least until you finally call skeleton-position-exit which will
Stefan> likely be never if you don't actually use skelposn).  This can
Stefan> lead to a significant slowdown because of the way markers are
Stefan> implemented.

> Note the kill-buffer-hook.

But that's too late.  The hook is actually pretty useless because
you're kill markers that will be killed by `kill-buffer' anyway
and you're setting variables to nil which will be destroyed by
`kill-buffer' as well.

> Won't do.  Much editing can happen between inserting the skeleton and
> starting to browse, and then the positions will be all wrong.  In
> particular, I fully intend to keep _multiple_ preceding skeletons'
> positions available until explicitly discarded.

Well, then.  Maybe the "many markers" will not be a real problem (it
typically only shows up once you have hundreds of markers in the current
buffer, so maybe it won't affect your code in practice).  Otherwise, you
might want to put an upper-limit, maybe using a ring.

Stefan> How about a less in-your-face mode that lets you edit the text
Stefan> at the same time as you navigate between the different markers ?

> But then you'd need more complicated, harder to type (and to retype, in
> particular) keybindings.  This is a general dilemma which I have
> resolved for myself in favor of special modes like this one.  See also
> wmanip.el which I have posted some time ago, similar idea.

You could maybe have an alternate minor mode, providing the
same bindings but under a prefix key, so users can choose between
the two styles.


        Stefan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Browse skeleton positions
  2003-10-19 23:36     ` Stefan Monnier
@ 2003-10-30 23:57       ` Ian Zimmerman
  2003-10-31 17:28         ` Stefan Monnier
  0 siblings, 1 reply; 7+ messages in thread
From: Ian Zimmerman @ 2003-10-30 23:57 UTC (permalink / raw)



Stefan> Well, then.  Maybe the "many markers" will not be a real problem
Stefan> (it typically only shows up once you have hundreds of markers in
Stefan> the current buffer, so maybe it won't affect your code in
Stefan> practice).  Otherwise, you might want to put an upper-limit,
Stefan> maybe using a ring.

Stefan> How about a less in-your-face mode that lets you edit the text
Stefan> at the same time as you navigate between the different markers ?

Ian> But then you'd need more complicated, harder to type (and to
Ian> retype, in particular) keybindings.  This is a general dilemma
Ian> which I have resolved for myself in favor of special modes like
Ian> this one.  See also wmanip.el which I have posted some time ago,
Ian> similar idea.

Stefan> You could maybe have an alternate minor mode, providing the same
Stefan> bindings but under a prefix key, so users can choose between the
Stefan> two styles.

OK, here's the latest - does it address some of the concerns?

;;; skelposn.el --- browse skeleton positions after insertion
;; Copyright (C) Ian Zimmerman, October 2003
;; Terms: GNU General Public License, Version 2

(defconst skeleton-position-mode-map
  (let ((kmap (make-sparse-keymap)))
    (suppress-keymap kmap)
    (define-key kmap "q" 'turn-off-skeleton-position-mode)
    (define-key kmap "\C-m" 'skeleton-position-exit)
    (define-key kmap "n" 'skeleton-position-next)
    (define-key kmap "p" 'skeleton-position-prev)
    (define-key kmap "a" 'skeleton-position-first)
    (define-key kmap "z" 'skeleton-position-last)
    kmap)
  "Keymap used in Skeleton Position mode.")

(defconst skeleton-position-carpal-mode-map
  (let ((kmap (make-sparse-keymap)))
    (define-key kmap "\C-c+q" 'turn-off-skeleton-position-carpal-mode)
    (define-key kmap "\C-c+\C-m" 'skeleton-position-carpal-exit)
    (define-key kmap "\C-c+n" 'skeleton-position-carpal-next)
    (define-key kmap "\C-c+p" 'skeleton-position-carpal-prev)
    (define-key kmap "\C-c+a" 'skeleton-position-carpal-first)
    (define-key kmap "\C-c+z" 'skeleton-position-carpal-last)
    kmap)
  "Keymap used in Skeleton Position Carpal mode.")

(defvar skeleton-position-max-list-length 50
  "*How many markers per buffer to keep in skeleton position mode.
If nil or negative, the lists of markers are allowed to grow
without limit, which can slow down Emacs dramatically.")

\f

;;;###autoload
(define-minor-mode skeleton-position-mode
  "Set or toggle the Skeleton Position minor mode.
\\<skeleton-position-mode-map>  This mode provides an interface to
browse the list of interesting position after a skeleton is inserted.

\\[skeleton-position-next] - Move to the next marker in `skeleton-position-marker-list'.
\\[skeleton-position-prev] - Move to the previous marker in `skeleton-position-marker-list'.
\\[skeleton-position-first] - Move to the first marker in `skeleton-position-marker-list'.
\\[skeleton-position-last] - Move to the last marker in `skeleton-position-marker-list'.
\\[skeleton-position-exit] - Clean up old skeleton positions and exit Skeleton Position mode."
  nil " SkelPosn" skeleton-position-mode-map)

;;;###autoload
(defun turn-on-skeleton-position-mode ()
  "Turn on the Skeleton Position minor mode."
  (interactive)
  (skeleton-position-mode 1))

(defun turn-off-skeleton-position-mode ()
  "Turn off the Skeleton Position minor mode."
  (interactive)
  (skeleton-position-mode 0))

(defvar skeleton-position-marker-list nil
  "List of markers pointing to skeleton positions in a buffer.")

(make-variable-buffer-local 'skeleton-position-marker-list)

(defvar skeleton-position-push-mark nil
  "\\<skeleton-position-mode-map>\
When set, causes \\[skeleton-position-next] and \\[skeleton-position-prev] \
in Skeleton Position mode to push a mark at point.")

(make-variable-buffer-local 'skeleton-position-push-mark)

(defvar skeleton-position-current nil
  "\\<skeleton-position-mode-map>\
The last position visited by \\[skeleton-position-next] or \\[skeleton-position-prev] \
in Skeleton Position mode, as a pointer into `skeleton-position-marker-list'.")

(make-variable-buffer-local 'skeleton-position-current)

(defun skeleton-end-hook-skelposn ()
  (setq skeleton-position-marker-list
        (append
         (nreverse
          (mapcar
           (lambda (p) (copy-marker p t))
           skeleton-positions))
         skeleton-position-marker-list))
  (let ((l (length skeleton-position-marker-list)))
    (when (and (integerp skeleton-position-max-list-length)
               (>= skeleton-position-max-list-length 0)
               (< skeleton-position-max-list-length l))
      (let* ((rest-length (- l skeleton-position-max-list-length))
             (rest
              (nthcdr
               skeleton-position-max-list-length
               skeleton-position-marker-list))
             (head (nbutlast skeleton-position-marker-list rest-length)))
        (when (and (consp skeleton-position-current)
                   (memq (car skeleton-position-current) rest))
          (setq skeleton-position-current nil))
        (mapcar (lambda (m) (set-marker m nil)) rest)
        (setq skeleton-position-marker-list head))))
  (when (and skeleton-position-marker-list
             (null skeleton-position-current))
    (setq skeleton-position-push-mark t)))  

(unless (featurep 'skelposn)
  (add-hook 'skeleton-end-hook 'skeleton-end-hook-skelposn))

(defun skeleton-position-next (&optional n)
  "Move to the next marker in `skeleton-position-marker-list'.

With an argument N, move to the Nth next marker on the list,
after `skeleton-position-current' instead.
If N is zero or negative, move to the Nth previous marker on the list.
The first call after a skeleton is inserted pushes a mark before moving."
  (interactive "p")
  (if (< n 0) (skeleton-position-prev n)
    (unless skeleton-position-current
      (setq skeleton-position-current (last skeleton-position-marker-list)))
    (while (> n 0)
      (while (and skeleton-position-current
                  (cdr skeleton-position-current)
                  (> n 0))
        (setq skeleton-position-current (cdr skeleton-position-current)
              n (1- n)))
      (when (> n 0)
        (setq n (1- n)
              skeleton-position-current skeleton-position-marker-list)))
    (when (null skeleton-position-current) (error "No more skeleton positions"))
    (when skeleton-position-push-mark
      (when (/= (point) (car skeleton-position-current)) (push-mark))
      (setq skeleton-position-push-mark nil))
    (goto-char (car skeleton-position-current))))

(defun skeleton-position-prev (&optional n)
  "Move to the previous marker in `skeleton-position-marker-list'.

With an argument N, move to the Nth previous marker on the list,
before `skeleton-position-current' instead.
If N is zero or negative, move to the Nth next marker on the list.
The first call after a skeleton is inserted pushes a mark before moving."
  (interactive "p")
  (if (< n 0) (skeleton-position-next n)
    (unless skeleton-position-current
      (setq skeleton-position-current skeleton-position-marker-list))
    (setq skeleton-position-marker-list (nreverse skeleton-position-marker-list))
    (unwind-protect
        (while (> n 0)
          (while (and skeleton-position-current
                      (cdr skeleton-position-current)
                      (> n 0))
            (setq skeleton-position-current (cdr skeleton-position-current)
                  n (1- n)))
          (when (> n 0)
            (setq n (1- n)
                  skeleton-position-current skeleton-position-marker-list)))
      (setq skeleton-position-marker-list (nreverse skeleton-position-marker-list)))
    (when (null skeleton-position-current) (error "No more skeleton positions"))
    (when skeleton-position-push-mark
      (when (/= (point) (car skeleton-position-current)) (push-mark))
      (setq skeleton-position-push-mark nil))
    (goto-char (car skeleton-position-current))))

(defun skeleton-position-first ()
  "Move to the first marker in `skeleton-position-marker-list'."
  (interactive)
  (setq skeleton-position-current skeleton-position-marker-list)
  (when (null skeleton-position-current) (error "No more skeleton positions"))
  (when skeleton-position-push-mark
    (when (/= (point) (car skeleton-position-current)) (push-mark))
    (setq skeleton-position-push-mark nil))
  (goto-char (car skeleton-position-current)))  

(defun skeleton-position-last ()
  "Move to the last marker in `skeleton-position-marker-list'."
  (interactive)
  (setq skeleton-position-current (last skeleton-position-marker-list))
  (when (null skeleton-position-current) (error "No more skeleton positions"))
  (when skeleton-position-push-mark
    (when (/= (point) (car skeleton-position-current)) (push-mark))
    (setq skeleton-position-push-mark nil))
  (goto-char (car skeleton-position-current)))  

(defun skeleton-position-cleanup ()
  (when skeleton-position-current
    (let ((rest (cdr skeleton-position-current)))
      (setcdr skeleton-position-current nil)
      (setq skeleton-position-current nil)
      (mapcar (lambda (m) (set-marker m nil)) skeleton-position-marker-list)
      (setq skeleton-position-marker-list rest))))  

(defun skeleton-position-exit ()
  "Clean up old skeleton positions and exit Skeleton Position mode."
  (interactive)
  (skeleton-position-cleanup)
  (turn-off-skeleton-position-mode))

\f

;;;###autoload
(define-minor-mode skeleton-position-carpal-mode
  "Set or toggle the Skeleton Position Carpal minor mode.
\\<skeleton-position-carpal-mode-map> This mode provides an interface to
browse the list of interesting position after a skeleton is inserted.
It is like `skeleton-position-mode', but does not rebind any normal
editing keystrokes.

\\[skeleton-position-carpal-next] - Move to the next marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-prev] - Move to the previous marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-first] - Move to the first marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-last] - Move to the last marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-exit] - Clean up old skeleton positions and exit Skeleton Position Carpal mode."
  nil " SkelCarp" skeleton-position-carpal-mode-map)

(defalias 'skeleton-position-carpal-next 'skeleton-position-next)
(defalias 'skeleton-position-carpal-prev 'skeleton-position-prev)
(defalias 'skeleton-position-carpal-first 'skeleton-position-first)
(defalias 'skeleton-position-carpal-last 'skeleton-position-last)

;;;###autoload
(defun turn-on-skeleton-position-carpal-mode ()
  "Turn on the Skeleton Position minor mode."
  (interactive)
  (skeleton-position-carpal-mode 1))

(defun turn-off-skeleton-position-carpal-mode ()
  "Turn off the Skeleton Position minor mode."
  (interactive)
  (skeleton-position-carpal-mode 0))

(defun skeleton-position-carpal-exit ()
  "Clean up old skeleton positions and exit Skeleton Position Carpal mode."
  (interactive)
  (skeleton-position-cleanup)
  (turn-off-skeleton-position-carpal-mode))

\f
;;;###autoload
(defun skeleton-position-reset ()
  "Clean up all saved skeleton positions."
  (interactive)
  (mapcar (lambda (m) (set-marker m nil)) skeleton-position-marker-list)
  (setq skeleton-position-marker-list nil)
  (setq skeleton-position-current nil))

(provide 'skelposn)

;;; skelposn.el ends here


-- 
"Rap music is our punishment for neglecting music education."
An anonymous teacher

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Browse skeleton positions
  2003-10-30 23:57       ` Ian Zimmerman
@ 2003-10-31 17:28         ` Stefan Monnier
  2003-11-02 16:10           ` Ian Zimmerman
  0 siblings, 1 reply; 7+ messages in thread
From: Stefan Monnier @ 2003-10-31 17:28 UTC (permalink / raw)


> (defconst skeleton-position-mode-map
>   (let ((kmap (make-sparse-keymap)))
>     (suppress-keymap kmap)
>     (define-key kmap "q" 'turn-off-skeleton-position-mode)
>     (define-key kmap "\C-m" 'skeleton-position-exit)
>     (define-key kmap "n" 'skeleton-position-next)
>     (define-key kmap "p" 'skeleton-position-prev)
>     (define-key kmap "a" 'skeleton-position-first)
>     (define-key kmap "z" 'skeleton-position-last)
>     kmap)
>   "Keymap used in Skeleton Position mode.")

> (defconst skeleton-position-carpal-mode-map
>   (let ((kmap (make-sparse-keymap)))
>     (define-key kmap "\C-c+q" 'turn-off-skeleton-position-carpal-mode)
>     (define-key kmap "\C-c+\C-m" 'skeleton-position-carpal-exit)
>     (define-key kmap "\C-c+n" 'skeleton-position-carpal-next)
>     (define-key kmap "\C-c+p" 'skeleton-position-carpal-prev)
>     (define-key kmap "\C-c+a" 'skeleton-position-carpal-first)
>     (define-key kmap "\C-c+z" 'skeleton-position-carpal-last)
>     kmap)
>   "Keymap used in Skeleton Position Carpal mode.")

How 'bout:

  (defvar s-p-c-prefix [?\C-c ?+])
  (defvar s-p-c-m-m
     (let ((map (make-sparse-keymap)))
       (define-key map s-p-c-prefix skeleton-position-mode-map)))

So you avoid redundancy.  The prefix variable is so that people
can use another prefix (ESC is often a good choice for some users
although it's a bad default choice).


-- Stefan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Browse skeleton positions
  2003-10-31 17:28         ` Stefan Monnier
@ 2003-11-02 16:10           ` Ian Zimmerman
  2003-11-11 17:49             ` Ian Zimmerman
  0 siblings, 1 reply; 7+ messages in thread
From: Ian Zimmerman @ 2003-11-02 16:10 UTC (permalink / raw)



Stefan> How 'bout:

  (defvar s-p-c-prefix [?\C-c ?+])
  (defvar s-p-c-m-m
     (let ((map (make-sparse-keymap)))
       (define-key map s-p-c-prefix skeleton-position-mode-map)))

Stefan> So you avoid redundancy.  The prefix variable is so that people
Stefan> can use another prefix (ESC is often a good choice for some
Stefan> users although it's a bad default choice).

Excellent idea, thanks.

-- 
"Rap music is our punishment for neglecting music education."
An anonymous teacher

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Browse skeleton positions
  2003-11-02 16:10           ` Ian Zimmerman
@ 2003-11-11 17:49             ` Ian Zimmerman
  0 siblings, 0 replies; 7+ messages in thread
From: Ian Zimmerman @ 2003-11-11 17:49 UTC (permalink / raw)


;;; skelposn.el --- browse skeleton positions after insertion
;; Copyright (C) Ian Zimmerman, October 2003
;; Terms: GNU General Public License, Version 2

(defconst skeleton-position-mode-map
  (let ((kmap (make-sparse-keymap)))
    (suppress-keymap kmap)
    (define-key kmap "q" 'turn-off-skeleton-position-mode)
    (define-key kmap "\C-m" 'skeleton-position-exit)
    (define-key kmap "n" 'skeleton-position-next)
    (define-key kmap "p" 'skeleton-position-prev)
    (define-key kmap "a" 'skeleton-position-first)
    (define-key kmap "z" 'skeleton-position-last)
    kmap)
  "Keymap used in Skeleton Position mode.")

(defvar skeleton-position-carpal-mode-prefix [?\C-c ?+]
  "*Prefix key sequence for commands in Skeleton Position Carpal mode.")

(defconst skeleton-position-carpal-mode-map
  (let ((kmap (make-sparse-keymap)))
    (define-key kmap skeleton-position-carpal-mode-prefix skeleton-position-mode-map)
    kmap)
  "Keymap used in Skeleton Position Carpal mode.")

(defvar skeleton-position-max-list-length 50
  "*How many markers per buffer to keep in skeleton position mode.
If nil or negative, the lists of markers are allowed to grow
without limit, which can slow down Emacs dramatically.")

\f

;;;###autoload
(define-minor-mode skeleton-position-mode
  "Set or toggle the Skeleton Position minor mode.
\\<skeleton-position-mode-map>  This mode provides an interface to
browse the list of interesting position after a skeleton is inserted.

\\[skeleton-position-next] - Move to the next marker in `skeleton-position-marker-list'.
\\[skeleton-position-prev] - Move to the previous marker in `skeleton-position-marker-list'.
\\[skeleton-position-first] - Move to the first marker in `skeleton-position-marker-list'.
\\[skeleton-position-last] - Move to the last marker in `skeleton-position-marker-list'.
\\[skeleton-position-exit] - Clean up old skeleton positions and exit Skeleton Position mode."
  nil " SkelPosn" skeleton-position-mode-map)

;;;###autoload
(defun turn-on-skeleton-position-mode ()
  "Turn on the Skeleton Position minor mode."
  (interactive)
  (skeleton-position-mode 1))

(defun turn-off-skeleton-position-mode ()
  "Turn off the Skeleton Position minor mode."
  (interactive)
  (skeleton-position-mode 0))

(defvar skeleton-position-marker-list nil
  "List of markers pointing to skeleton positions in a buffer.")

(make-variable-buffer-local 'skeleton-position-marker-list)

(defvar skeleton-position-push-mark nil
  "\\<skeleton-position-mode-map>\
When set, causes \\[skeleton-position-next] and \\[skeleton-position-prev] \
in Skeleton Position mode to push a mark at point.")

(make-variable-buffer-local 'skeleton-position-push-mark)

(defvar skeleton-position-current nil
  "\\<skeleton-position-mode-map>\
The last position visited by \\[skeleton-position-next] or \\[skeleton-position-prev] \
in Skeleton Position mode, as a pointer into `skeleton-position-marker-list'.")

(make-variable-buffer-local 'skeleton-position-current)

(defun skeleton-end-hook-skelposn ()
  (setq skeleton-position-marker-list
        (append
         (nreverse
          (mapcar
           (lambda (p) (copy-marker p t))
           skeleton-positions))
         skeleton-position-marker-list))
  (let ((l (length skeleton-position-marker-list)))
    (when (and (integerp skeleton-position-max-list-length)
               (>= skeleton-position-max-list-length 0)
               (< skeleton-position-max-list-length l))
      (let* ((rest-length (- l skeleton-position-max-list-length))
             (rest
              (nthcdr
               skeleton-position-max-list-length
               skeleton-position-marker-list))
             (head (nbutlast skeleton-position-marker-list rest-length)))
        (when (and (consp skeleton-position-current)
                   (memq (car skeleton-position-current) rest))
          (setq skeleton-position-current nil))
        (mapcar (lambda (m) (set-marker m nil)) rest)
        (setq skeleton-position-marker-list head))))
  (when (and skeleton-position-marker-list
             (null skeleton-position-current))
    (setq skeleton-position-push-mark t)))  

(unless (featurep 'skelposn)
  (add-hook 'skeleton-end-hook 'skeleton-end-hook-skelposn))

(defun skeleton-position-next (&optional n)
  "Move to the next marker in `skeleton-position-marker-list'.

With an argument N, move to the Nth next marker on the list,
after `skeleton-position-current' instead.
If N is zero or negative, move to the Nth previous marker on the list.
The first call after a skeleton is inserted pushes a mark before moving."
  (interactive "p")
  (if (< n 0) (skeleton-position-prev n)
    (unless skeleton-position-current
      (setq skeleton-position-current (last skeleton-position-marker-list)))
    (while (> n 0)
      (while (and skeleton-position-current
                  (cdr skeleton-position-current)
                  (> n 0))
        (setq skeleton-position-current (cdr skeleton-position-current)
              n (1- n)))
      (when (> n 0)
        (setq n (1- n)
              skeleton-position-current skeleton-position-marker-list)))
    (when (null skeleton-position-current) (error "No more skeleton positions"))
    (when skeleton-position-push-mark
      (when (/= (point) (car skeleton-position-current)) (push-mark))
      (setq skeleton-position-push-mark nil))
    (goto-char (car skeleton-position-current))))

(defun skeleton-position-prev (&optional n)
  "Move to the previous marker in `skeleton-position-marker-list'.

With an argument N, move to the Nth previous marker on the list,
before `skeleton-position-current' instead.
If N is zero or negative, move to the Nth next marker on the list.
The first call after a skeleton is inserted pushes a mark before moving."
  (interactive "p")
  (if (< n 0) (skeleton-position-next n)
    (unless skeleton-position-current
      (setq skeleton-position-current skeleton-position-marker-list))
    (setq skeleton-position-marker-list (nreverse skeleton-position-marker-list))
    (unwind-protect
        (while (> n 0)
          (while (and skeleton-position-current
                      (cdr skeleton-position-current)
                      (> n 0))
            (setq skeleton-position-current (cdr skeleton-position-current)
                  n (1- n)))
          (when (> n 0)
            (setq n (1- n)
                  skeleton-position-current skeleton-position-marker-list)))
      (setq skeleton-position-marker-list (nreverse skeleton-position-marker-list)))
    (when (null skeleton-position-current) (error "No more skeleton positions"))
    (when skeleton-position-push-mark
      (when (/= (point) (car skeleton-position-current)) (push-mark))
      (setq skeleton-position-push-mark nil))
    (goto-char (car skeleton-position-current))))

(defun skeleton-position-first ()
  "Move to the first marker in `skeleton-position-marker-list'."
  (interactive)
  (setq skeleton-position-current skeleton-position-marker-list)
  (when (null skeleton-position-current) (error "No more skeleton positions"))
  (when skeleton-position-push-mark
    (when (/= (point) (car skeleton-position-current)) (push-mark))
    (setq skeleton-position-push-mark nil))
  (goto-char (car skeleton-position-current)))  

(defun skeleton-position-last ()
  "Move to the last marker in `skeleton-position-marker-list'."
  (interactive)
  (setq skeleton-position-current (last skeleton-position-marker-list))
  (when (null skeleton-position-current) (error "No more skeleton positions"))
  (when skeleton-position-push-mark
    (when (/= (point) (car skeleton-position-current)) (push-mark))
    (setq skeleton-position-push-mark nil))
  (goto-char (car skeleton-position-current)))  

(defun skeleton-position-cleanup ()
  (when skeleton-position-current
    (let ((rest (cdr skeleton-position-current)))
      (setcdr skeleton-position-current nil)
      (setq skeleton-position-current nil)
      (mapcar (lambda (m) (set-marker m nil)) skeleton-position-marker-list)
      (setq skeleton-position-marker-list rest))))  

(defun skeleton-position-exit ()
  "Clean up old skeleton positions and exit Skeleton Position mode."
  (interactive)
  (skeleton-position-cleanup)
  (turn-off-skeleton-position-mode))

\f

;;;###autoload
(define-minor-mode skeleton-position-carpal-mode
  "Set or toggle the Skeleton Position Carpal minor mode.
\\<skeleton-position-carpal-mode-map> This mode provides an interface to
browse the list of interesting position after a skeleton is inserted.
It is like `skeleton-position-mode', but does not rebind any normal
editing keystrokes.

\\[skeleton-position-carpal-next] - Move to the next marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-prev] - Move to the previous marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-first] - Move to the first marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-last] - Move to the last marker in `skeleton-position-marker-list'.
\\[skeleton-position-carpal-exit] - Clean up old skeleton positions and exit Skeleton Position Carpal mode."
  nil " SkelCarp" skeleton-position-carpal-mode-map)

(defalias 'skeleton-position-carpal-next 'skeleton-position-next)
(defalias 'skeleton-position-carpal-prev 'skeleton-position-prev)
(defalias 'skeleton-position-carpal-first 'skeleton-position-first)
(defalias 'skeleton-position-carpal-last 'skeleton-position-last)

;;;###autoload
(defun turn-on-skeleton-position-carpal-mode ()
  "Turn on the Skeleton Position Carpal minor mode."
  (interactive)
  (skeleton-position-carpal-mode 1))

(defun turn-off-skeleton-position-carpal-mode ()
  "Turn off the Skeleton Position Carpal minor mode."
  (interactive)
  (skeleton-position-carpal-mode 0))

(defun skeleton-position-carpal-exit ()
  "Clean up old skeleton positions and exit Skeleton Position Carpal mode."
  (interactive)
  (skeleton-position-cleanup)
  (turn-off-skeleton-position-carpal-mode))

\f
;;;###autoload
(defun skeleton-position-reset ()
  "Clean up all saved skeleton positions."
  (interactive)
  (mapcar (lambda (m) (set-marker m nil)) skeleton-position-marker-list)
  (setq skeleton-position-marker-list nil)
  (setq skeleton-position-current nil))

(provide 'skelposn)

;;; skelposn.el ends here

-- 
"Rap music is our punishment for neglecting music education."
An anonymous teacher

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2003-11-11 17:49 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <87vfqnygi7.fsf@newsguy.com>
2003-10-17 20:42 ` Browse skeleton positions Stefan Monnier
2003-10-18 17:58   ` Ian Zimmerman
2003-10-19 23:36     ` Stefan Monnier
2003-10-30 23:57       ` Ian Zimmerman
2003-10-31 17:28         ` Stefan Monnier
2003-11-02 16:10           ` Ian Zimmerman
2003-11-11 17:49             ` Ian Zimmerman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).