[plt-scheme] Fixing keybinding-lang.ss

From: Danny Yoo (dyoo at hkn.eecs.berkeley.edu)
Date: Fri Mar 31 17:03:26 EST 2006

> Let me see... Ok, got it.  I'm also not sure if this is the best way to
> do this either, but here's an example that binds M-, to the less than
> sign, and M-. to the greater than sign:
>
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
> (module test-keybindings (lib "keybinding-lang.ss" "framework")
>   ;; A small demo of how we can make our own keymap handlers
>
>   ;; make-handler: string -> handler
>   ;; makes a handler that inserts the string s
>   (define (make-handler s)
>     (lambda (editor event)
>       (send editor insert (make-object string-snip% s))))
>
>   ;; Some sample bindings:
>   (keybinding "M:," (make-handler "<"))
>   (keybinding "M:." (make-handler ">")))
> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


Hi everyone,

I've been playing around with this a little more; it looks like the
keybindings language might need some kind of warning in the documentation
saying that the 'keybinding' macro isn't very composable.  I had tried
something like:


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(module test-keybindings (lib "keybinding-lang.ss" "framework")
  (define (make-handler s)
    (lambda (editor event)
      (send editor insert (make-object string-snip% s))))

  (define (simple-bind trigger target)
    (keybinding trigger (make-handler target)))

  (simple-bind "M:," "<")
  (simple-bind "M:." ">"))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

but this had the surprising behavior of binding both M:. and M:. to the
greater than sign!



The reason for this is because each handler is assigned a
uniquely-identifying name based on the location of the 'keybinding' macro:

;; inside "keybinding-lang.ss" ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define-syntax (keybinding stx)
  (syntax-case stx ()
    [(_ key val)
     (with-syntax ([src (syntax-source stx)]
                   [line (syntax-line stx)]
                   [col (syntax-column stx)]
                   [pos (syntax-position stx)])
       (syntax (#%keybinding key val 'src 'line 'col 'pos)))]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

And unfortunately, this breaks terribly when I try using keybinding as a
function, since my two handlers will collide with the same name.



Would a good solution to this be adding some kind of uniquely identifying
gensym as part of the name?  I added a little to the underlying
%keybinding macro in the keybinding-lang language, and things appear to
work a little better.


I've put the updated collects/framework/keybinding-lang.ss file here:

    http://hkn.eecs.berkeley.edu/~dyoo/tmp/keybinding-lang.ss

With the small change from:

                    (let ([name (if (and line col)
                                    (format "~a:~a.~a" src line col)
                                    (format "~a:~a" src pos))]) ...)

to:

                    (let ([name
                           (string-append
                            (symbol->string (gensym)) ":"
                            (if (and line col)
                                (format "~a:~a.~a" src line col)
                                (format "~a:~a" src pos)))] ...)

things are working a little bit better for me now, and I can use the
'keybinding' in a definition without weird side effects.


Does this look ok?  I hope this helps!



Posted on the users mailing list.