parent
8d0db4cd35
commit
f8974781fe
80
collects/xrepl/doc-utils.rkt
Normal file
80
collects/xrepl/doc-utils.rkt
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#lang racket/base
|
||||||
|
|
||||||
|
(require scribble/manual scribble/core scribble/decode
|
||||||
|
racket/list racket/sandbox)
|
||||||
|
|
||||||
|
(provide (all-from-out scribble/manual)
|
||||||
|
RL GUIDE cmd defcmd check-all-documented)
|
||||||
|
|
||||||
|
(define RL '(lib "readline/readline.scrbl"))
|
||||||
|
(define GUIDE '(lib "scribblings/guide/guide.scrbl"))
|
||||||
|
|
||||||
|
(define commands
|
||||||
|
(let ([c #f])
|
||||||
|
(λ ()
|
||||||
|
(unless c
|
||||||
|
(define e (call-with-trusted-sandbox-configuration
|
||||||
|
(λ () (make-evaluator 'racket/base))))
|
||||||
|
(e '(require xrepl/xrepl))
|
||||||
|
(e '(current-namespace (module->namespace 'xrepl/xrepl)))
|
||||||
|
(set! c (e '(for/list ([c (in-list commands-list)])
|
||||||
|
(list (car (command-names c))
|
||||||
|
(cdr (command-names c))
|
||||||
|
(command-argline c)
|
||||||
|
(command-blurb c)))))
|
||||||
|
(kill-evaluator e))
|
||||||
|
c)))
|
||||||
|
(define documented '())
|
||||||
|
|
||||||
|
(define (cmd* name0 . more)
|
||||||
|
(define name (if (symbol? name0) name0 (string->symbol name0)))
|
||||||
|
(define full-name
|
||||||
|
(or (and (assq name (commands)) name)
|
||||||
|
(for/or ([c (in-list (commands))]) (and (memq name (cadr c)) (car c)))
|
||||||
|
(error 'cmd "unknown command: ~s" name)))
|
||||||
|
(define content
|
||||||
|
(litchar (let ([s (format ",~a" name)])
|
||||||
|
(if (pair? more) (apply string-append s " " more) s))))
|
||||||
|
(link-element "plainlink" content `(xrepl ,(format "~a" full-name))))
|
||||||
|
|
||||||
|
(define-syntax-rule (cmd name more ...) (cmd* 'name more ...))
|
||||||
|
|
||||||
|
(define (cmd-index name)
|
||||||
|
(define namestr (format ",~a" name))
|
||||||
|
(define tag `(xrepl ,(format "~a" name)))
|
||||||
|
(define content (cmd* name))
|
||||||
|
(define ielem
|
||||||
|
(index-element #f content tag (list namestr) (list content)
|
||||||
|
'xrepl-command))
|
||||||
|
(toc-target-element #f (list ielem) tag))
|
||||||
|
|
||||||
|
(define (defcmd* name . text)
|
||||||
|
(set! documented (cons name documented))
|
||||||
|
(define-values [other-names argline blurb]
|
||||||
|
(apply values (cond [(assq name (commands)) => cdr]
|
||||||
|
[else (error 'defcmd "unknown command: ~s" name)])))
|
||||||
|
(define header
|
||||||
|
(list (cmd-index name) (litchar (string-append " " (or argline "")))))
|
||||||
|
(define desc
|
||||||
|
(list (hspace 2) (make-element 'italic blurb)))
|
||||||
|
(define synonyms
|
||||||
|
(and (pair? other-names)
|
||||||
|
(list (hspace 2)
|
||||||
|
"[Synonyms: "
|
||||||
|
(add-between (map (λ (n) (litchar (format ",~a" n)))
|
||||||
|
other-names)
|
||||||
|
" ")
|
||||||
|
"]")))
|
||||||
|
(splice
|
||||||
|
(list* (tabular #:style 'boxed `((,header) (,desc)
|
||||||
|
,@(if synonyms `((,synonyms)) `())))
|
||||||
|
"\n" "\n" text)))
|
||||||
|
|
||||||
|
(define-syntax-rule (defcmd name text ...) (defcmd* 'name text ...))
|
||||||
|
|
||||||
|
(define (check-all-documented)
|
||||||
|
(unless (= (length documented) (length (remove-duplicates documented)))
|
||||||
|
(error 'xrepl-docs "some commands were documented multiple times"))
|
||||||
|
(let ([missing (remove* documented (map car (commands)))])
|
||||||
|
(when (pair? missing)
|
||||||
|
(error 'xrepl-docs "missing command documentation: ~s" missing))))
|
|
@ -1,3 +1,5 @@
|
||||||
#lang setup/infotab
|
#lang setup/infotab
|
||||||
|
|
||||||
(define name "eXtended REPL")
|
(define name "eXtended REPL")
|
||||||
|
|
||||||
|
(define scribblings '(("xrepl.scrbl" () (tool-library))))
|
||||||
|
|
484
collects/xrepl/xrepl.scrbl
Normal file
484
collects/xrepl/xrepl.scrbl
Normal file
|
@ -0,0 +1,484 @@
|
||||||
|
#lang scribble/doc
|
||||||
|
@(require scribble/manual "doc-utils.rkt"
|
||||||
|
scribble/decode (only-in scribble/core)
|
||||||
|
(for-label racket readline racket/help racket/enter
|
||||||
|
racket/trace profile))
|
||||||
|
|
||||||
|
@title{XREPL: eXtended REPL}
|
||||||
|
@author+email["Eli Barzilay" "eli@barzilay.org"]
|
||||||
|
|
||||||
|
@defmodule[xrepl]{
|
||||||
|
The @filepath{xrepl} collection extends the @exec{racket} @tech[#:doc
|
||||||
|
GUIDE]{REPL} significantly, turning it into a more useful tool for
|
||||||
|
interactive exploration and development. This includes ``meta
|
||||||
|
commands'', using readline, keeping past evaluation results, and
|
||||||
|
more.}
|
||||||
|
|
||||||
|
@; ---------------------------------------------------------------------
|
||||||
|
@section{Installing XREPL}
|
||||||
|
|
||||||
|
To use XREPL, start @exec{racket} and enter @racket[(require xrepl)].
|
||||||
|
You will know that it works when the prompt changes to a @litchar{->},
|
||||||
|
and, if you're working on a capable terminal, you will now have readline
|
||||||
|
editing. You can also start @exec{racket} and ask for XREPL to be
|
||||||
|
loaded using command-line arguments:
|
||||||
|
@commandline{racket -il xrepl}
|
||||||
|
|
||||||
|
If you want to enable XREPL automatically, add this expression to your
|
||||||
|
Racket initialization file.
|
||||||
|
@margin-note*{To load XREPL conditionally (e.g., not in older Racket
|
||||||
|
versions), you can use @racket[(dynamic-require 'xrepl #f)]. This
|
||||||
|
is a plain expression that can be placed inside @racket[when] and
|
||||||
|
elsewhere.}
|
||||||
|
An easy way to do the necessary editing is to enter @cmd[install!],
|
||||||
|
which will inspect and edit your initialization file (it will describe
|
||||||
|
the change and ask for your permission). Alternatively, you can edit
|
||||||
|
the file directly: on Unix, it is @filepath{~/.racketrc}, and for
|
||||||
|
other platforms evaluate @racket[(find-system-path 'init-file)] to see
|
||||||
|
where it is.
|
||||||
|
|
||||||
|
XREPL will set up a readline-based reader, so you do not need to load
|
||||||
|
that yourself. If your initialization file was previously set to load
|
||||||
|
readline via @racket[install-readline!], the @cmd[install!] command
|
||||||
|
will (notify you and) remove it. If you added it yourself, consider
|
||||||
|
removing it. (This is not strictly needed, but XREPL is slightly
|
||||||
|
better at detecting when to use readline.)
|
||||||
|
|
||||||
|
@; ---------------------------------------------------------------------
|
||||||
|
@section{Meta REPL Commands}
|
||||||
|
|
||||||
|
Most of the XREPL extensions are implemented as meta commands. These
|
||||||
|
commands are entered at the REPL, prefixed by a @litchar{,} and followed
|
||||||
|
by the command name. Note that several commands correspond directly to
|
||||||
|
Racket functions (e.g., @cmd[exit]) --- but since they work outside of
|
||||||
|
your REPL, they can be used even if the matching bindings are not
|
||||||
|
available.
|
||||||
|
|
||||||
|
@; ---------------------------------
|
||||||
|
@subsection{Generic Commands}
|
||||||
|
|
||||||
|
@defcmd[help]{
|
||||||
|
Without an argument, displays a list of all known commands. Specify a
|
||||||
|
command to get help specific to that command.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[exit]{
|
||||||
|
Exits Racket, optionally with an error code (see @racket[exit]).
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[cd]{
|
||||||
|
Sets the @racket[current-directory] to the given path. If no path is
|
||||||
|
specified, use your home directory. Path arguments are passed through
|
||||||
|
@racket[expand-user-path] so you can use @litchar{~}. An argument of
|
||||||
|
@litchar{-} means ``the previous path''.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[pwd]{
|
||||||
|
Reports the value of @racket[current-directory].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[shell]{
|
||||||
|
Use @cmd[shell] (or @cmd[sh]) to run a generic shell command (via
|
||||||
|
@racket[system]). For convenience, a few synonyms are provided ---
|
||||||
|
they run the specified executables (still using @racket[system]).
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[edit]{
|
||||||
|
Runs an editor, as specified by your @envvar{EDITOR} environment
|
||||||
|
variable, with the given file/s arguments. If no files are specified
|
||||||
|
and the REPL is currently inside a module's namespace, then the file
|
||||||
|
for that module is used. If the @envvar{EDITOR} environment variable
|
||||||
|
is not set, use the @cmd[drracket] command instead.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[drracket]{
|
||||||
|
Runs DrRacket with the specified file/s. If no files are given, and
|
||||||
|
the REPL is currently inside a module, the file for that module is
|
||||||
|
used.
|
||||||
|
|
||||||
|
DrRacket is launched directly, without starting a new subprocess, and
|
||||||
|
it is then kept running in a hidden window so further invocations are
|
||||||
|
immediate. (When this command is used for the first time, you will
|
||||||
|
see DrRacket start as usual, and then its window will disappear ---
|
||||||
|
that window is keeping DrRacket ready for quick editing.)
|
||||||
|
|
||||||
|
In addition to file arguments, arguments can specify one of a few
|
||||||
|
flags for additional operations:
|
||||||
|
@itemize[
|
||||||
|
@item{@litchar{-new}: opens a new editing window. This is the default
|
||||||
|
when no files are given and the REPL is not inside a module,}
|
||||||
|
@item{@litchar{-open}: opens the specified file/s (or the current
|
||||||
|
module's file). This is the default when files are given or when
|
||||||
|
inside a module.}
|
||||||
|
@item{@litchar{-quit}: exits the running DrRacket instance. Quitting
|
||||||
|
DrRacket is usually not necessary. Therefore, if you try to quit it
|
||||||
|
from the DrRacket window, it will instead just close the window but
|
||||||
|
DrRacket will still be running in the background. Use this command
|
||||||
|
in case there is some exceptional problem that requires actually
|
||||||
|
quitting the IDE. (Once you do so, future uses of this command will
|
||||||
|
start a fresh instance.)}]
|
||||||
|
}
|
||||||
|
|
||||||
|
@; ---------------------------------
|
||||||
|
@subsection{Binding Information}
|
||||||
|
|
||||||
|
@defcmd[apropos]{
|
||||||
|
Searches for known bindings in the current namespace. The arguments
|
||||||
|
specify which binding to look for: use a symbol (without a
|
||||||
|
@litchar{'}) to look for bindings that contain that name, and use a
|
||||||
|
regexp (e.g., @racket[#rx"..."]) to use a regexp for the search.
|
||||||
|
Multiple arguments are and-ed together.
|
||||||
|
|
||||||
|
If no arguments are given, @emph{all} bindings are listed.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[describe]{
|
||||||
|
For each of the specified names, describe where where it is coming
|
||||||
|
from and how it was defined if it names a known binding. In addition,
|
||||||
|
desribe the module (list its imports and exports) that is named by
|
||||||
|
arguments that are known module names.
|
||||||
|
|
||||||
|
By default, bindings are searched for at the runtime level (phase 0).
|
||||||
|
You can add a different phase level for identifier lookups as a first
|
||||||
|
argument. In this case, only a binding can be described, even if the
|
||||||
|
same name is a known module.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[doc]{
|
||||||
|
Uses Racket's @racket[help] to browse the documentation, look for a
|
||||||
|
binding, etc. Note that this can be used even in languages that don't
|
||||||
|
have the @racket[help] binding.
|
||||||
|
}
|
||||||
|
|
||||||
|
@; ---------------------------------
|
||||||
|
@subsection{Requiring and Loading Files}
|
||||||
|
|
||||||
|
@defcmd[require]{
|
||||||
|
Most arguments are passed to @racket[require] as is. As a
|
||||||
|
convenience, if an argument specifies an existing file name, then use
|
||||||
|
its string form to specify the require, or use a @racket[file] in case
|
||||||
|
of an absolute path. In addition, an argument that names a known
|
||||||
|
symbolic module name (e.g., one that was defined on the REPL, or a
|
||||||
|
builtin module like @racket[#%network]), then its quoted form is used.
|
||||||
|
(Note that these shorthands do not work inside require subforms like
|
||||||
|
@racket[only-in].)
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[require-reloadable]{
|
||||||
|
Same as @cmd[require], but arranges to load the code in a way that
|
||||||
|
makes it possible to reload it later, or if a module was already
|
||||||
|
loaded (using this command) then reload it. Note that the arguments
|
||||||
|
should be simple specifications, without any require macros. If no
|
||||||
|
arguments are given, use arguments from the last use of this command
|
||||||
|
(if any).
|
||||||
|
|
||||||
|
Module reloading is enabled by turnning off the
|
||||||
|
@racket[compile-enforce-module-constants] parameter --- note that this
|
||||||
|
prohibits some opimizations, since the compiler assumes that all
|
||||||
|
bindings may change.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[enter]{
|
||||||
|
Uses @racket[enter!] to have the REPL go `inside' a given module's
|
||||||
|
namespace. A module name can specify an existing file as with the
|
||||||
|
@cmd[require-reloadable] command. If no module is given, and the REPL
|
||||||
|
is already in some module's namespace, then `enter!' is used with that
|
||||||
|
module, causing it to reload if needed. Using @racket[#f] makes it go
|
||||||
|
back to the toplevel namespace.
|
||||||
|
|
||||||
|
Note that this can be used even in languages that don't have the
|
||||||
|
@racket[enter!] binding. In addition, @racket[enter!] is used in a
|
||||||
|
way that does not make it require itself into the target namespace.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[toplevel]{
|
||||||
|
Makes the REPL go back to the toplevel namespace. Same as using the
|
||||||
|
@cmd[enter] command with a @racket[#f] argument.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[load]{
|
||||||
|
Uses @racket[load] to load the specified file(s).
|
||||||
|
}
|
||||||
|
|
||||||
|
@; ---------------------------------
|
||||||
|
@subsection{Debugging}
|
||||||
|
|
||||||
|
@defcmd[time]{
|
||||||
|
Times execution of an expression (or expressions). This is similar to
|
||||||
|
@racket{time} but the information that is displayed is a bit easier to
|
||||||
|
read.
|
||||||
|
|
||||||
|
In addition, you can provide an initial number to specify repeating
|
||||||
|
the evaluation a number of times. In this case, each iteration is
|
||||||
|
preceded by two garbage collections, and when the iteration is done
|
||||||
|
its timing information and evaluation result(s) are displayed. When
|
||||||
|
the requested number of repetitions is done, some extreme results are
|
||||||
|
removed (top and bottom 2/7ths), and the remaining results are be
|
||||||
|
averaged. Finally, the resulting value(s) are from the last run are
|
||||||
|
returned (and can be accessed via the bindings for the last few
|
||||||
|
results, see @secref["past-vals"]).
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[trace]{
|
||||||
|
Traces the named function (or functions), using @racket[trace].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[untrace]{
|
||||||
|
Untraces the named function (or functions), using @racket[untrace].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[errortrace]{
|
||||||
|
@racketmodname[errortrace] is a useful Racket library which can
|
||||||
|
provide a number of useful services like precise profiling, test
|
||||||
|
coverage, and accurate error information. However, using it can be a
|
||||||
|
little tricky. @cmd[errortrace] and a few related commands fill this
|
||||||
|
gap, making @racketmodname[errortrace] easier to use.
|
||||||
|
|
||||||
|
@cmd[errortrace] controls global use of @racketmodname[errortrace].
|
||||||
|
With a flag argument of @litchar{+} errortrace instrumentation is
|
||||||
|
turned on, with @litchar{-} it is turned off, and with no arguments it
|
||||||
|
is toggled. In addition, a @litchar{?} flag displays instrumentation
|
||||||
|
state.
|
||||||
|
|
||||||
|
Remember that @racketmodname[errortrace] instrumentation hooks into
|
||||||
|
the Racket compiler, and applies only to source code that gets loaded
|
||||||
|
from source and therefore compiled. Therefore, you should use it
|
||||||
|
@emph{before} loading the code that you want to instrument.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[profile]{
|
||||||
|
This command can perform profiling of code in one of two very
|
||||||
|
different ways: either statistical profiling via the
|
||||||
|
@racketmodname[profile] library, or using the exact profiler feature
|
||||||
|
of @racketmodname[errortrace].
|
||||||
|
|
||||||
|
When given a parenthesized expression, @cmd[profile] will run it via
|
||||||
|
the statistical profiler, as with the @racket[profile] form, reporting
|
||||||
|
results as usual. This profiler adds almost no overhead, and it
|
||||||
|
requires no special setup. In particular, it does not require
|
||||||
|
pre-compiling code in a special way. However, there are some
|
||||||
|
imprecise elements to this profiling: the profiler samples stack
|
||||||
|
snapshots periodically which can miss certain calls, and it is also
|
||||||
|
sensitive to some compiler optimizations like inlining procedures and
|
||||||
|
thereby not showing them in the displayed analysis. See
|
||||||
|
@other-doc['(lib "profile/scribblings/profile.scrbl")] for more
|
||||||
|
information.
|
||||||
|
|
||||||
|
In the second mode of operation, @cmd[profile] uses the precise
|
||||||
|
@racketmodname[errortrace] profiler. This profiler produces precise
|
||||||
|
results, but like other uses of the @racketmodname[errortrace], it
|
||||||
|
must be enabled before loading the code that is to be profiled. It
|
||||||
|
can add noticeable overhead (potentially affecting the reported
|
||||||
|
runtimes), but the results are accurate in the sense that no procedure
|
||||||
|
is skipped. (For additional details, see
|
||||||
|
@other-doc['(lib "errortrace/scribblings/errortrace.scrbl")].)
|
||||||
|
|
||||||
|
In this mode, the arguments are flags that control the profiler. A
|
||||||
|
@litchar{+} flag turns the profiler on --- and as usual with
|
||||||
|
@racketmodname[errortrace] functionality, this applies to code that is
|
||||||
|
compiled from now on. A @litchar{-} flag turns this instrumentation
|
||||||
|
off, and without any flags it is toggled. Once the profiler is
|
||||||
|
enabled, you can run some code and then use this command to report
|
||||||
|
profiling results: use @litchar{*} to show profiling results by time,
|
||||||
|
and @litchar{#} for the results by counts. Once you've seen the
|
||||||
|
results, you can evaluate additional code to collect more profiling
|
||||||
|
information, or you can reset the results with a @litchar{!} flag.
|
||||||
|
You can also combine several flags to perform the associated
|
||||||
|
operations, for example, @cmd[prof]{*!-} will show the accumulated
|
||||||
|
results, clear them, and turn profiler instrumentation off.
|
||||||
|
|
||||||
|
Note that using @emph{any} of these flags turns errortrace
|
||||||
|
instrumentation on, even @cmd[prof]{-} (or no flags). Use the
|
||||||
|
@cmd[errortrace] command to turn off instrumentation completely.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[execution-counts]{
|
||||||
|
This command makes it easy to use the execution counts functionality
|
||||||
|
of @racketmodname[errortrace]. Given a file name (or names),
|
||||||
|
@cmd[execution-counts] will enable errortrace instrumentation for
|
||||||
|
coverage, require the file(s), display the results, disables coverage,
|
||||||
|
and disables instrumentation (if it wasn't previously turned on).
|
||||||
|
This is useful as an indication of how well the test coverage is for
|
||||||
|
some file.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[coverage]{
|
||||||
|
Runs a given file and displays coverage information for the run. This
|
||||||
|
is somewhat similar to the @cmd[execution-counts] command, but instead
|
||||||
|
of using @racketmodname[errortrace] directly, it runs the file in a
|
||||||
|
(trusted) sandbox, using the @racketmodname[racket/sandbox] library
|
||||||
|
and its ability to provide coverage information.
|
||||||
|
}
|
||||||
|
|
||||||
|
@; ---------------------------------
|
||||||
|
@subsection{Miscellaneous Commands}
|
||||||
|
|
||||||
|
@defcmd[switch-namespace]{
|
||||||
|
This powerful command controls the REPL's namespace. While
|
||||||
|
@cmd[enter] can be used to make the REPL go into the namespace of a
|
||||||
|
specific module, the @cmd[switch-namespace] command can switch between
|
||||||
|
@emph{toplevel namespaces}, allowing you to get multiple separate
|
||||||
|
``workspaces''.
|
||||||
|
|
||||||
|
Namespaces are given names that are symbols or integers, where
|
||||||
|
@litchar{*} is the name for the first initial namespace, serving as
|
||||||
|
the default one. These names are not bindings --- they are only used
|
||||||
|
to label the known namespaces.
|
||||||
|
|
||||||
|
The most basic usage for this command is to simply specify a new name.
|
||||||
|
A namespace that corresponds to that name will be created and the REPL
|
||||||
|
will switch to that namespace. The prompt will now indicate this
|
||||||
|
namespace's name. The name is usually insignificant, except when it
|
||||||
|
is a @racket[require]-able module: in this case, the new namespace is
|
||||||
|
initialized to use that module's bindings. For example,
|
||||||
|
@cmd[switch]{racket/base} creates a new namespace that is called
|
||||||
|
@litchar{racket/base} and initializes it with
|
||||||
|
@racketmodname[racket/base]. For all other names, the new namespace
|
||||||
|
is initialized the same as the current one.
|
||||||
|
|
||||||
|
Additional @cmd[switch] uses:
|
||||||
|
@itemize[
|
||||||
|
@item{@cmd[switch]{!} --- reset the current namespace, recreating it
|
||||||
|
using the same initial library. Note that it is forbidden to reset
|
||||||
|
the default initial namespace, the one named @litchar{*} --- this
|
||||||
|
namespace corresponds to the one that Racket was started with, and
|
||||||
|
where XREPL was initialized. There is no technical reason for
|
||||||
|
forbidding this, but doing so is not useful as no resources will
|
||||||
|
actually be freed.}
|
||||||
|
@item{@cmd[switch]{! <module>} --- resets the current namespace with
|
||||||
|
the explicitly given simple module spec.}
|
||||||
|
@item{@cmd[switch]{<name> !} --- switch to a newly made namespace. If
|
||||||
|
a namespace by that name already existed, it is rest.}
|
||||||
|
@item{@cmd[switch]{<name> ! <module>} --- same, but reset to the given
|
||||||
|
module instead of what it previously used.}
|
||||||
|
@item{@cmd[switch]{- <name>} --- drop the specified namespace, making
|
||||||
|
it possible to garbage-collect away any associated resources. You
|
||||||
|
cannot drop the current namespace or the default one (@litchar{*}).}
|
||||||
|
@item{@cmd[switch]{?} --- list all known namespaces.}]
|
||||||
|
|
||||||
|
Do not confuse namespaces with sandboxes or custodians. The
|
||||||
|
@cmd{switch} command changes @emph{only} the
|
||||||
|
@racket[current-namespace] --- it does not install a new custodian or
|
||||||
|
restricts evaluation in any way. Note that it is possible to pass
|
||||||
|
around values from one namespace to another via past result reference;
|
||||||
|
see @secref["past-vals"].
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[syntax]{
|
||||||
|
Manipulate syntaxes and inspect their expansion.
|
||||||
|
|
||||||
|
Useful operations revolve around a ``currently set syntax''. With no
|
||||||
|
arguments, the currently set syntax is displayed; an argument of
|
||||||
|
@litchar{^} sets the current syntax from the last input to the REPL;
|
||||||
|
and an argument that holds any other s-expression will set it as the
|
||||||
|
current syntax.
|
||||||
|
|
||||||
|
Syntax operations are specified via flags:
|
||||||
|
@itemize[
|
||||||
|
@item{@litchar{+} uses @racket[expand-once] on the current syntax and
|
||||||
|
prints the resulting syntax. In addition, the result becomes the
|
||||||
|
new ``current'' syntax, so you can use this as a poor-man's syntax
|
||||||
|
stepper. (Note that in some rare cases expansion via a sequence of
|
||||||
|
@racket[expand-once] might differ from the actual expansion.)}
|
||||||
|
@item{@litchar{!} uses @racket[expand] to completely expand the
|
||||||
|
current syntax.}
|
||||||
|
@item{@litchar{*} uses the macro debugger's textual output to show
|
||||||
|
expansion steps for the current syntax, leaving macros from
|
||||||
|
@racketmodname[racket/base] intact. Does not change the current
|
||||||
|
syntax.
|
||||||
|
See @other-doc['(lib "macro-debugger/macro-debugger.scrbl")] for
|
||||||
|
details.}
|
||||||
|
@item{@litchar{**} uses the macro debugger similarly to @litchar{*},
|
||||||
|
but expands @racketmodname[racket/base] macros too, showing the
|
||||||
|
resulting full expansion process.}]
|
||||||
|
Several input flags and/or syntaxes can be spacified in succession as
|
||||||
|
arguments to @cmd{syntax}. For example, @cmd[stx]{(when 1 2) ** !}.
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[log]{
|
||||||
|
Starts (or stops) logging events at a specific level. The level can
|
||||||
|
be:
|
||||||
|
@itemize[
|
||||||
|
@item{a known level name (currently one of @litchar{fatal},
|
||||||
|
@litchar{error}, @litchar{warning}, @litchar{info},
|
||||||
|
@litchar{debug}),}
|
||||||
|
@item{@racket[#f] for no logging,}
|
||||||
|
@item{@racket[#t] for maximum logging,}
|
||||||
|
@item{an integer level specification, with @racket[0] for no logging
|
||||||
|
and bigger ones for additional verbosity.}]
|
||||||
|
}
|
||||||
|
|
||||||
|
@defcmd[install!]{
|
||||||
|
Convenient utility command to install XREPL in your Racket
|
||||||
|
initialization file. This is done carefully, you will be notified of
|
||||||
|
potential issues, and asked to authorize changes.
|
||||||
|
}
|
||||||
|
|
||||||
|
@; ---------------------------------------------------------------------
|
||||||
|
@section[#:tag "past-vals"]{Past Evaluation Results}
|
||||||
|
|
||||||
|
XREPL makes the last few interaction results available for evaluation
|
||||||
|
via special toplevel variables: @racketidfont{^}, @racketidfont{^^},
|
||||||
|
..., @racketidfont{^^^^^}. The first, @racketidfont{^}, refers to the
|
||||||
|
last result, @racketidfont{^^} to the previous one and so on.
|
||||||
|
|
||||||
|
As with the usual REPL printouts, @void-const results are not kept. In
|
||||||
|
case of multiple results, they are spliced in reverse, so
|
||||||
|
@racketidfont{^} refers to the last result of the last evaluation. For
|
||||||
|
example:
|
||||||
|
@verbatim[#:indent 4]{
|
||||||
|
-> 1
|
||||||
|
1
|
||||||
|
-> (values 2 3)
|
||||||
|
2
|
||||||
|
3
|
||||||
|
-> (values 4)
|
||||||
|
4
|
||||||
|
-> (list ^ ^^ ^^^ ^^^^)
|
||||||
|
'(4 3 2 1)}
|
||||||
|
The rationale for this is that @racketidfont{^} always refers to the
|
||||||
|
last @emph{printed} result, @racketidfont{^^} to the one before that,
|
||||||
|
etc.
|
||||||
|
|
||||||
|
These bindings are made available only if they are not already defined,
|
||||||
|
and if they are not modified. This means that if you have code that
|
||||||
|
uses these names, it will continue to work as usual.
|
||||||
|
|
||||||
|
@; ---------------------------------------------------------------------
|
||||||
|
@section{Hacking XREPL}
|
||||||
|
|
||||||
|
XREPL is mainly a convenience tool, and as such you might want to hack
|
||||||
|
it to better suite your needs. Currently, there is no convenient way to
|
||||||
|
customize and extend it, but this will be added in the future.
|
||||||
|
|
||||||
|
Meanwhile, if you're interested in tweaking XREPL, the @cmd[enter]
|
||||||
|
command can be used as usual to go into its implementation. For
|
||||||
|
example:
|
||||||
|
@verbatim[#:indent 4]{
|
||||||
|
-> ,en xrepl/xrepl
|
||||||
|
xrepl/xrepl> ,e
|
||||||
|
xrepl/xrepl> (saved-values-char #\~)
|
||||||
|
xrepl/xrepl> ,top
|
||||||
|
-> 123
|
||||||
|
123
|
||||||
|
-> ~
|
||||||
|
123}
|
||||||
|
While this is not intended as @emph{the} way to extend and customize
|
||||||
|
XREPL, it is a useful debugging tool should you want to do so.
|
||||||
|
|
||||||
|
If you have any useful tweaks and extensions, please mail the author or
|
||||||
|
the Racket developer's
|
||||||
|
@hyperlink["http://racket-lang.org/community.html"]{mailing list}.
|
||||||
|
|
||||||
|
@; ---------------------------------------------------------------------
|
||||||
|
@section{License Issues}
|
||||||
|
|
||||||
|
Under most circumstances XREPL uses the @racketmodname[readline]
|
||||||
|
library, and therefore a similar license caveat applies: XREPL cannot be
|
||||||
|
enabled by default because of the @seclink["readline-license" #:doc
|
||||||
|
RL]{readline licensing}, you have to explicitly do so yourself to use
|
||||||
|
it. (Note that XREPL is intended to be used only for enhanced
|
||||||
|
interaction, not as a library; so there are no additional issues.)
|
||||||
|
|
||||||
|
@; ---------------------------------------------------------------------
|
||||||
|
@(check-all-documented)
|
Loading…
Reference in New Issue
Block a user