DivaScheme: semi-structured programming editing for DrScheme
DivaScheme: semi-structured programming editing for DrScheme
(http://www.cs.brown.edu/research/plt/software/divascheme/)
============================================================
_About DivaScheme_
DivaScheme is an alternative set of key bindings for DrScheme. The
keystrokes that navigates sexps are essential to Scheme programmers,
but they are also very harsh on the wrists. The chord ctrl-alt-shift-f
is hardly ergonomic.
DivaScheme is an alternative. When DivaScheme is on, the most important
functions of DrScheme are available through unchorded keystrokes, and
the motion commands operate on sexps by default. DivaScheme also takes cares
of layout concerns. It automatically maintains the white spaces, the
indentation, and the balance of the parentheses.
Once installed, you can toggle DivaScheme on and off by pressing F4.
Like Vi, DivaScheme has a command mode and an insert mode. The command
mode contains code-editing key bindings, and almost all of them are
unchorded. These keys are bound in the DrScheme definitions editing
window. DivaScheme key bindings override the normal DrScheme key
bindings; at the times you need to use the normal key bindings of
DrScheme, strike F4 to disable DivaScheme momentarily, then strike F4
to bring DivaScheme back.
,--------------------------------------------------------------------------------.
| |
| Table 1 : _DivaScheme Editing Commands_ |
| |
| key command |
| |
| x cut |
| c copy |
| v paste |
| d delete |
| u undo |
| y redo |
| t transpose sexp |
| o join lines |
| |
| r replace, enter insert mode |
| w edit symbol, enter insert mode |
| |
| h insert before the current expression, enter insert mode |
| ; insert after the current expression, enter insert mode |
| |
| (, [ open parenthesis, enter insert mode |
| { open square brace, enter insert mode |
| ), ], or } close parenthesis |
| |
| F4 toggle DivaScheme on and off |
| |
`--------------------------------------------------------------------------------'
In DivaScheme, the _open_ command inserts both an opening and a
closing parenthesis. This way, DivaScheme ensures that all parentheses
in the program remain balanced. The _close_ command simply skips over
the next closing parenthesis (as opposed to inserting an
out-of-balance close parenthesis character).
The _replace_, _edit_, _insert_, and _open_ commands switch to insert
mode. While in insert mode, key strokes insert characters instead
of triggering commands, allowing the programmer to write the name of
Scheme identifiers. The ESC key leaves insert mode and returns to the
command mode. The CTRL-c key cancels the insert mode: it returns to
the command mode undoing any inserts done.
,---------------------------------------------------------.
| |
| Table 2 : _DivaScheme Insert Mode Commands_ |
| |
| key command |
| |
| esc return to command mode |
| ctrl-c, ctrl-g cancel insertion |
| (, [ open parenthesis |
| { open square brace |
| ), ], or } close parenthesis |
| alt-b bring |
| |
| tab dynamic auto-completion |
| |
`---------------------------------------------------------'
.============================================================
|
| _DivaScheme Tutorial #1 : Inserting Text_
|
|
| Using the command above, we can type a short Scheme expression:
|
| In an empty file, with DivaScheme on, press the following keys:
|
| [ * [ + space 1 space 2 ] esc a c shift-H v e ]
|
| This will insert the expression:
|
| (* (+ 1 2) (+ 1 2))
|
| Let's go over this key by key.
|
| Pressing "[" at the beginning of this sequence of keys builds
| a pair of parentheses and enters the insert mode. We then type
| the multiplication and the first subexpression, and type ESC to
| exit the insert mode. We use the navigation commands and the
| copy and paste commands of the command mode to copy the first
| subexpression. At this point the window contains this expression:
|
| (* (+ 1 2) $expr$ ---)
| ^
| |
| position of the cursor
|
| The $expr$ is a _placeholder_. As we type, DivaScheme inserts
| stand-ins for expressions that need to be filled in. In this example,
| $expr$ is a placeholder for the subsequent arguments to multiply. The
| --- symbol signifies that zero, one, or more expressions can take
| place for $expr$. So, when we fill $expr$ another $expr$ placeholder
| appears to its right.
|
| Using DivaScheme's motion commands, we can copy the first
| subexpression to the placeholder:
|
| keys pressed result
|
| [ * [ + space 1 space 2 ] inserts the first subexpression
| esc returns to command mode
| a moves to the previous s-expression,
| selects "(+ 1 2)"
| c copies "(+ 1 2)" to the clipboard
| shift-H jumps to placeholder $expr$
|
| v paste "(+ 1 2)" onto the placeholder
| (a new placeholder appears)
|
| e moves to the next s-expression
|
| ] collapse the placeholder and
| skips over the closing parenthesis
|
| The DrScheme window, now shows the expression we want:
|
| (* (+ 1 2) (+ 1 2))
|
|
`===========================================================
DivaScheme has the following motion commands to move between sexps and
between placeholders.
,--------------------------------------------------------------------------------.
| |
| Table 3 : _DivaScheme Moving Commands_ |
| |
| key command |
| |
| arrows standard character-based motion |
| |
| a previous sexp |
| e next sexp |
| i up |
| k down |
| j left |
| l right |
| |
| space extend, next motions will extend the selection |
| (press space again to turn off) |
| |
| shift-K out, move to enclosing sexp |
| shift-H move to the nearest placeholder |
| z return to the previous position (undoing if necessary) |
| |
| |
`--------------------------------------------------------------------------------'
The key "z" is bound to the command _cancel_, which acts as a
fine-grained undo. It reverts changes made to the cursor position as
well as changes to the text.
DivaScheme supports navigation via searching. The searching commands
only match prefixes of identifiers. They will not match characters in
the middle of an identifier, and will not match words inside of
comments. Searching selects the entire sexp whenever the search
matches the first symbol in the sexp. To select the first symbol
itself, execute the search then go to the next sexp to the right
by pressing the "l" key.
DivaScheme can also compute and jump to the definition point of an
identifier. Scheme Navigation Tags (_stags_) can be generated project-wide by selecting
"File/Generate Navigation Tags...". Select your project directory, and an STAGS
file will be generated there will an index of keywords for all .SS and .SCM files.
_generate-stags_
Alternatively, the command line utility $PLTHOME/bin/generate-stags
can be used to generate an STAGS file. This command line utility is
not automatically installed into $PLTHOME/bin, but can be installed
with the 'install-launchers.ss' module. install-launchers provides a
single function:
> install-launcher: -> void
> install-launcher: path -> void
With no arguments, installs the launchers into $PLTHOME/bin.
Otherwise, installs the launcher into the specified path.
The most direct installation is:
> (require (planet "install-launchers.ss" ("divascheme" "divascheme.plt" 1 3)))
> (install-launchers)
Once installed, generate-stags consumes the name of all the Scheme
source files composing your project, as command line arguments, and
will produce a file called STAGS in the current directory.
Load this file by selecting "File/Load Navigation Tags..." in the
menus of the main window of DrScheme. Note that DivaScheme
automatically load the STAGS file in the current directory when
DrScheme starts, if one is present.
Once a tag file is loaded, use the "." key to jump to the definition
point of an identifier. Also, the names mentioned in the tag file will be
considered as possible completions of identifier, when pressing the TAB key.
,-------------------------------------------------------------.
| |
| Table 4 : _DivaScheme Searching Commands_ |
| |
| key command |
| |
| s select the nearest match |
| f search forward |
| < search from the top of the file |
| > search from the bottom of the file |
| |
| n skip to the next match |
| p skip to the previous match |
| |
| . jump to definition |
| |
`-------------------------------------------------------------'
DivaScheme has a set of commands for rearranging nearby subexpressions
into a new expression.
The "m" key marks the current expression. The currently marked
expression is indicated with a orange highlight. The _bring_ command
(or the "b" key) moves the currently marked expression to the cursor,
then moves the mark to the next expression forward. This allows the
programmer to bring multiple subsequent expressions in quick
succession. Inversely, the _put_ command (on the shift-B key) sends
the current expression to the mark, and moves the mark forward.
Finally, the _exchange_ command switches the position of the
cursor with that of the mark (and vice-versa). When using the command _bring_ and
_put_, if no expression is currently marked, Divascheme gets the
next expression on the right of the cursor, by default.
Here is the summary of the rearranging command:
,--------------------------------------------------------------.
| |
| Table 5 : _DivaScheme Rearranging Commands_ |
| |
| key command |
| |
| m mark this |
| b bring here |
| shift-B put there |
| shift-M unmark |
| shift-X exchange the selection and the mark |
| |
`--------------------------------------------------------------'
.===========================================================
|
| _DivaScheme Tutorial #2 : Rearranging Text_
|
|
| You can use the mark and the bring/put commands to rebuild an
| expression into a similar expression. For instance, we can rewrite a
| LET-LAMBDA into a DEFINE as follow:
|
| Starting with this text:
|
| (let ([foo (lambda (x y) (+ x y))])
| (foo 1 2))
|
| we will transform the LET expression into this:
|
| (define foo
| (lambda (x y) (+ x y))
|
| (foo 1 2)
|
| by typing these keys :
|
| s l e t enter
| up-arrow
| enter up-arrow
| enter up-arrow inserts two empty lines
| [ opens a parenthesis, goes to insert mode
| d e f i n e space inserts the define template
| esc returns to command mode
|
| The buffer now has a define s-expression, with the selection on $expr$.
|
| (define $expr$ ---)
|
| (let ([foo (lambda (x y) (+ x y))])
| (foo 1 2))
|
| m marks the placeholder $expr$
| s f o o enter selects "[foo (lambda (x y) (+ x y))]"
| l selects "foo"
| shift-B moves the name "foo" to the define
| shift-B moves the lambda expression into the define
| shift-H selects the placeholder
| ] closes the argument placeholder
| s l a m enter selects "(lambda)"
| enter moves the lambda down one line
|
| After these, the text looks like this:
|
| (define foo
| (lambda (x y) (+ x y)))
|
| (let ([])
| (foo 1 2))
|
| Continuing:
|
| s foo enter selects the first foo definition
| n move to the next occurence of foo
| x cuts the foo application
| shift-K selects the surrounding let
| v pastes the foo application
|
| At the end of this command sequence, the resulting text is:
|
| (define foo
| (lambda (x y) (+ x y)))
|
| (foo 1 2)
|
| as we wanted.
|
`===========================================================
The key bindings of DivaScheme are customizable. In the DivaScheme
tab of the preferences dialog box you will find a list of all the
active key bindings. This list is editable, as long as it remains an
association list mapping keystrokes to function names. In addition to
the DivaScheme functions (with the "diva:" prefix), the right hand
side of each pair can refer to any text editing function listed in the
entry for _add-text-keymap-functions_, in the Help Desk.
DivaScheme has an alternative set of key bindings for people using a
Dvorak keyboard. On a Dvorak, the movement key "i, ,j, k, l" no
longer form an inverted T, so DivaScheme uses "e, q, j, k" instead.
Similarly, DivaScheme has a set of key bindings for people using the
orbiTouch key-less keyboard, so that the movement keys form a sensible
mnemonic. You can enable these alternative key bindings via the
preference dialog box.
,---------------------------------------------------------.
| |
| Table 6 : _DivaScheme on a Dvorak keyboard_ |
| |
| key command |
| |
| e up |
| j down |
| q left |
| k right |
| ` previous sexp |
| , next sexp |
| |
| shift-E out |
| |
`---------------------------------------------------------'
,-------------------------------------------------------------.
| |
| Table 7 : _DivaScheme on an orbiTouch keyboard_ |
| |
| key command motion |
| |
| 8 up up + down |
| = down down-left + down |
| 0 left left + down |
| 6 right right + down |
| 9 insert before up-left + down |
| 7 insert after up-right + down |
| |
| 5 previous page left + down-left |
| 1 next page right + down-left |
| 2 forward char up-right + down-left |
| 4 backward char up-left + down-left |
| 3 out up + down-left |
| |
`-------------------------------------------------------------'
============================================================
_Credits_
DivaScheme was designed and implemented by Romain Legendre, Guillaume
Marceau, Danny Yoo, Kathi Fisler and Shriram Krishnamurthi. We thank
Jay McCarthy for his help. Send comments and bug reports to [email protected].
"Your future dream is a shopping scheme."