unofficial mirror of help-gnu-emacs@gnu.org
 help / color / mirror / Atom feed
* undo custom delete
@ 2005-10-04 16:03 Shug Boabby
  2005-10-04 17:29 ` rgb
  0 siblings, 1 reply; 8+ messages in thread
From: Shug Boabby @ 2005-10-04 16:03 UTC (permalink / raw)


Hi everyone,

I have used a very neat custom backspace key for a while now, which
will hungry delete back to the current level of indentation. I found it
on the emacs mailing list some time ago (Stefan Monnier originally
wrote it).

However I have had a little bit of trouble with it when it comes to
undo... normally if you type a word in emacs and then delete it, one
letter at a time (using the normal delete command), one utterance of
"C-x u" will return the whole word. However, with this custom command,
the letters are returned one at a time.

Could somebody please have a look at this code and suggest an
improvement to allow undo to work correctly? Or perhaps there is a list
of such commands with this property that undo needs to know about...
which I cannot find.

thanks,
Shug

;;;;;;;;;;;;;;;;;;;;;;;
;; Fancy delete key
;; This function was written by Stefan Monnier
(defun fancy-backspace ()
  "Delete space backward to prev level of indentation."
  (interactive)
  (if (or (bolp) (save-excursion (skip-chars-backward " \t") (not
(bolp))))
      ;; If we're not inside indentation, behave as usual.
      (call-interactively 'backward-delete-char-untabify)
    ;; We're inside indentation.
    (let* ((col (current-column))
           (destcol
            (save-excursion
              ;; Skip previous lines that are more indented than us.
              (while (and (not (bobp))
                          (zerop (forward-line -1))
                          (skip-chars-forward " \t")
                          (>= (current-column) col)))
              (current-column))))
      (delete-region (point)(progn(move-to-column destcol) (point))))))
(global-set-key "\C-?" 'fancy-backspace)
;; note: C, lisp and a few other modes need this defined locally
;;;;;;;;;;;;;;;;;;;;;;;

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

* Re: undo custom delete
  2005-10-04 16:03 undo custom delete Shug Boabby
@ 2005-10-04 17:29 ` rgb
  2005-10-05  9:08   ` Shug Boabby
  0 siblings, 1 reply; 8+ messages in thread
From: rgb @ 2005-10-04 17:29 UTC (permalink / raw)


> undo... normally if you type a word in emacs and then delete it, one
> letter at a time (using the normal delete command), one utterance of
> "C-x u" will return the whole word. However, with this custom command,
> the letters are returned one at a time.

I, for one, was unable to recreate either symptom you describe.
After using backward-delete-char-untabify in the normal way, on
my machine, the undo key returned each character I deleted one
at a time.  In situations where fancy-backspace deleted more
than one character in a single keystroke, undo returned all the
deleted characters in a single invocation.  So it seems to work
as I would expect already.
Perhaps what you are calling "(using the normal delete command)"
uses some other command besides backward-delete-char-untabify.
If so, perhaps replacing backward-delete-char-untabify with your
"normal delete command" will yield the results you expect.

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

* Re: undo custom delete
  2005-10-04 17:29 ` rgb
@ 2005-10-05  9:08   ` Shug Boabby
  2005-10-05 14:23     ` rgb
  0 siblings, 1 reply; 8+ messages in thread
From: Shug Boabby @ 2005-10-05  9:08 UTC (permalink / raw)


> I, for one, was unable to recreate either symptom you describe.

err... sorry, i don't know what i was thinking; for some reason i had
imagined that the normal delete returned whole words instead of
character at a time. i guess i should have checked this explicitly
before posting. i must have been thinking about undo after you type a
whole word.

but this does raise another question... is there a way to undo deletion
of a complete word in the same way that undo would undo the typing of a
complete word? surely it must be do-able, the logic being something
recursive like "if (last action was delete char) and (char not
whitespace), then (undo last action) and (repeat this loop), else
(break)".

sorry for not checking!

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

* Re: undo custom delete
  2005-10-05  9:08   ` Shug Boabby
@ 2005-10-05 14:23     ` rgb
  2005-10-05 14:36       ` Shug Boabby
  0 siblings, 1 reply; 8+ messages in thread
From: rgb @ 2005-10-05 14:23 UTC (permalink / raw)


> but this does raise another question... is there a way to undo deletion
> of a complete word in the same way that undo would undo the typing of a
> complete word? surely it must be do-able, the logic being something
> recursive like "if (last action was delete char) and (char not
> whitespace), then (undo last action) and (repeat this loop), else
> (break)".

The only possibility is to change how undo elements appear on
buffer-undo-list. Since undoing an insert involves deleting the
inserted character the undo list doesn't record what character
was inserted.  Only when you delete something does the original
content need to be saved so it can be re-inserted during undo.
So a special-undo could not tell when to stop undoing unless it
looked at the buffer contents at the point where undo list says
delete something.
Hmm, so it could tell...  Anyway...
Undo normally undoes elements on the list until it reaches a
undo-boundary element.  A nil.
You could create a pre command hook or remap word constituent
characters to an intermediate function.  Either way the
function would decide if it wanted to remove the car of
buffer-undo-list (if it's an undo-boundary element (nil)).
This has the effect of making the next action belong to the
previous group of keystrokes and all will be undone at once.

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

* Re: undo custom delete
  2005-10-05 14:23     ` rgb
@ 2005-10-05 14:36       ` Shug Boabby
  2005-10-05 15:17         ` Johan Bockgård
  0 siblings, 1 reply; 8+ messages in thread
From: Shug Boabby @ 2005-10-05 14:36 UTC (permalink / raw)


and also, i'd have to ensure that the character deleted wasn't
whitespace and that it was beside the last character deleted... or undo
would undo not just the last word, but the last N deletes until it
encounters whitespace!

a pre command hook sounds like the way to do it. if anyone wants a
little project to work on for a few hours, please be my guest! i'll try
when i get time.

could somebody please describe the buffer-undo-list in more detail to
me... specifically, how do i tell which action was performed, where the
action was performed, and if it was a deletion, what was deleted.

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

* Re: undo custom delete
  2005-10-05 14:36       ` Shug Boabby
@ 2005-10-05 15:17         ` Johan Bockgård
  2005-10-05 16:47           ` Shug Boabby
  0 siblings, 1 reply; 8+ messages in thread
From: Johan Bockgård @ 2005-10-05 15:17 UTC (permalink / raw)


"Shug Boabby" <Shug.Boabby@gmail.com> writes:

> could somebody please describe the buffer-undo-list in more detail
> to me... specifically, how do i tell which action was performed,
> where the action was performed, and if it was a deletion, what was
> deleted.

Read the documentation.

Look up buffer-undo-list in the "GNU Emacs Lisp Reference Manual"[1],
or take a look at the docstring[2].


[1] http://www.gnu.org/software/emacs/elisp-manual/elisp.html
[2] C-h v buffer-undo-list RET

-- 
Johan Bockgård

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

* Re: undo custom delete
  2005-10-05 15:17         ` Johan Bockgård
@ 2005-10-05 16:47           ` Shug Boabby
  2005-10-05 17:49             ` Johan Bockgård
  0 siblings, 1 reply; 8+ messages in thread
From: Shug Boabby @ 2005-10-05 16:47 UTC (permalink / raw)


thanks Johan,

I had already read the documentation about this list... but my lisp
skills are weak and it seems that buffer-undo-list can contain many
different types of elements, namely an element can be of the type:

  position
  (beg . end)
  (text . position)
  (t high . low)
  (nil property value beg . end)
  (put-text-property beg end property value)
  (marker . adjustment)
  nil

how can i get the first element from the list, and once i have it test
which type it is, reference it's components and delete it from the list
if need be.

it doesn't seem to record the operation that was performed... but the
object type (text . position) is the important one... i want to check
if the element is of this type, and if it is, then i want to be able to
do more checks on the position part before proceeding.

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

* Re: undo custom delete
  2005-10-05 16:47           ` Shug Boabby
@ 2005-10-05 17:49             ` Johan Bockgård
  0 siblings, 0 replies; 8+ messages in thread
From: Johan Bockgård @ 2005-10-05 17:49 UTC (permalink / raw)


"Shug Boabby" <Shug.Boabby@gmail.com> writes:

> how can i get the first element from the list, and once i have it
> test which type it is, reference it's components and delete it from
> the list if need be.

All of this is thoroughly explained in the "Emacs Lisp Reference
Manual".

Lists are constructed from "cons cells".

The expression
    (cons 1 (cons 2 (cons 3 nil)))
builds the list
    (1 2 3)
which can also be represented as
    (1 . (2 . (3 . nil))).

`car' picks out the left half (the "car") of a pair / the first
      element of a list

`cdr' picks out the right half (the "cdr") of a pair / the rest
      of a list

(car '(1 2 3))                => 1
(car '(1 . (2 . (3 . nil))))  => 1 ; this is exactly the same as above
(car '("text" . position))    => "text"
(cdr '("text" . position))    => position

`stringp' is used to test an object for being a string.

(stringp "text")  => t
(stringp 0)      => nil

Maybe you should start with "Introduction to Programming in Emacs
Lisp", http://www.gnu.org/software/emacs/emacs-lisp-intro/

If you use the CVS version of emacs then the Emacs manual, Elisp
manual, and Elisp Intro manual are all included.


You can use `M-x ielm RET' to practice evaluating simple Lisp
expressions:

*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (+ 1 2)
3
ELISP> (list 'a 'b 'c)
(a b c)

ELISP> (cons 'a 'b)
(a . b)

You can use C-x C-e (eval-last-sexp) to evaluate Lisp expressions
anywhere.

> it doesn't seem to record the operation that was performed

Correct. Only changes to the text are recorded, not which command was
used.

-- 
Johan Bockgård

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

end of thread, other threads:[~2005-10-05 17:49 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-10-04 16:03 undo custom delete Shug Boabby
2005-10-04 17:29 ` rgb
2005-10-05  9:08   ` Shug Boabby
2005-10-05 14:23     ` rgb
2005-10-05 14:36       ` Shug Boabby
2005-10-05 15:17         ` Johan Bockgård
2005-10-05 16:47           ` Shug Boabby
2005-10-05 17:49             ` Johan Bockgård

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).