moved the 'send to repl' keystrokes to the manual (and added a test

suite to make sure the example code in the manual doesn't get stale)
This commit is contained in:
Robby Findler 2011-09-23 16:36:28 -05:00
parent a553cd7a4b
commit abda257295
7 changed files with 150 additions and 70 deletions

View File

@ -281,13 +281,6 @@ TODO
(send drs-bindings-keymap map-function "c:x;0" "collapse")
(send drs-bindings-keymap map-function "c:x;2" "split")
(send drs-bindings-keymap map-function "esc;c:x" "send-toplevel-form-to-repl")
(send drs-bindings-keymap map-function "m:c:x" "send-toplevel-form-to-repl")
(send drs-bindings-keymap map-function "c:c;c:e" "send-toplevel-form-to-repl")
(send drs-bindings-keymap map-function "c:c;c:r" "send-selection-to-repl")
(send drs-bindings-keymap map-function "c:c;m:e" "send-toplevel-form-to-repl-and-go")
(send drs-bindings-keymap map-function "c:c;m:r" "send-selection-to-repl-and-go")
(send drs-bindings-keymap map-function "c:c;c:z" "move-to-interactions")
(for ([i (in-range 1 10)])

View File

@ -4013,48 +4013,9 @@ module browser threading seems wrong.
(send ed set-position (- (srcloc-position srcloc) 1))
(send ed set-caret-owner #f 'global))
(define/public (send-toplevel-form-to-repl shift-focus?)
(define defs (get-definitions-text))
(when (= (send defs get-start-position)
(send defs get-end-position))
(let loop ([pos (send defs get-start-position)])
(define next-up (send defs find-up-sexp pos))
(cond
[next-up (loop next-up)]
[else
(send-range-to-repl pos
(send defs get-forward-sexp pos)
shift-focus?)]))))
(define/public (send-selection-to-repl shift-focus?)
(define defs (get-definitions-text))
(send-range-to-repl (send defs get-start-position) (send defs get-end-position) shift-focus?))
(define/public (move-to-interactions)
(ensure-rep-shown (get-interactions-text))
(send (get-interactions-canvas) focus))
(define/private (send-range-to-repl start end shift-focus?)
(unless (= start end)
(define defs (get-definitions-text))
(define ints (get-interactions-text))
(send defs move/copy-to-edit ints start end (send ints last-position) #:try-to-move? #f)
;; clear out the whitespace after the copied down thing
(let loop ()
(define last-pos (- (send ints last-position) 1))
(when (last-pos . > . 0)
(define last-char (send ints get-character last-pos))
(when (char-whitespace? last-char)
(send ints delete last-pos (+ last-pos 1))
(loop))))
;; insert a newline
(send ints insert "\n" (send ints last-position) (send ints last-position))
(ensure-rep-shown ints)
(when shift-focus? (send (get-interactions-canvas) focus))
(send ints do-submission)))
;

View File

@ -950,16 +950,15 @@
If conflicting modifiers are provided, the ones later in the list are used.})
(proc-doc/names
(proc-doc
test:menu-select
(string? string? . -> . void?)
(menu item)
@{Selects the menu-item named @racket[item] in the menu named @racket[menu].
(->i ([menu string?]) () #:rest [items (listof string?)] [res void?])
@{Selects the menu-item named by the @racket[item]s in the menu named @racket[menu].
@italic{Note:}
The string for the menu item does not include its keyboard equivalent.
For example, to select ``New'' from the ``File'' menu,
use ``New'', not ``New Ctrl+m n''.})
use ``New'', not ``New Ctrl+N''.})
(proc-doc/names
test:mouse-click

View File

@ -1,12 +1,14 @@
#lang scheme/base
#lang racket/base
(require scribble/manual
(for-label scheme))
(for-label racket
racket/gui/base))
(provide HtDP
drlang
(all-from-out scribble/manual)
(for-label (all-from-out scheme)))
(for-label (all-from-out racket
racket/gui/base)))
(define HtDP
(italic "How to Design Programs"))

View File

@ -0,0 +1,61 @@
#lang s-exp framework/keybinding-lang
(require drracket/tool-lib)
(keybinding "c:c;c:e" (lambda (ed evt) (send-toplevel-form ed #f)))
(keybinding "c:c;c:r" (lambda (ed evt) (send-selection ed #f)))
(keybinding "c:c;m:e" (lambda (ed evt) (send-toplevel-form ed #t)))
(keybinding "c:c;m:r" (lambda (ed evt) (send-selection ed #t)))
(define/contract (send-toplevel-form defs shift-focus?)
(-> any/c boolean? any)
(when (is-a? defs drracket:unit:definitions-text<%>)
(when (= (send defs get-start-position)
(send defs get-end-position))
(let loop ([pos (send defs get-start-position)])
(define next-up (send defs find-up-sexp pos))
(cond
[next-up (loop next-up)]
[else
(send-range-to-repl defs
pos
(send defs get-forward-sexp pos)
shift-focus?)])))))
(define/contract (send-selection defs shift-focus?)
(-> any/c boolean? any)
(when (is-a? defs drracket:unit:definitions-text<%>)
(send-range-to-repl defs
(send defs get-start-position)
(send defs get-end-position)
shift-focus?)))
(define/contract (send-range-to-repl defs start end shift-focus?)
(-> (is-a?/c drracket:unit:definitions-text<%>)
exact-positive-integer?
exact-positive-integer?
boolean?
any)
(unless (= start end)
(define ints (send (send defs get-tab) get-ints))
(define frame (send (send defs get-tab) get-frame))
(send defs move/copy-to-edit
ints start end
(send ints last-position)
#:try-to-move? #f)
(let loop ()
(define last-pos (- (send ints last-position) 1))
(when (last-pos . > . 0)
(define last-char (send ints get-character last-pos))
(when (char-whitespace? last-char)
(send ints delete last-pos (+ last-pos 1))
(loop))))
(send ints insert
"\n"
(send ints last-position)
(send ints last-position))
(send frame ensure-rep-shown ints)
(when shift-focus? (send (send ints get-canvas) focus))
(send ints do-submission)))

View File

@ -1,7 +1,9 @@
#lang scribble/doc
@(require "common.rkt"
scribble/struct scribble/bnf racket/list mrlib/tex-table
(for-label racket/gui/base))
scribble/struct scribble/bnf
racket/list racket/runtime-path racket/port
mrlib/tex-table
(for-label drracket/tool-lib))
@(define (keybinding key . desc)
(let* ([keys (if (string? key) (list key) key)]
@ -91,8 +93,6 @@ inspired by Emacs.
@keybinding["A-C-down"]{move down into an embedded editor}
@keybinding["C-C C-Z"]{move the cursor to the interactions window}
@keybinding["C-F6"]{move the cursor from the definitions
window to the interactions window (or the search window, if it is open).}
]
@section{Editing Operations}
@ -156,18 +156,6 @@ window to the interactions window (or the search window, if it is open).}
@itemize[
@keybinding["F5"]{Run}
@keybinding["M-C-x"]{Copy the top-level form surrounding the insertion point to the interactions window
and submit it for evaluation}
@keybinding["C-c C-e"]{Copy the top-level form surrounding the insertion point to the interactions window
and submit it for evaluation}
@keybinding["C-c M-e"]{Copy the top-level form surrounding the insertion point to the interactions window,
submit it for evaluation, and move the focus to the interations window}
@keybinding["C-c C-r"]{Copy the selection to the interactions window
and submit it for evaluation}
@keybinding["C-c C-r"]{Copy the selection to the interactions window
and submit it for evaluation}
@keybinding["C-c M-r"]{Copy the selection to the interactions window,
submit it for evaluation, and move the focus to the interactions window}
]
@ -244,3 +232,32 @@ s-exp framework/keybinding-lang
Note that DrRacket does not reload this file automatically when you
make a change, so you'll need to restart DrRacket to see changes to
the file.
@section{Sending Program Fragments to the REPL}
@index['("Emacs keybindings")]Users comfortable with Emacs and the conventional Lisp/Scheme-style
of interaction with an ``inferior process'' commonly request
keybindings in DrRacket that send program fragments to be evaluated
at the prompt. This style of interaction is fraught with difficulty,
especially for beginners, and so DrRacket, by default, does not support
it. Instead, clicking DrRacket's ``Run'' button starts with a clean slate
and sends the entire contents of the definitions window, ensuring that
the state in the REPL matches what you would expect by reading
the source code of the program.
That said, it is difficult for some people to switch to this new mode and,
in some cases (for example when most of the interesting state is not
in the program but in an external database or in the filesystem), using
the contentional keystrokes may make sense.
So, the remainder of this section is an example keybindings file that
adds the ability to send expressions piecemeal to the interactions
window. It also demonstrates how to pull together a bunch of pieces
of DrRacket's implementation and its libraries to implement keystrokes.
@(define-runtime-path incremental-keybindings.rkt "incremental-keybindings.rkt")
@(let ([sp (open-output-string)])
(call-with-input-file incremental-keybindings.rkt
(λ (port)
(copy-port port sp)))
(codeblock (get-output-string sp)))

View File

@ -0,0 +1,47 @@
#lang racket/base
#|
Adds the incremental-keybindings.rkt file (also shown in the docs)
to DrRacket and then tries out the keystrokes.
|#
(require "private/drracket-test-util.rkt"
framework/test
racket/class)
(fire-up-drscheme-and-run-tests
(λ ()
(define drs-frame (wait-for-drscheme-frame))
(use-get/put-dialog
(λ ()
(test:menu-select "Edit" "Keybindings" "Add User-defined Keybindings..."))
(collection-file-path "incremental-keybindings.rkt"
"scribblings"
"drracket"))
(insert-in-definitions drs-frame "#lang racket/base\n")
(do-execute drs-frame)
(insert-in-definitions drs-frame "(+ 1 (+ 2 3))")
(queue-callback/res
(λ ()
(define defs (send drs-frame get-definitions-text))
(send defs set-position (+ (send defs paragraph-start-position 1) 5))))
(test:keystroke #\c '(control))
(test:keystroke #\e '(control))
(wait-for-computation drs-frame)
(test:keystroke 'right '(alt shift))
(test:keystroke #\c '(control))
(test:keystroke #\r '(control))
(wait-for-computation drs-frame)
(define got
(queue-callback/res
(λ ()
(define ints (send drs-frame get-interactions-text))
(send ints get-text
(send ints paragraph-start-position 2)
(send ints last-position)))))
(unless (equal? got "> (+ 1 (+ 2 3))\n6\n> (+ 2 3)\n5\n> ")
(error 'incrementalkeybindings-test.rkt "failed-test; got ~s" got))))