[racket] Writing a single key binding in DrRacket for commenting/uncommenting

From: Colin Gan (gan.colin.e at gmail.com)
Date: Thu Nov 28 08:58:53 EST 2013

You're right, I just tested out your example. My custom binding will
comment out the 'd', but bona-fide comment-out-selection will not. Thanks
for explaining it; I looked over the documentation but couldn't make sense
of it at the time. I'll probably keep using my binding like this until it
irritates me and I'll look at changing it again.

Thanks again,

C


On Thu, Nov 28, 2013 at 11:51 AM, Robby Findler <robby at eecs.northwestern.edu
> wrote:

> I believe the code in racket.rkt is correct.
>
> An example situation where (send editor position-paragraph end-pos) would
> be different from the result of calc-last-para is when you have an editor
> that has "abc" followed by a newline, followed by "d" as the entire
> contents of the buffer, and the selection starts at position 0 and goes to
> position 4 (so the newline is selected, but not the "d").
>
> In this case the commenting out should not comment out the second line
> (the one that contains the "d"), which is why calc-last-para returns 0 in
> that case instead of 1, which is what position-paragraph does.
>
> See also the at-eol discussion in the docs:
>
>
> http://docs.racket-lang.org/gui/editor-overview.html#%28part._editoreol%29
>
> Robby
>
>
>
> On Wed, Nov 27, 2013 at 6:10 AM, Colin Gan <gan.colin.e at gmail.com> wrote:
> >
> > Thanks for your pointers Robby. After much digging through of source
> code, I seem to have located the source of the problem.
> >
> > The definition of comment-out-selection in
> collects/framework/private/racket.rt has a loop which goes through and
> inserts a semi-colon at the start of every paragraph in the selection. To
> determine where it should end, it calculates the number of the last
> paragraph by calling a function named calc-last-para.
> >
> > It's here:
> >
> >     (define (calc-last-para last-pos)
> >       (let ([last-para (position-paragraph last-pos #t)])
> >         (if (and (> last-pos 0)
> >                  (> last-para 0))
> >             (begin (split-snip last-pos)
> >                    (let ([snip (find-snip last-pos 'before)])
> >                      (if (member 'hard-newline (send snip get-flags))
> >                          (- last-para 1)
> >                          last-para)))
> >             last-para)))
> >
> > The 'begin body' is what I have difficulty understanding. I'm guessing
> it finds the very last snip before the last position, determine if it is a
> newline, and if it is then it decrements the position of the last paragraph
> by 1. If this is done when the caret is positioned at the start of the
> line, the last paragraph position is off by 1. This means that the caret
> could be on paragraph 10 and calc-last-para would return 9, resulting in
> the line not being commented.
> >
> > To remedy this, I just use (send editor position-paragraph end-pos)
> instead of calc-last-para. I also removed a when expression in
> comment-out-selection which I found was causing the semicolon to become
> selected when commenting out on a new line. You can look at what I have
> done in the file I have attached: comment-toggle.rkt.
> >
> > Have a good day,
> >
> > C
> >
> >
> >
> > On Mon, Nov 25, 2013 at 9:23 PM, Robby Findler <
> robby at eecs.northwestern.edu> wrote:
> >>
> >> Nice job!
> >>
> >> One point where the docs are confusing: "line"s are soft-wrapped, not
> hard-wrapped lines. For code you want the methods with the word "paragraph"
> in the name instead of "line".
> >>
> >> I'm not seeing why your code doesn't work at the beginning of the line,
> but if you start up drracket from the command-line and then put printfs
> into your functions, you should be able to see intermediate values and you
> can check what's going on. Or, if you're on windows, you might find it
> easier to call "message-box", ie:
> >>
> >> (define is-line-commented?
> >>   (lambda (editor)
> >>     (define ans
> >>       (send editor find-string
> >>             ";" 'forward (get-start-of-line editor) (get-end-of-line
> editor)))
> >>     (message-box "hi" (format "ans ~s" ans))
> >>     ans))
> >>
> >> Robby
> >>
> >>
> >>
> >>
> >> On Sat, Nov 23, 2013 at 9:42 AM, Colin Gan <gan.colin.e at gmail.com>
> wrote:
> >>>
> >>> Hi all,
> >>>
> >>> I have recently picked up Scheme and would like to customize the key
> bindings in DrScheme. Specifically, I find the default binding for
> commenting and uncommenting out to be cumbersome; on OSX it is esc;c:= and
> esc;c:semicolon.
> >>>
> >>> What I would like to achieve is use one key to comment and uncomment,
> so it comments an uncommented line, and vice versa. Unfortunately I'm
> finding the documentation on key-binding a little sparse. Here's what I've
> been working at:
> >>>
> >>>
> >>> (define get-start-of-line
> >>>   (lambda (editor)
> >>>     (send editor get-character (send editor line-start-position
> >>>           (send editor position-line (send editor
> get-start-position))))))
> >>>
> >>> (define is-line-commented?
> >>>   (lambda (editor)
> >>>     (cond
> >>>       ((eq? ";"
> >>>             (get-start-of-line editor) )#t)
> >>>       (else #f))))
> >>>
> >>> (keybinding "d:/" (λ (editor evt) (if (is-line-commented? editor)
> >>>                                       (send editor uncomment-selection
> (send editor get-start-position))
> >>>                                       (send editor
> comment-out-selection (send editor get-start-position))
> >>>                                       )))
> >>>
> >>>
> >>> I know it's not very well written; I've only just finished the
> recursion section of The Little Schemer. I was going to leave it here, then
> I had another look at the documentation and had another go:
> >>>
> >>> (define get-start-of-line
> >>>   (lambda (editor)
> >>>     (send editor line-start-position
> >>>           (send editor position-line (send editor
> get-start-position)))))
> >>>
> >>> (define get-end-of-line
> >>>   (lambda (editor)
> >>>     (send editor line-end-position
> >>>           (send editor position-line (send editor get-end-position)))))
> >>>
> >>> (define is-line-commented?
> >>>   (lambda (editor)
> >>>      (send editor find-string
> >>>            ";" 'forward (get-start-of-line editor) (get-end-of-line
> editor))))
> >>>
> >>>
> >>> (keybinding "d:/" (λ (editor evt) (if (is-line-commented? editor)
> >>>                                       (send editor uncomment-selection
> (send editor get-start-position))
> >>>                                       (send editor
> comment-out-selection (send editor get-start-position))
> >>>                                       )))
> >>>
> >>>
> >>> This one actually works, but of course it is clumsy and dumb; it
> doesn't work when the caret is at the start of each line, and doesn't know
> if the semi-colon is escaped. I'm thrilled anyway. :)
> >>>
> >>>
> >>> Colin
> >>>
> >>> ____________________
> >>>   Racket Users list:
> >>>   http://lists.racket-lang.org/users
> >>>
> >>
> >
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20131128/9cdb5dea/attachment.html>

Posted on the users mailing list.