all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* Help with keybinding to delete between {}
@ 2007-12-05  1:33 lampshade
  2007-12-05 10:48 ` Bernardo Bacic
                   ` (5 more replies)
  0 siblings, 6 replies; 15+ messages in thread
From: lampshade @ 2007-12-05  1:33 UTC (permalink / raw
  To: help-gnu-emacs

Hello,


I would really like a keybinding that would allow me to delete any
text between sexp's like {} (), etc no matter where I am between them
and whether or not that text has spaces.

For example
{asdfdsfa asdfasdf asd}
I would like to delete between leaving only the {} with my cursor
inside ready to type.  So far I've been trying
(defun delete_between ()
	(interactive)
	(backward-sexp)
	(kill-sexp))
(global-set-key [(control meta k)] 'delete_between)

but that doesn't quite work.  Anyone have any improvements or help
they could give me?

Thanks in advance,
lampshade

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

* Re: Help with keybinding to delete between {}
  2007-12-05  1:33 Help with keybinding to delete between {} lampshade
@ 2007-12-05 10:48 ` Bernardo Bacic
  2007-12-05 12:55 ` William Xu
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Bernardo Bacic @ 2007-12-05 10:48 UTC (permalink / raw
  Cc: help-gnu-emacs

it was a dark and stormy night when lampshade said, On 12/05/2007 12:33 PM:
> I would really like a keybinding that would allow me to delete any
> text between sexp's like {} (), etc no matter where I am between them
> and whether or not that text has spaces.
mark-sexp + delete-region ?

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

* Re: Help with keybinding to delete between {}
  2007-12-05  1:33 Help with keybinding to delete between {} lampshade
  2007-12-05 10:48 ` Bernardo Bacic
@ 2007-12-05 12:55 ` William Xu
  2007-12-05 13:30 ` Andreas Röhler
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: William Xu @ 2007-12-05 12:55 UTC (permalink / raw
  To: help-gnu-emacs

lampshade <mwolffedu@gmail.com> writes:

> Anyone have any improvements or help they could give me?

How does this feel?

,----
| (defun delete-between ()
|   (interactive)
|   (save-excursion
|     (let ((beg (re-search-backward "{\\|(" nil t 1))
|           (end (re-search-forward "}\\|)" nil t 1)))
|       (when (and beg end)
|         (kill-region (1+ beg) (1- end))))))
`----

-- 
William

http://williamxu.net9.org

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

* Re: Help with keybinding to delete between {}
  2007-12-05  1:33 Help with keybinding to delete between {} lampshade
  2007-12-05 10:48 ` Bernardo Bacic
  2007-12-05 12:55 ` William Xu
@ 2007-12-05 13:30 ` Andreas Röhler
  2007-12-05 23:50 ` Ilya Zakharevich
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 15+ messages in thread
From: Andreas Röhler @ 2007-12-05 13:30 UTC (permalink / raw
  To: help-gnu-emacs

Am Mittwoch, 5. Dezember 2007 02:33 schrieb lampshade:
> Hello,
>
>
> I would really like a keybinding that would allow me to delete any
> text between sexp's like {} (), etc no matter where I am between them
> and whether or not that text has spaces.
>
> For example
> {asdfdsfa asdfasdf asd}
> I would like to delete between leaving only the {} with my cursor
> inside ready to type.  So far I've been trying
> (defun delete_between ()
> 	(interactive)
> 	(backward-sexp)
> 	(kill-sexp))
> (global-set-key [(control meta k)] 'delete_between)
>
> but that doesn't quite work.  Anyone have any improvements or help
> they could give me?
>
> Thanks in advance,
> lampshade
> _______________________________________________

Maybe try thingatpt-utils1.7 in gnu-emacs-sources.

Changed `delimited-atpt', so `kill-delimited-atpt' 

should do it now.

Remains to provide a key for it.

Andreas Röhler

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

* Re: Help with keybinding to delete between {}
  2007-12-05  1:33 Help with keybinding to delete between {} lampshade
                   ` (2 preceding siblings ...)
  2007-12-05 13:30 ` Andreas Röhler
@ 2007-12-05 23:50 ` Ilya Zakharevich
  2007-12-06  6:33 ` Xah Lee
  2007-12-07 16:30 ` Stefan Monnier
  5 siblings, 0 replies; 15+ messages in thread
From: Ilya Zakharevich @ 2007-12-05 23:50 UTC (permalink / raw
  To: help-gnu-emacs

[A complimentary Cc of this posting was sent to
lampshade 
<mwolffedu@gmail.com>], who wrote in article <598472b5-c766-483a-93e5-15b31bfd880f@b40g2000prf.googlegroups.com>:
> Hello,
> 
> 
> I would really like a keybinding that would allow me to delete any
> text between sexp's like {} (), etc no matter where I am between them
> and whether or not that text has spaces.
> 
> For example
> {asdfdsfa asdfasdf asd}
> I would like to delete between leaving only the {} with my cursor
> inside ready to type.  So far I've been trying
> (defun delete_between ()
> 	(interactive)
> 	(backward-sexp)

	(up-list -1)

> 	(kill-sexp))
> (global-set-key [(control meta k)] 'delete_between)
> 
> but that doesn't quite work.  Anyone have any improvements or help
> they could give me?

In my setup, backspace kills back, delete forward; control-whatever
acts in words; meta-left/right acts in sexps, meta-up/down does
(up-list 1/-1).  shift- adds some pepper (changes search-* to
replace-*, changes kill-word to kill-up-to-begin/end-of-line, changes
movement to move-and-modify-CUA-selection).

But I do not have kill-by-sexp commands.  Instead, I do a shifted-move
(to select), and kill-CUA-selected.  So to do what you want, I would
M-up, S-M-right, S-backspace.  More keystrokes, but much more flexible
- I rarely want to delete something as simple as sexp, usually I
combine several move-and-modify-CUA-selection commands...

Probably this does not help your problem much...
Ilya

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

* Re: Help with keybinding to delete between {}
  2007-12-05  1:33 Help with keybinding to delete between {} lampshade
                   ` (3 preceding siblings ...)
  2007-12-05 23:50 ` Ilya Zakharevich
@ 2007-12-06  6:33 ` Xah Lee
  2007-12-06 17:14   ` Xah Lee
  2007-12-14 11:43   ` Xah Lee
  2007-12-07 16:30 ` Stefan Monnier
  5 siblings, 2 replies; 15+ messages in thread
From: Xah Lee @ 2007-12-06  6:33 UTC (permalink / raw
  To: help-gnu-emacs

you wrote:
<<I would really like a keybinding that would allow me to delete any
text between sexp's like {} (), etc no matter where I am between them
and whether or not that text has spaces.>>

I wrote a code few months ago that does exactly what you asked.

(defun delete-enclosed-text ()
  "Delete texts between any pair of delimiters."
  (interactive)
  (skip-chars-backward "^<>()""")
  (delete-char (skip-chars-forward "^<>()""")))

For more, see:
http://xahlee.org/emacs/elisp_examples.html

These days i don't use the above. Instead, i have a extend-selection
that selects text inside matching pairs. (then i can delete or cop or
cut with another keystroke) Here's the code:

(defun extend-selection ()
"Highlight a region between the nearest left and right delimiters.
Delimiters are paired characters: ()[]<><<>>""''「」, including \"\".
When the function is run again, it extends the
selection to the next level of enclosing delimiters. "
 (interactive)
(if
    (or (and (eq last-command this-command) (mark t))
        (and transient-mark-mode mark-active))
    (let ((e1 (region-beginning))  (e2 (region-end)) b1 b2)
      (goto-char (- e1 1))
      (skip-chars-backward "^<>("{[「<<\"")
      (setq b1 (point))

      (goto-char (+ e2 1))
      (skip-chars-forward "^<>)"}]」>>\"")
      (setq b2 (point))
      (push-mark b1 nil t)
      )
  (progn
    (push-mark
     (save-excursion
       (skip-chars-backward "^<>("{[「<<\"")
       (point)
       ) nil t)
    (skip-chars-forward "^<>)"}]」>>\"")
    )
  )
)

This is currently assigned to Alt+7.

In the near future i'll rework the code so that, on repeated press of
Alt+7, it extend to outer matching pairs. (skiping pairs of delimiters
that's siblings) For more detail on this concept, see:

A Text Editor Feature: Syntax Tree Walk
http://xahlee.org/emacs/syntax_tree_walk.html

This concept of code selection is far more powerful (and simpler) than
existing sexp forward/backward or the whole set of paren-edit.el, in
particular when combined with a auto-lisp-formater.
(detailed at:
A Simple Lisp Code Formatter
http://xahlee.org/emacs/lisp_formatter.html
)


PS this message is posted thur groups.google.com. It in the past half
a year has been diddling with the french quote charaters "<<>>" (double
angle quotes; unicode U+00AB and U+00BB) that i use often for quation
in my posts.
For a period google groups will omit them, another period it'll
replace it with << and >>, and in the past week sometimes it'll omit
the closing char. In this post, the elisp code above also contain the
french quote. Let's see what google transformed it to this time.

  Xah
  xah@xahlee.org
\xAD\xF4 http://xahlee.org/

On Dec 4, 5:33 pm, lampshade <mwolff...@gmail.com> wrote:
> Hello,
>
> I would really like a keybinding that would allow me to delete any
> text between sexp's like {} (), etc no matter where I am between them
> and whether or not that text has spaces.
>
> For example
> {asdfdsfa asdfasdf asd}
> I would like to delete between leaving only the {} with my cursor
> inside ready to type.  So far I've been trying
> (defun delete_between ()
>         (interactive)
>         (backward-sexp)
>         (kill-sexp))
> (global-set-key [(control meta k)] 'delete_between)
>
> but that doesn't quite work.  Anyone have any improvements or help
> they could give me?
>
> Thanks in advance,
> lampshade

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

* Re: Help with keybinding to delete between {}
  2007-12-06  6:33 ` Xah Lee
@ 2007-12-06 17:14   ` Xah Lee
  2007-12-12  9:20     ` lampshade
                       ` (3 more replies)
  2007-12-14 11:43   ` Xah Lee
  1 sibling, 4 replies; 15+ messages in thread
From: Xah Lee @ 2007-12-06 17:14 UTC (permalink / raw
  To: help-gnu-emacs

for some reason my code in the previous post is completely non-
functional. (i swear i used it for few months. Perhaps when i put on
the website i got smart and edited it "for the better" without
testing)

Here's the correct version:

(defun delete-enclosed-text ()
  "Delete texts between any pair of delimiters.
Note: if you have nested matching pairs, the cursor
should be inside the inner most one. Else it gets confused.
This code should to be fixed in the future."
  (interactive)
  (save-excursion
    (let (p1 p2)
      (skip-chars-backward "^(<["<<") (setq p1 (point))
      (skip-chars-forward "^)>]">>") (setq p2 (point))
      (delete-region p1 p2)
    )
  )
)

  Xah
  xah@xahlee.org
\xAD\xF4 http://xahlee.org/

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

* Re: Help with keybinding to delete between {}
  2007-12-05  1:33 Help with keybinding to delete between {} lampshade
                   ` (4 preceding siblings ...)
  2007-12-06  6:33 ` Xah Lee
@ 2007-12-07 16:30 ` Stefan Monnier
  5 siblings, 0 replies; 15+ messages in thread
From: Stefan Monnier @ 2007-12-07 16:30 UTC (permalink / raw
  To: help-gnu-emacs

> I would really like a keybinding that would allow me to delete any
> text between sexp's like {} (), etc no matter where I am between them
> and whether or not that text has spaces.

You could start with C-M-u C-M-k.  The only problem is if you're inside
a string or a comment, in which case it probably won't do what you want.


        Stefan

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

* Re: Help with keybinding to delete between {}
  2007-12-06 17:14   ` Xah Lee
@ 2007-12-12  9:20     ` lampshade
  2007-12-13  3:59     ` Mike Mattie
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: lampshade @ 2007-12-12  9:20 UTC (permalink / raw
  To: help-gnu-emacs

On Dec 6, 11:14 am, Xah Lee <x...@xahlee.org> wrote:
> for some reason my code in the previous post is completely non-
> functional. (i swear i used it for few months. Perhaps when i put on
> the website i got smart and edited it "for the better" without
> testing)
>
> Here's the correct version:
>
> (defun delete-enclosed-text ()
>   "Delete texts between any pair of delimiters.
> Note: if you have nested matching pairs, the cursor
> should be inside the inner most one. Else it gets confused.
> This code should to be fixed in the future."
>   (interactive)
>   (save-excursion
>     (let (p1 p2)
>       (skip-chars-backward "^(<["<<") (setq p1 (point))
>       (skip-chars-forward "^)>]">>") (setq p2 (point))
>       (delete-region p1 p2)
>     )
>   )
> )
>
>   Xah
>   x...@xahlee.org
> \xAD\xF4http://xahlee.org/

I'm glad to see you in this thread! I actually came across your code
and tried that first.  Unfortunately, that version wasn't working so I
moved on to trying to write one myself.  Your implementation was
pretty well exactly what I was looking for.  Thank you for the updated
version!

Thank you!

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

* Re: Help with keybinding to delete between {}
  2007-12-06 17:14   ` Xah Lee
  2007-12-12  9:20     ` lampshade
@ 2007-12-13  3:59     ` Mike Mattie
       [not found]     ` <mailman.4961.1197518641.18990.help-gnu-emacs@gnu.org>
  2007-12-13 10:44     ` Mike Mattie
  3 siblings, 0 replies; 15+ messages in thread
From: Mike Mattie @ 2007-12-13  3:59 UTC (permalink / raw
  To: help-gnu-emacs


[-- Attachment #1.1: Type: text/plain, Size: 1703 bytes --]

On Thu, 6 Dec 2007 09:14:12 -0800 (PST)
Xah Lee <xah@xahlee.org> wrote:

> for some reason my code in the previous post is completely non-
> functional. (i swear i used it for few months. Perhaps when i put on
> the website i got smart and edited it "for the better" without
> testing)
> 
> Here's the correct version:
> 
> (defun delete-enclosed-text ()
>   "Delete texts between any pair of delimiters.
> Note: if you have nested matching pairs, the cursor
> should be inside the inner most one. Else it gets confused.
> This code should to be fixed in the future."
>   (interactive)
>   (save-excursion
>     (let (p1 p2)
>       (skip-chars-backward "^(<["<<") (setq p1 (point))
>       (skip-chars-forward "^)>]">>") (setq p2 (point))
>       (delete-region p1 p2)
>     )
>   )
> )

I don't this this can be right. on a single line it has three string quotation characters.

(defun delete-enclosed-text ()
   "Delete texts between any pair of delimiters.
 Note: if you have nested matching pairs, the cursor
 should be inside the inner most one. Else it gets confused.
 This code should to be fixed in the future."
   (interactive)
  (skip-chars-forward "^)>>")
  (delete-backward-char (skip-chars-backward "^(<<")))

this version doesn't change the mark so I dropped the save-excursion. It is not quite right because
it does not handle nested sexp at all. I don't understand the elisp flavor of regex yet, so it's
probably an easy fix.

>   Xah
>   xah@xahlee.org
> ∑ http://xahlee.org/
> _______________________________________________
> help-gnu-emacs mailing list
> help-gnu-emacs@gnu.org
> http://lists.gnu.org/mailman/listinfo/help-gnu-emacs

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 152 bytes --]

_______________________________________________
help-gnu-emacs mailing list
help-gnu-emacs@gnu.org
http://lists.gnu.org/mailman/listinfo/help-gnu-emacs

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

* Re: Help with keybinding to delete between {}
       [not found]     ` <mailman.4961.1197518641.18990.help-gnu-emacs@gnu.org>
@ 2007-12-13 10:39       ` Xah Lee
  0 siblings, 0 replies; 15+ messages in thread
From: Xah Lee @ 2007-12-13 10:39 UTC (permalink / raw
  To: help-gnu-emacs

Google Groups diddles with my unicode chars.

The unadulterated code can be found here:
http://xahlee.org/emacs/elisp_examples.html

--------------

am not sure what's the prob with google. Don't know if they are still
experimenting with unicode chars in posts or what. I often use U+00AB
and U+00BB (french double angle quotes, here: <<>>). But starting about
2007-09, google groups either deletes them, or replace them with <<
and >>, or botched the replacement lopsided. (and this transformation
apparantly took place before it is posted, so it's distributed to all
other places, not just a displaying issue on goople groups) This week
i also noticed that they replace my bullet char "*" by a asterisk "*".

i'll be using one of the chinese quotations "「」『』〈〉《》" for posting i
think. For the bullet i might use a start "★" or heart "♥".

  Xah
  xah@xahlee.org
∑ http://xahlee.org/

On Dec 12, 7:59 pm, Mike Mattie <codermat...@gmail.com> wrote:
> On Thu, 6 Dec 2007 09:14:12 -0800 (PST)
>
>
>
> Xah Lee <x...@xahlee.org> wrote:
> > for some reason my code in the previous post is completely non-
> > functional. (i swear i used it for few months. Perhaps when i put on
> > the website i got smart and edited it "for the better" without
> > testing)
>
> > Here's the correct version:
>
> > (defun delete-enclosed-text ()
> >   "Delete texts between any pair of delimiters.
> > Note: if you have nested matching pairs, the cursor
> > should be inside the inner most one. Else it gets confused.
> > This code should to be fixed in the future."
> >   (interactive)
> >   (save-excursion
> >     (let (p1 p2)
> >       (skip-chars-backward "^(<["<<") (setq p1 (point))
> >       (skip-chars-forward "^)>]">>") (setq p2 (point))
> >       (delete-region p1 p2)
> >     )
> >   )
> > )
>
> I don't this this can be right. on a single line it has three string quotation characters.
>
> (defun delete-enclosed-text ()
>    "Delete texts between any pair of delimiters.
>  Note: if you have nested matching pairs, the cursor
>  should be inside the inner most one. Else it gets confused.
>  This code should to be fixed in the future."
>    (interactive)
>   (skip-chars-forward "^)>>")
>   (delete-backward-char (skip-chars-backward "^(<<")))
>
> this version doesn't change the mark so I dropped the save-excursion. It is not quite right because
> it does not handle nested sexp at all. I don't understand the elisp flavor of regex yet, so it's
> probably an easy fix.

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

* Re: Help with keybinding to delete between {}
  2007-12-06 17:14   ` Xah Lee
                       ` (2 preceding siblings ...)
       [not found]     ` <mailman.4961.1197518641.18990.help-gnu-emacs@gnu.org>
@ 2007-12-13 10:44     ` Mike Mattie
  2007-12-13 12:46       ` Mike Mattie
  2007-12-13 13:01       ` Peter Dyballa
  3 siblings, 2 replies; 15+ messages in thread
From: Mike Mattie @ 2007-12-13 10:44 UTC (permalink / raw
  To: help-gnu-emacs


[-- Attachment #1.1: Type: text/plain, Size: 5528 bytes --]

On Thu, 6 Dec 2007 09:14:12 -0800 (PST)
Xah Lee <xah@xahlee.org> wrote:

> for some reason my code in the previous post is completely non-
> functional. (i swear i used it for few months. Perhaps when i put on
> the website i got smart and edited it "for the better" without
> testing)
> 
> Here's the correct version:
> 
> (defun delete-enclosed-text ()
>   "Delete texts between any pair of delimiters.
> Note: if you have nested matching pairs, the cursor
> should be inside the inner most one. Else it gets confused.
> This code should to be fixed in the future."
>   (interactive)
>   (save-excursion
>     (let (p1 p2)
>       (skip-chars-backward "^(<["<<") (setq p1 (point))
>       (skip-chars-forward "^)>]">>") (setq p2 (point))
>       (delete-region p1 p2)
>     )
>   )
> )

I decided to fix it in regards to nested lists. My implementation works
however it is purely for elucidation. It is a recursive implementation
that is nth recursive where n is the number of nested delimiters in the list.

that means that if you use this on a list with deep nesting it *will* crash
after exhausting the recursion limit. So don't use it for real.

A reliable solution would likely be based off something from thingatpoint.el ?
there must be something like this in the code-motion code for elisp.

This sort of function/feature? is dangerous even when implemented procedurally
because it will go wild if your delimiters aren't matched correctly.

Other flaws:
  * error path in bounds scan marked by "error ?" not implemented because I have
    not studied elisp error handling yet.

  * does not handle multi-byte characters due to use of aref in bounds-scan-{forward,backward}

With that said it does illustrate the value of lexical-let, and solves the
problem in a general way. It would be quite easy to add variations that
kill instead of deleting, or whatever other features you want.

I implemented it recursively simply because It looked prettier to me, probably
since I started with scheme. anyways here goes.

one last big fat warning: this code is for fun, it will eat your children eventually.

;; --- start of elisp

(defun bounds-scan ( seek-bounds open-bound-p close-bound-p restart-position position level )
  "scan for the delimitation of a region. This is a general form of a
   simple algorithm that counts opening and closing delimiters to scan
   past nested delimited spans."
  (progn
    (goto-char position) ;; move to the starting position before scanning.
    (funcall seek-bounds)

    (cond
      ((funcall open-bound-p)
        (bounds-scan seek-bounds open-bound-p close-bound-p restart-position
          (funcall restart-position) (+ level 1)))

      ((funcall close-bound-p)
        (if (> level 0)
          ;; when we have a positive level to start with
          ;; scan again with a decremented level.
          (bounds-scan seek-bounds open-bound-p close-bound-p restart-position
            (funcall restart-position) (- level 1))

          ;; return point as we are done
          (point)
          ))
      ;; error ?
      )))

(defun bounds-scan-forward ( delimiters position )
  "entry point for bounds-scan forward. given delimiters: a
   string containing a pair of delimiting characters, which must
   be in \"open close\" order, scan forward for the bounding
   delimiter returning the position before the delimiter"

  (lexical-let
    ((open-delimiter (aref delimiters 0))
     (close-delimiter (aref delimiters 1)))

    (bounds-scan
      (lambda ()
        (skip-chars-forward (concat "^" delimiters)))

      (lambda ()
        (char-equal open-delimiter (char-after)))

      (lambda ()
        (char-equal close-delimiter (char-after)))

      (lambda ()
        (+ (point) 1))

      position 0)))

(defun bounds-scan-backward ( delimiters position)
  "entry point for bounds-scan backward. given delimiters: a
   string containing a pair of delimiting characters, which must
   be in \"open close\" order, scan backward for the bounding
   delimiter returning the position after the delimiter"

  (lexical-let
    ;; note the inversion of the order since we are looking backwards
    ((open-delimiter (aref delimiters 1))
     (close-delimiter (aref delimiters 0)))

    (bounds-scan
      (lambda ()
        (skip-chars-backward (concat "^" delimiters)))

      (lambda ()
        (char-equal open-delimiter (char-before)))

      (lambda ()
        (char-equal close-delimiter (char-before)))

      (lambda ()
        (- (point) 1))

      position 0)))

(defun scan-lisp-list-close ()
  "wrapper for bounds-scan that searches for the closing delimiter of a lisp list"
  (let*
    ((start-at (point))
      (close-at (bounds-scan-forward "()" start-at)))

    (if (> close-at start-at)
      (- close-at 1)
      start-at)
    ))

(defun scan-lisp-list-open ()
  "wrapper for bounds-scan that searches for the opening delimiter of a lisp list"
  (let*
    ((start-at (point))
      (open-at (bounds-scan-backward "()" start-at)))

    (if (< open-at start-at)
      (+ open-at 1)
      start-at)
    ))

(defun lisp-list-delete-body ()
  "delete the body of a lisp list including any nested lists"
  (interactive)
  (let
    ((open-pos (scan-lisp-list-open))
     (close-pos (scan-lisp-list-close)))

    (delete-backward-char (- close-pos open-pos))))

;;----- end of elisp

Cheers,
Mike Mattie

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 152 bytes --]

_______________________________________________
help-gnu-emacs mailing list
help-gnu-emacs@gnu.org
http://lists.gnu.org/mailman/listinfo/help-gnu-emacs

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

* Re: Help with keybinding to delete between {}
  2007-12-13 10:44     ` Mike Mattie
@ 2007-12-13 12:46       ` Mike Mattie
  2007-12-13 13:01       ` Peter Dyballa
  1 sibling, 0 replies; 15+ messages in thread
From: Mike Mattie @ 2007-12-13 12:46 UTC (permalink / raw
  To: help-gnu-emacs


[-- Attachment #1.1: Type: text/plain, Size: 6110 bytes --]

On Thu, 13 Dec 2007 02:44:00 -0800
Mike Mattie <codermattie@gmail.com> wrote:

> On Thu, 6 Dec 2007 09:14:12 -0800 (PST)
> Xah Lee <xah@xahlee.org> wrote:
> 
> > for some reason my code in the previous post is completely non-
> > functional. (i swear i used it for few months. Perhaps when i put on
> > the website i got smart and edited it "for the better" without
> > testing)
> > 
> > Here's the correct version:
> > 
> > (defun delete-enclosed-text ()
> >   "Delete texts between any pair of delimiters.
> > Note: if you have nested matching pairs, the cursor
> > should be inside the inner most one. Else it gets confused.
> > This code should to be fixed in the future."
> >   (interactive)
> >   (save-excursion
> >     (let (p1 p2)
> >       (skip-chars-backward "^(<["<<") (setq p1 (point))
> >       (skip-chars-forward "^)>]">>") (setq p2 (point))
> >       (delete-region p1 p2)
> >     )
> >   )
> > )
> 
> I decided to fix it in regards to nested lists. My implementation
> works however it is purely for elucidation. It is a recursive
> implementation that is nth recursive where n is the number of nested
> delimiters in the list.
> 
> that means that if you use this on a list with deep nesting it *will*
> crash after exhausting the recursion limit. So don't use it for real.
> 
> A reliable solution would likely be based off something from
> thingatpoint.el ? there must be something like this in the
> code-motion code for elisp.
> 
> This sort of function/feature? is dangerous even when implemented
> procedurally because it will go wild if your delimiters aren't
> matched correctly.
> 
> Other flaws:
>   * error path in bounds scan marked by "error ?" not implemented
> because I have not studied elisp error handling yet.
> 
>   * does not handle multi-byte characters due to use of aref in
> bounds-scan-{forward,backward}
> 
> With that said it does illustrate the value of lexical-let, and
> solves the problem in a general way. It would be quite easy to add
> variations that kill instead of deleting, or whatever other features
> you want.
> 
> I implemented it recursively simply because It looked prettier to me,
> probably since I started with scheme. anyways here goes.
> 
> one last big fat warning: this code is for fun, it will eat your
> children eventually.

a small re-factor I noticed when I read the code a bit later. the check
for motion in the scan is hoisted into bounds-scan-{forward,backward} so
it isn't duplicated needlessly.

> ;; --- start of elisp

(defun bounds-scan ( seek-bounds open-bound-p close-bound-p restart-position position level )
  "scan for the delimitation of a region. This is a general form of a
   simple algorithm that counts opening and closing delimiters to scan
   past nested delimited spans."
  (progn
    (goto-char position) ;; move to the starting position before scanning.
    (funcall seek-bounds)

    (cond
      ((funcall open-bound-p)
        (bounds-scan seek-bounds open-bound-p close-bound-p restart-position
          (funcall restart-position) (+ level 1)))

      ((funcall close-bound-p)
        (if (> level 0)
          ;; when we have a positive level to start with
          ;; scan again with a decremented level.
          (bounds-scan seek-bounds open-bound-p close-bound-p restart-position
            (funcall restart-position) (- level 1))

          ;; return point as we are done
          (point)
          ))
      ;; error ?
      )))

(defun bounds-scan-forward ( delimiters position )
  "entry point for bounds-scan forward. given delimiters: a
   string containing a pair of delimiting characters, which must
   be in \"open close\" order, scan forward for the bounding
   delimiter returning the position before the delimiter"

  (lexical-let
    ((open-delimiter (aref delimiters 0))
     (close-delimiter (aref delimiters 1)))

    (let
      ((close-at (bounds-scan
                   (lambda ()
                     (skip-chars-forward (concat "^" delimiters)))

                   (lambda ()
                     (char-equal open-delimiter (char-after)))

                   (lambda ()
                     (char-equal close-delimiter (char-after)))

                   (lambda ()
                     (+ (point) 1))

                   position 0)))
      (if (> close-at position)
        (- close-at 1)
        position)
      )))

(defun bounds-scan-backward ( delimiters position )
  "entry point for bounds-scan backward. given delimiters: a
   string containing a pair of delimiting characters, which must
   be in \"open close\" order, scan backward for the bounding
   delimiter returning the position after the delimiter"

  (lexical-let
    ;; note the inversion of the order since we are looking backwards
    ((open-delimiter (aref delimiters 1))
     (close-delimiter (aref delimiters 0)))

    (let
      ((open-at (bounds-scan
                  (lambda ()
                    (skip-chars-backward (concat "^" delimiters)))

                  (lambda ()
                    (char-equal open-delimiter (char-before)))

                  (lambda ()
                    (char-equal close-delimiter (char-before)))

                  (lambda ()
                    (- (point) 1))

                  position 0)))
      (if (< open-at position)
        (+ open-at 1)
        position)
      )))

(defun scan-lisp-list-close ()
  "wrapper for bounds-scan that searches for the closing delimiter of a lisp list"
  (bounds-scan-forward "()" (point)))

(defun scan-lisp-list-open ()
  "wrapper for bounds-scan that searches for the opening delimiter of a lisp list"
  (bounds-scan-backward "()" (point)))

(defun lisp-list-delete-body ()
  "delete the body of a lisp list including any nested lists"
  (interactive)
  (let
    ((open-pos (scan-lisp-list-open))
     (close-pos (scan-lisp-list-close)))

    (delete-backward-char (- close-pos open-pos))))

> 
> ;;----- end of elisp
> 
> Cheers,
> Mike Mattie

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

[-- Attachment #2: Type: text/plain, Size: 152 bytes --]

_______________________________________________
help-gnu-emacs mailing list
help-gnu-emacs@gnu.org
http://lists.gnu.org/mailman/listinfo/help-gnu-emacs

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

* Re: Help with keybinding to delete between {}
  2007-12-13 10:44     ` Mike Mattie
  2007-12-13 12:46       ` Mike Mattie
@ 2007-12-13 13:01       ` Peter Dyballa
  1 sibling, 0 replies; 15+ messages in thread
From: Peter Dyballa @ 2007-12-13 13:01 UTC (permalink / raw
  To: Mike Mattie; +Cc: help-gnu-emacs


[-- Attachment #1.1: Type: text/plain, Size: 777 bytes --]


Am 13.12.2007 um 11:44 schrieb Mike Mattie:

> A reliable solution would likely be based off something from  
> thingatpoint.el ?


Isn't there also a problem when some such character is there in a  
comment? Wouldn't it make more sense to use sexpressions? One of:  
backward-sexp/backward-up-list/up-list? This could be used to climb  
higher one level, if the previous region isn't worth enough to be  
deleted. With kill-sexp.

These backward-sexp/backward-up-list/up-list should take into account  
what is defined as delimiter.

--
Greetings
                                  <]
    Pete      o        __o         |__    o           recumbo
     ___o    /I       -\<,         |o \  -\),-%       ergo sum!
___/\ /\___./ \___...O/ O____.....`-O-'-()--o_________________



[-- Attachment #1.2: Signierter Teil der Nachricht --]
[-- Type: application/pgp-signature, Size: 194 bytes --]

[-- Attachment #2: Type: text/plain, Size: 152 bytes --]

_______________________________________________
help-gnu-emacs mailing list
help-gnu-emacs@gnu.org
http://lists.gnu.org/mailman/listinfo/help-gnu-emacs

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

* Re: Help with keybinding to delete between {}
  2007-12-06  6:33 ` Xah Lee
  2007-12-06 17:14   ` Xah Lee
@ 2007-12-14 11:43   ` Xah Lee
  1 sibling, 0 replies; 15+ messages in thread
From: Xah Lee @ 2007-12-14 11:43 UTC (permalink / raw
  To: help-gnu-emacs

today i took some closer look at cursor moving commands for editing
lisp code.

`C-M-n'     Move forward over a parenthetical group (`forward-list').
`C-M-p'     Move backward over a parenthetical group (`backward-
list').

`C-M-u'     Move up in parenthesis structure (`backward-up-list').
`C-M-d'     Move down in parenthesis structure (`down-list').

`C-M-f'     Move forward over a balanced expression (`forward-sexp').
`C-M-b'     Move backward over a balanced expression (`backward-
sexp').
`C-M-k'     Kill balanced expression forward (`kill-sexp').
`C-M-<SPC>'     Put mark after following expression (`mark-sexp').

which i was aware for about a year but never really used. I think they
are FANTASTIC. Previously i thought the extend-selection idea i had
was more powerful, but not really. (the extend-selection idea is
simply backward-up-list followed by mark-sexp)

The keybinding choices are pretty bad though. I now set them thus:

(global-set-key (kbd "M-<up>") 'backward-up-list)
(global-set-key (kbd "M-<down>") 'down-list)
(global-set-key (kbd "M-<left>") 'backward-sexp)
(global-set-key (kbd "M-<right>") 'forward-sexp)
(global-set-key (kbd "M-S-<left>") 'backward-list)
(global-set-key (kbd "M-S-<right>") 'forward-list)

  Xah
  xah@xahlee.org
\xAD\xF4 http://xahlee.org/

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

end of thread, other threads:[~2007-12-14 11:43 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-05  1:33 Help with keybinding to delete between {} lampshade
2007-12-05 10:48 ` Bernardo Bacic
2007-12-05 12:55 ` William Xu
2007-12-05 13:30 ` Andreas Röhler
2007-12-05 23:50 ` Ilya Zakharevich
2007-12-06  6:33 ` Xah Lee
2007-12-06 17:14   ` Xah Lee
2007-12-12  9:20     ` lampshade
2007-12-13  3:59     ` Mike Mattie
     [not found]     ` <mailman.4961.1197518641.18990.help-gnu-emacs@gnu.org>
2007-12-13 10:39       ` Xah Lee
2007-12-13 10:44     ` Mike Mattie
2007-12-13 12:46       ` Mike Mattie
2007-12-13 13:01       ` Peter Dyballa
2007-12-14 11:43   ` Xah Lee
2007-12-07 16:30 ` Stefan Monnier

Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.