DrRacket suggestion: Add a hotkey to peel off the most immediate surrounding s-expression

DrRacket already makes it easy to delete or hide an entire s-expression (i.e. parentheses bounded expression).

However, often you actually want to delete only the surrounding s-expression rather than the entire expression. It would be nice if there was a built-in hotkey in DrRacket to do this whenever you are on or in an s-expression.

For example, if applied to (+ (- a b) c) while inside (- a b) it would change to (- a b), deleting only the (+ ... c) part.

That would be super convenient and useful.

It is a very common operation when editing any Lisp/Scheme-like languages.

PS: I really appreciate how elegant and cleaning designed Racket is and how abundant and easy to get working its libraries are. This is my first post on Racket's Discourse page by the way (if my memory is correct).

4 Likes

You can create a custom keyboard binding, following https://docs.racket-lang.org/drracket/Keyboard_Shortcuts.html

For your use case:

  1. Create a new Racket file with the following content:
#lang s-exp framework/keybinding-lang

(define (rebind key . commands)
  (keybinding
   key
   (λ (ed evt)
     (send ed begin-edit-sequence)
     (for-each (λ (command)
                 (send (send ed get-keymap) call-function
                       command ed evt #t))
               commands)
     (send ed end-edit-sequence))))

(rebind "c:w"
        "up-sexp"
        "select-forward-sexp"
        "cut-clipboard"
        "up-sexp"
        "select-forward-sexp"
        "paste-clipboard")

  1. Enter “Edit > Keybindings > Add User-defined Keybindings..”. Choose the Racket file that you just created.

  2. Restart DrRacket

Here’s an example interaction, where | indicates the caret:

(* (+ (- a |b) c) d)

;; press c-w

(* (- a b)| d)

5 Likes

In the language of GitHub - benknoble/vim-sexp: Precision Editing for S-expressions which borrows from the original GitHub - guns/vim-sexp: Precision Editing for S-expressions, which was probably inspired by ParEdit or similar, this would be called "raising" the s-expression.

3 Likes

Thank you guys so much sorawee and benknoble!

I'll definitely try out both of these next time I get the time to. I wasn't expecting someone to give me an implementation so fast especially!

I'm a Vim user too by the way, although for Racket I haven't been using Vim for much more than larger scale substitutions when working with Racket so far since the indentation rules and other formatting nuances are so different from most languages. Sometimes I'll do a transformation in Vim and then reload in DrRacket currently, basically. It's good to know there's related tools and it's nice to have a name for the operation too.

Sorry for the delay in my response. I've been busy with random things.

1 Like

RE: vim, you may be interested in the recently-revised 24.3 Vim. I would be happy to share more about my setup, too.

1 Like

It doesn't look to me like anyone here has mentioned C:c,C:o, which I use all the time to accomplish this. It specifically discards the s-expression surrounding the one that the cursor is immediately before. So, in your example, given the expression (+ (- a b) c), if the cursor was just before the (- a b), then hitting C:c,C:o would discard the (- and the c). If (as you mention) you want to do this when the cursor is inside of the (- a b), you would use alt-up-arrow first.

To add to this, there's also C:c,C:e, which deletes the outer parens without deleting any of the content—a "splice", if you will. Using C:c,C:e instead of C:c,C:o would leave you with + (- a b) c. This is very useful when e.g. you want to unwrap an expression and rearrange its elements.

3 Likes

I'm guessing that there's a typo and you meant to discard the '(+' instead of the '(-'.

Hello again everyone!

I'm just stopping by to say thanks again for all this wonderful help you've all provided!

Racket's elegant design is very pleasant and getting more acquainted with manipulating s-expressions more flexibly and easily like this should help even more.

Having this thread here will also help other users searching the internet to figure out various ways of manipulating Racket's parenthetical expressions more easily too, so that's a bonus as well.

Anyway, looking forward to experimenting with Racket more in the future. :sunglasses:

1 Like