branch: elpa/racket-mode
commit 0160fca2543ab6d3c9506797533b2cf26cf88c33
Author: Greg Hendershott <[email protected]>
Commit: Greg Hendershott <[email protected]>
Improve co-existence with keyword font-lock
TL;DR Although we don't want any syntactic font-lock (which instead is
should be driven solely by tokens) we do want to peacefully co-exist
with keyword search-based fontification.
- Limit other font-lock to keywords (not syntactic); fixes #679. In
fixing #669 we allowed things like highlight-indent-guides-mode to
contribute font-lock-add-keywords (even though we don't use that
mechanism). But we didn't sufficiently limit that: We didn't
explicitly limit font-lock to keywords-only, and also we called the
general purpose font-lock-default-fontify-region. As a result,
font-lock based on char syntax could occur, with bad results.
- Furthermore, defer calling font-lock-fontify-keywords-region until
we handle our command response, and do so after we use tokens to add
properties like face and char-syntax. This ensures keyword
fontification does not happen inside strings or comments.
- Update documentation wrt two choices for richer fontification:
1. Using some of racket-mode's search-based fontification keyword
lists. In the example we skip the first two levels which concern
syntax things better handled by tokenization. (Note this same approach
can work if someone wants to define their own keyword patterns for
other langs.)
2. Using binding faces from racket-xp-mode, as before, but change that
to be enabled via a simple boolean variable, so can setq-local per
buffer.
---
doc/generate.el | 2 +-
doc/racket-mode.org | 4 +-
doc/racket-mode.texi | 350 +++++++++++++++++++++++++++++++++------------------
racket-custom.el | 9 +-
racket-font-lock.el | 19 +--
racket-hash-lang.el | 209 +++++++++++++++++++-----------
racket-xp.el | 156 +++++++++++------------
7 files changed, 453 insertions(+), 296 deletions(-)
diff --git a/doc/generate.el b/doc/generate.el
index 623120219a..21fc544b70 100644
--- a/doc/generate.el
+++ b/doc/generate.el
@@ -188,7 +188,7 @@
racket-browse-url-function
racket-xp-after-change-refresh-delay
racket-xp-highlight-unused-regexp
- racket-xp-binding-font-lock-face-modes
+ racket-xp-add-binding-faces
racket-documentation-search-location
"Hash lang variables"
racket-hash-lang-token-face-alist
diff --git a/doc/racket-mode.org b/doc/racket-mode.org
index 0dc0ae0ff3..6c948d81b2 100644
--- a/doc/racket-mode.org
+++ b/doc/racket-mode.org
@@ -175,9 +175,9 @@ The Racket Mode package offers a choice of two major modes
to use in buffers for
Whereas ~racket-mode~ is in the tradition of Emacs ~lisp-mode~ and
~scheme-mode~ and assumes s-expression langs, ~racket-hash-lang-mode~ takes the
approach of DrRacket to work for all langs.
-- ~racket-mode~ is the original, "classic" mode for ~#lang racket~ and related
s-expression languages. It is implemented entirely in Emacs and does /not/ need
Racket Mode's back end racket process running. Font-lock (coloring) uses rules
for a fixed set of identifiers from ~racket~ lang and popular modules like
~racket/match~. Indentation uses rules for a fixed set of forms, and may be
customized (see below).
+- ~racket-mode~ is the original, "classic" mode for ~#lang racket~ and related
s-expression languages. It is implemented entirely in Emacs and does /not/ need
Racket Mode's back end racket process running. Font-lock (coloring) uses rules
for a fixed set of identifiers from ~racket~ lang and popular modules like
~racket/match~. Indentation uses rules for a fixed set of forms, and may be
customized.
-- ~racket-hash-lang-mode~ uses font-lock (colors) and indentation determined
by the lang; to get this information it /does/ need the Racket Mode's back end
racket process running. Although basic editing should feel fast, you might
notice some delay when indenting. You might see colors appear after a small
delay (but it will not block editing). Speaking of colors, they will be
"plainer" than ~racket-mode~ -- mostly just for different kinds of tokens like
numbers, comments, strings, and ke [...]
+- ~racket-hash-lang-mode~ uses font-lock (colors) and indentation determined
by the lang; to get this information it /does/ need the Racket Mode's back end
racket process running. Although basic editing should feel fast, you might
notice some delay when indenting. You might see colors appear after a small
delay (but it will not block editing). Speaking of colors, they will be
"plainer" than ~racket-mode~ -- just colors for tokens like numbers, comments,
strings, and keywords. This looks [...]
You can use different major modes for different kinds of files:
diff --git a/doc/racket-mode.texi b/doc/racket-mode.texi
index 1f43d1a6f4..d39ad3c3cf 100644
--- a/doc/racket-mode.texi
+++ b/doc/racket-mode.texi
@@ -8,7 +8,6 @@
@c %**end of header
@copying
-
Copyright (C) 2013-2022 by Greg Hendershott.
SPDX-License-Identifier: GPL-3.0-or-later
@@ -33,7 +32,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
@ifnottex
@node Top
@top Racket Mode
-@insertcopying
@end ifnottex
@menu
@@ -63,6 +61,7 @@ Update
* Upgrading all packages::
* Updating just Racket Mode::
+
Configure
* Which major mode to use::
@@ -186,6 +185,7 @@ Other
* racket-debug-toggle-breakpoint::
* racket-mode-start-faster::
* racket-mode-start-slower::
+
Variables
* General variables::
@@ -206,7 +206,7 @@ General variables
* racket-browse-url-function::
* racket-xp-after-change-refresh-delay::
* racket-xp-highlight-unused-regexp::
-* racket-xp-binding-font-lock-face-modes::
+* racket-xp-add-binding-faces::
* racket-documentation-search-location::
Hash lang variables
@@ -248,13 +248,14 @@ Showing information
Running racket and raco commands in a shell or terminal
* racket-shell-or-terminal-function::
+
Configuration functions
-* Showing information: Showing informationx.
+* Showing information: Showing information (1).
* Associating edit buffers with REPL buffers::
* Browsing file URLs with anchors::
* Configuring back ends::
-* Running racket and raco commands in a shell or terminal: Running racket and
raco commands in a shell or terminalx.
+* Running racket and raco commands in a shell or terminal: Running racket and
raco commands in a shell or terminal (1).
Showing information
@@ -284,6 +285,7 @@ Running racket and raco commands in a shell or terminal
* racket-term::
* racket-ansi-term::
* racket-vterm::
+
Faces
* All::
@@ -323,15 +325,14 @@ All
* racket-repl-error-location::
* racket-repl-stdout::
* racket-repl-stderr::
+
@end detailmenu
@end menu
-
-
@node Introduction
@chapter Introduction
-The @uref{https://www.racket-mode.com/,Racket Mode} package consists of a
variety of Emacs major and minor modes, including:
+The @uref{https://www.racket-mode.com/, Racket Mode} package consists of a
variety of Emacs major and minor modes, including:
@itemize
@item
@@ -344,7 +345,7 @@ The @uref{https://www.racket-mode.com/,Racket Mode} package
consists of a variet
@ref{racket-xp-mode}: A minor mode to enhance either edit mode. Explain and
explore code, similar to background check-syntax in Dr Racket.
@item
-@code{racket-repl-mode}: A major mode to run programs and use a REPL.
+@code{racket-repl-mode}: A major mode to run programs and use a REPL@.
@item
Various other modes to support specific features:
@@ -358,18 +359,19 @@ Various other modes to support specific features:
@end itemize
@end itemize
-For code, issues, and pull requests, see the
@uref{https://github.com/greghendershott/racket-mode,Git repo}.
+For code, issues, and pull requests, see the
@uref{https://github.com/greghendershott/racket-mode, Git repo}.
-To sponsor this work, see
@uref{https://github.com/users/greghendershott/sponsorship,GitHub Sponsors} or
@uref{https://www.paypal.me/greghendershott,PayPal}.
+To sponsor this work, see
@uref{https://github.com/users/greghendershott/sponsorship, GitHub Sponsors} or
@uref{https://www.paypal.me/greghendershott, PayPal}.
@node Install Update and Uninstall
@chapter Install, Update, and Uninstall
-The most common way to use Racket Mode is to install from a package archive
like MELPA or NonGNU ELPA.
+The most common way to use Racket Mode is to install from a package archive
like MELPA or NonGNU ELPA@.
-Some people also use a system like
@uref{https://github.com/radian-software/straight.el,straight.el}.
+Some people also use a system like
@uref{https://github.com/radian-software/straight.el, straight.el}.
+
+Note that Racket Mode is only available on MELPA (@emph{not} ``MELPA
Stable''), and is available as a ``rolling release'' from NonGNU ELPA@.
-Note that Racket Mode is only available on MELPA (@emph{not} ``MELPA
Stable''), and is available as a ``rolling release'' from NonGNU ELPA.
@menu
* Use Emacs 28.1 or newer with NonGNU ELPA: Use Emacs 281 or newer with NonGNU
ELPA.
* Configure Emacs to use MELPA::
@@ -382,9 +384,9 @@ Note that Racket Mode is only available on MELPA
(@emph{not} ``MELPA Stable''),
@node Use Emacs 281 or newer with NonGNU ELPA
@section Use Emacs 28.1 or newer with NonGNU ELPA
-Emacs 28.1 or newer comes configured to use
@uref{https://elpa.nongnu.org,NonGNU ELPA}, in which case you can skip ahead to
@ref{Install,Install}.
+Emacs 28.1 or newer comes configured to use @uref{https://elpa.nongnu.org,
NonGNU ELPA}, in which case you can skip ahead to @ref{Install}.
-With older versions of Emacs, you can use MELPA.
+With older versions of Emacs, you can use MELPA@.
@node Configure Emacs to use MELPA
@section Configure Emacs to use MELPA
@@ -393,7 +395,7 @@ Following is a quick guide that may work for you. (For
definitive instructions a
@itemize
@item
-Add the following to your @verb{,~/.emacs,} or @verb{,~/.emacs.d/init.el,}:
+Add the following to your @samp{~/.emacs} or @samp{~/.emacs.d/init.el}:
@end itemize
@lisp
@@ -411,6 +413,7 @@ Restart Emacs.
@quotation
NOTE: If you ever get an error message about ``contacting a host'' or
``downloading an archive'', the problem is not unique to Racket Mode. Please
see @uref{https://melpa.org/#/getting-started}.
+
@end quotation
@node Install
@@ -431,12 +434,13 @@ Type @kbd{M-x} @code{package-install} @kbd{RET}
@code{racket-mode} @kbd{RET} .
@quotation
NOTE: If you get an error message about ``contacting a host'' or ``downloading
an archive'', the problem is not unique to Racket Mode. Please see
@uref{https://melpa.org/#/getting-started}.
+
@end quotation
@node Minimal Racket
@section Minimal Racket
-If you have installed the minimal Racket distribution (for example by using
the
@uref{https://github.com/Homebrew/homebrew-core/blob/master/Formula/minimal-racket.rb,homebrew
formula}) Racket Mode needs some additional Racket packages. A simple way to
get all these packages is to install the @code{drracket} Racket package. In a
command shell:
+If you have installed the minimal Racket distribution (for example by using
the
@uref{https://github.com/Homebrew/homebrew-core/blob/master/Formula/minimal-racket.rb,
homebrew formula}) Racket Mode needs some additional Racket packages. A simple
way to get all these packages is to install the @code{drracket} Racket package.
In a command shell:
@example
raco pkg install --auto drracket
@@ -493,6 +497,7 @@ After such a mass update, it might be wise to exit and
restart Emacs.
@quotation
NOTE: If you get an error message about ``contacting a host'' or ``downloading
an archive'', the problem is not unique to Racket Mode. Please see
@uref{https://melpa.org/#/getting-started}.
+
@end quotation
@node Updating just Racket Mode
@@ -520,9 +525,10 @@ Although Racket Mode can be customized with many
@ref{Variables}, there is only
On Windows or Linux, this default will probably work for you.
-On macOS, downloading Racket doesn't add its @code{bin} directory to your
@code{PATH}. Even after you add it, GUI Emacs doesn't automatically use your
path (unless you use the handy
@uref{https://melpa.org/#/exec-path-from-shell,exec-path-from-shell} package).
Therefore you might want to set @code{racket-program} to a complete pathname.
+On macOS, downloading Racket doesn't add its @code{bin} directory to your
@code{PATH}. Even after you add it, GUI Emacs doesn't automatically use your
path (unless you use the handy @uref{https://melpa.org/#/exec-path-from-shell,
exec-path-from-shell} package). Therefore you might want to set
@code{racket-program} to a complete pathname.
+
+You can @code{setq} this directly in your Emacs init file (@samp{~/.emacs} or
@samp{~/.emacs.d/init.el}), or, use @kbd{M-x} @code{customize}, as you prefer.
-You can @code{setq} this directly in your Emacs init file (@verb{,~/.emacs,}
or @verb{,~/.emacs.d/init.el,}), or, use @kbd{M-x} @code{customize}, as you
prefer.
@menu
* Which major mode to use::
* Key bindings::
@@ -554,10 +560,10 @@ Whereas @code{racket-mode} is in the tradition of Emacs
@code{lisp-mode} and @co
@itemize
@item
-@code{racket-mode} is the original, ``classic'' mode for @code{#lang racket}
and related s-expression languages. It is implemented entirely in Emacs and
does @emph{not} need Racket Mode's back end racket process running. Font-lock
(coloring) uses rules for a fixed set of identifiers from @code{racket} lang
and popular modules like @code{racket/match}. Indentation uses rules for a
fixed set of forms, and may be customized (see below).
+@code{racket-mode} is the original, ``classic'' mode for @code{#lang racket}
and related s-expression languages. It is implemented entirely in Emacs and
does @emph{not} need Racket Mode's back end racket process running. Font-lock
(coloring) uses rules for a fixed set of identifiers from @code{racket} lang
and popular modules like @code{racket/match}. Indentation uses rules for a
fixed set of forms, and may be customized.
@item
-@code{racket-hash-lang-mode} uses font-lock (colors) and indentation
determined by the lang; to get this information it @emph{does} need the Racket
Mode's back end racket process running. Although basic editing should feel
fast, you might notice some delay when indenting. You might see colors appear
after a small delay (but it will not block editing). Speaking of colors, they
will be ``plainer'' than @code{racket-mode} -- mostly just for different kinds
of tokens like numbers, comments, [...]
+@code{racket-hash-lang-mode} uses font-lock (colors) and indentation
determined by the lang; to get this information it @emph{does} need the Racket
Mode's back end racket process running. Although basic editing should feel
fast, you might notice some delay when indenting. You might see colors appear
after a small delay (but it will not block editing). Speaking of colors, they
will be ``plainer'' than @code{racket-mode} -- just colors for tokens like
numbers, comments, strings, and keywor [...]
@end itemize
You can use different major modes for different kinds of files:
@@ -593,6 +599,7 @@ Likewise for @code{racket-repl-mode-hook} and
@code{racket-repl-mode-map}.
@quotation
Note: The alternative major mode @ref{racket-hash-lang-mode} disables all of
the following behavior and uses colors determined by the #lang.
+
@end quotation
Font-lock (as Emacs calls syntax highlighting) can be controlled using the
variable @code{font-lock-maximum-decoration}, which defaults to @code{t}
(maximum). You can set it to a number, where @code{0} is the lowest level. You
can even supply an association list to specify different values for different
major modes.
@@ -625,7 +632,7 @@ In Emacs, a major mode may supply a ``completion-at-point
function''. This funct
@code{racket-xp-mode} --- an optional minor mode that enhances
@code{racket-mode} --- supplies @code{racket-xp-complete-at-point}, which uses
a static analysis to find local and imported binding names. Although this
requires the Racket Mode back end to be running --- and will automatically
start it --- it does @emph{not} require the edit buffer to be
@code{racket-run}. This also supplies meta data usable by the
@code{company-capf} backend.
@item
-@code{racket-repl-mode} supplies @code{racket-repl-complete-at-point}, which
uses the result of @code{namespace-mapped-symbols} on the program currently
running in the REPL.
+@code{racket-repl-mode} supplies @code{racket-repl-complete-at-point}, which
uses the result of @code{namespace-mapped-symbols} on the program currently
running in the REPL@.
@end itemize
These completion functions are set by default. (However, @code{racket-xp-mode}
is not enabled by default. To do so: @ref{racket-xp-mode}.)
@@ -698,20 +705,22 @@ In any case, using the Emacs xref API allows for
consistent command names, short
@quotation
Note: The alternative major mode @ref{racket-hash-lang-mode} disables all of
the following behavior and uses indentation determined by the #lang.
+
@end quotation
Indentation can be customized in a way similar to lisp-mode and scheme-mode:
@ref{racket-indent-line}.
-(Indentation preserves your line breaks. If you want to use an
auto-reformatter --- an expressive pretty printer that chooses line breaks
while computing an optimal layout --- the Racket package
@uref{https://docs.racket-lang.org/fmt/,fmt} is supported by the Emacs package
@uref{https://github.com/lassik/emacs-format-all-the-code,emacs-format-all-the-code}.)
+(Indentation preserves your line breaks. If you want to use an
auto-reformatter --- an expressive pretty printer that chooses line breaks
while computing an optimal layout --- the Racket package
@uref{https://docs.racket-lang.org/fmt/, fmt} is supported by the Emacs package
@uref{https://github.com/lassik/emacs-format-all-the-code,
emacs-format-all-the-code}.)
@node paredit
@section paredit
@quotation
Note: If you use @ref{racket-hash-lang-mode}, you can use
@code{racket-hash-lang-mode-hook} to enable/disable paredit based on the
specific #lang.
+
@end quotation
-If you use @uref{https://melpa.org/#/paredit,paredit}, you might want to add
keybindings to @code{paredit-mode-map}:
+If you use @uref{https://melpa.org/#/paredit, paredit}, you might want to add
keybindings to @code{paredit-mode-map}:
@itemize
@item
@@ -721,7 +730,7 @@ Bind the curly brace keys to @code{paredit-open-curly} and
@code{paredit-close-c
Bind whatever keys you prefer for @code{paredit-wrap-square} and
@code{paredit-wrap-curly}.
@end itemize
-For example, with @uref{https://melpa.org/#/use-package,@code{use-package}}:
+For example, with @uref{https://melpa.org/#/use-package, @code{use-package}}:
@lisp
(use-package paredit
@@ -740,7 +749,7 @@ For example, with
@uref{https://melpa.org/#/use-package,@code{use-package}}:
("M-@{" . paredit-wrap-curly))))
@end lisp
-Starting c. November 2022, paredit binds the @kbd{RET} key to its own
command. Unfortunately this is @emph{not} compatible with interactive modes ---
including but not limited to @code{racket-repl-mode} --- which expect @kbd{RET}
to be bound to a command to submit your input to the REPL. In other words, if
you type an expression and hit @kbd{RET} , nothing will happen and the REPL
will seem frozen. You @code{M-x racket-repl-submit} to proceed.
+Starting c. November 2022, paredit binds the @kbd{RET} key to its own
command. Unfortunately this is @emph{not} compatible with interactive modes ---
including but not limited to @code{racket-repl-mode} --- which expect @kbd{RET}
to be bound to a command to submit your input to the REPL@. In other words, if
you type an expression and hit @kbd{RET} , nothing will happen and the REPL
will seem frozen. You @code{M-x racket-repl-submit} to proceed.
If you want to use paredit with interactive modes, their advice is to remove
the binding from @code{paredit-mode-map} (note that this will also disable it
for all buffers, including editing buffers). One way you can do this for all
related keys:
@@ -752,7 +761,7 @@ If you want to use paredit with interactive modes, their
advice is to remove the
@node smartparens
@section smartparens
-If instead of paredit you prefer
@uref{https://melpa.org/#/smartparens,smartparens}, you can use the default
configuration it provides for Lisp modes generally and for Racket Mode
specifically:
+If instead of paredit you prefer @uref{https://melpa.org/#/smartparens,
smartparens}, you can use the default configuration it provides for Lisp modes
generally and for Racket Mode specifically:
@lisp
(require 'smartparens-config)
@@ -761,9 +770,9 @@ If instead of paredit you prefer
@uref{https://melpa.org/#/smartparens,smartpare
@node Appearance of parentheses
@section Appearance of parentheses
-If you prefer parentheses to appear ``dimmed'', see
@uref{https://melpa.org/#/paren-face,paren-face}.
+If you prefer parentheses to appear ``dimmed'', see
@uref{https://melpa.org/#/paren-face, paren-face}.
-If you prefer the opposite, see
@uref{https://melpa.org/#/rainbow-delimiters,rainbow-delimiters}.
+If you prefer the opposite, see @uref{https://melpa.org/#/rainbow-delimiters,
rainbow-delimiters}.
@node Edit buffers and REPL buffers
@section Edit buffers and REPL buffers
@@ -805,7 +814,7 @@ Many Racket primitives are defined in @code{#%kernel} or
@code{#%runtime}. There
Many of the interesting Racket forms are syntax (macros) not functions.
There's no easy way to determine their ``argument lists''.
@item
-When a form has documentation, Racket Mode can show the \"bluebox\'' -- but
often that does not fit in a single line as you would normally expect with
eldoc.
+When a form has documentation, Racket Mode can show the \``bluebox\'' -- but
often that does not fit in a single line as you would normally expect with
eldoc.
@end itemize
A more satisfying experience is to use @ref{racket-xp-describe} or
@ref{racket-xp-documentation}.
@@ -843,7 +852,7 @@ Racket Mode consists of a single Emacs front end, and one
or more processes runn
A back end is responsible for commands that cannot be implemented in Emacs
Lisp, as well as supplying zero or more REPLs.
-Although you can start and stop a back end with @code{racket-start-back-end}
and @code{racket-stop-back-end}, a back end is normally started automatically
when the front end needs to issue some command. This includes commands that do
@emph{not} involve @code{racket-run} or a REPL. For example
@code{racket-xp-mode} issues commands to check your code and annotate the
buffer, even if you do not run it. In other words, a back end supplies zero or
more REPLs --- a back end is not the same thi [...]
+Although you can start and stop a back end with @code{racket-start-back-end}
and @code{racket-stop-back-end}, a back end is normally started automatically
when the front end needs to issue some command. This includes commands that do
@emph{not} involve @code{racket-run} or a REPL@. For example
@code{racket-xp-mode} issues commands to check your code and annotate the
buffer, even if you do not run it. In other words, a back end supplies zero or
more REPLs --- a back end is not the same th [...]
To learn more about how @emph{many} REPLs are used:
@xref{racket-repl-buffer-name-function}.
@@ -857,7 +866,7 @@ As one example, you can have multiple back ends on the
local host. One back end
@image{scenario-1,,, Emacs front end and two local back ends --- one for a
project path. Command I/O via pipe (local) or ssh (remote). Each back end
provides zero or more REPLs.,.svg}
-Furthermore, you could work with a project located on a remote host, whose
files you edit using TRAMP. You also want the back end to run there. For a
remote host, Racket Mode copies its back end source files to the remote when
necessary, and runs the back end using ssh.
+Furthermore, you could work with a project located on a remote host, whose
files you edit using TRAMP@. You also want the back end to run there. For a
remote host, Racket Mode copies its back end source files to the remote when
necessary, and runs the back end using ssh.
@image{scenario-2,,, Emacs front end and a back end on a remote host. Command
I/O via pipe (local) or ssh (remote). Each back end provides zero or more
REPLs.,.svg}
@@ -992,8 +1001,8 @@ Major mode for editing Racket source files.
In addition to any hooks its parent mode @code{prog-mode} might have run,
-this mode runs the hook @code{racket-mode-hook}, as the final step
-during initialization.
+this mode runs the hook @code{racket-mode-hook}, as the final or
+penultimate step during initialization.
@node racket-insert-lambda
@subsection racket-insert-lambda
@@ -1136,7 +1145,7 @@ Indent current line as Racket code.
Normally you don't invoke this command directly. Instead, because
it is used as the value for the variable @code{indent-line-function}
in @ref{racket-mode} and @ref{racket-repl-mode} buffers, it is used
-automatically when you press keys like RET or TAB. However you
+automatically when you press keys like RET or TAB@. However you
might refer to it when configuring custom indentation, explained
below.
@@ -1218,7 +1227,7 @@ Literal forms like #hasheq()
@item
Quoted forms when the variable @ref{racket-indent-sequence-depth}
- is > 0.
+is > 0.
@item
@{@} forms when the variable @ref{racket-indent-curly-as-sequence} is
@@ -1268,6 +1277,21 @@ even ``let'' forms:
Minor mode to let you always type @code{[}' to insert @code{(} or @code{[}
automatically.
+This is a minor mode. If called interactively, toggle the
+@code{Racket-Smart-Open-Bracket mode} mode. If the prefix argument is
+positive, enable the mode, and if it is zero or negative, disable
+the mode.
+
+If called from Lisp, toggle the mode if ARG is @code{toggle}. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate @ref{racket-smart-open-bracket-mode}.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
Behaves like the ``Automatically adjust opening square brackets''
feature in Dr. Racket.
@@ -1306,6 +1330,10 @@ the binding for the @code{[}' key in the map for
@ref{racket-smart-open-bracket-mode} has higher priority. See also
the variable @code{minor-mode-map-alist}.
+Tip: When using this with @ref{racket-hash-lang-mode}, you may want
+to use @ref{racket-hash-lang-module-language-hook} to enable it IFF
+the module langugage is something like ``racket''.
+
@node racket-insert-closing
@subsection racket-insert-closing
@@ -1420,7 +1448,7 @@ of ``couples''. A couple is:
@itemize
@item
-A list of two or more sexprs: "[sexpr val sexpr @dots{}]".
+A list of two or more sexprs: ``[sexpr val sexpr @dots{}]''.
@item
Two sexprs: ``sexpr val''.
@end itemize
@@ -1428,7 +1456,7 @@ Two sexprs: ``sexpr val''.
Each ``val'' moves to the same column and is
@code{prog-indent-sexp}-ed (in case it is a multi-line form).
-For example with point on the "[" before ``a'':
+For example with point on the ``['' before ``a'':
@example
Before After
@@ -1534,13 +1562,17 @@ A discussion of the information provided by a Racket
language:
Note that langs supply colors only for lexer tokens like strings
and comments. If you enable the minor mode @ref{racket-xp-mode}, it
can contribute more colors; see the customization variable
-@ref{racket-xp-binding-font-lock-face-modes}.
+@code{nil}.
@multitable {aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
@item Key
@tab Binding
@item @kbd{RET}
@tab @code{newline-and-indent}
+@item @kbd{TAB}
+@tab @code{indent-for-tab-command}
+@item @kbd{C-x C-e}
+@tab @ref{racket-send-last-sexp}
@item @kbd{C-M-q}
@tab @ref{racket-hash-lang-C-M-q-dwim}
@item @kbd{C-M-d}
@@ -1553,12 +1585,24 @@ can contribute more colors; see the customization
variable
@tab @ref{racket-hash-lang-backward}
@item @kbd{C-M-y}
@tab @ref{racket-insert-lambda}
-@item @kbd{TAB}
-@tab @code{indent-for-tab-command}
+@item @kbd{C-M-x}
+@tab @ref{racket-send-definition}
+@item @kbd{C-c C-u}
+@tab @ref{racket-unfold-all-tests}
+@item @kbd{C-c C-f}
+@tab @ref{racket-fold-all-tests}
@item @kbd{C-c C-x C-f}
@tab @ref{racket-open-require-path}
+@item @kbd{C-c C-e r}
+@tab @ref{racket-expand-region}
+@item @kbd{C-c C-e e}
+@tab @ref{racket-expand-last-sexp}
+@item @kbd{C-c C-e x}
+@tab @ref{racket-expand-definition}
@item @kbd{C-c C-e f}
@tab @ref{racket-expand-file}
+@item @kbd{C-c C-r}
+@tab @ref{racket-send-region}
@item @kbd{C-c C-o}
@tab @ref{racket-profile}
@item @kbd{C-c C-l}
@@ -1577,8 +1621,8 @@ can contribute more colors; see the customization variable
In addition to any hooks its parent mode @code{prog-mode} might have run,
-this mode runs the hook @code{racket-hash-lang-mode-hook}, as the final step
-during initialization.
+this mode runs the hook @code{racket-hash-lang-mode-hook}, as the final or
+penultimate step during initialization.
@node racket-hash-lang-backward
@subsection racket-hash-lang-backward
@@ -1660,6 +1704,20 @@ anything else, do @code{prog-indent-sexp}.
A minor mode that analyzes expanded code to explain and explore.
+This is a minor mode. If called interactively, toggle the
+@code{Racket-Xp mode} mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is @code{toggle}. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate @ref{racket-xp-mode}.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
This minor mode is an optional enhancement to @ref{racket-mode} edit
buffers. Like any minor mode, you can turn it on or off for a
specific buffer. If you always want to use it, put the following
@@ -1795,10 +1853,10 @@ and use the @code{racket-xp-annotate} command manually.
The mode line changes to reflect the current status of
annotations, and whether or not you had a syntax error.
-If you have one or more syntax errors, @ref{racket-xp-next-error} and
-@ref{racket-xp-previous-error} navigate among them. Although most
-languages will stop after the first syntax error, some like Typed
-Racket will try to collect and report multiple errors.
+If you have one or more syntax errors, @code{next-error} and
+@code{previous-error} navigate among them. Although most languages
+will stop after the first syntax error, some like Typed Racket
+will try to collect and report multiple errors.
You may use @code{xref-find-definitions} @kbd{M-.} ,
@code{xref-pop-marker-stack} @kbd{M-,} , and
@@ -1829,9 +1887,9 @@ commands directly to whatever keys you prefer.
@item @kbd{C-c C-.}
@tab @ref{racket-xp-describe}
@item @kbd{C-c # P}
-@tab @ref{racket-xp-previous-error}
+@tab @code{previous-error}
@item @kbd{C-c # N}
-@tab @ref{racket-xp-next-error}
+@tab @code{next-error}
@item @kbd{C-c # g}
@tab @code{racket-xp-annotate}
@item @kbd{C-c # <}
@@ -1885,8 +1943,8 @@ examples.
@item
Otherwise, if the identifier is a function, then its
-signature is displayed, for example "(name arg-1-name
-arg-2-name)".
+signature is displayed, for example ``(name arg-1-name
+arg-2-name)''.
@end itemize
@item
@@ -1930,7 +1988,7 @@ identifer defined in the expansion of the current buffer.
If no such identifer exists, opens the Search Manuals page. In
this case, the variable @ref{racket-documentation-search-location}
determines whether the search is done locally as with @code{raco
- doc}, or visits a URL.
+ doc}, or visits a URL@.
@item
@kbd{C-u} @kbd{C-c C-d}
@@ -1980,16 +2038,16 @@ When point is on a use, go to the previous, sibling use.
@node racket-xp-next-error
@subsection racket-xp-next-error
-@kbd{C-c # N}
+@kbd{M-x} @code{racket-xp-next-error}
-Go to the next error.
+An obsolete alias for @code{next-error}.
@node racket-xp-previous-error
@subsection racket-xp-previous-error
-@kbd{C-c # P}
+@kbd{M-x} @code{racket-xp-previous-error}
-Go to the previous error.
+An obsolete alias for @code{previous-error}.
@node racket-xp-tail-up
@subsection racket-xp-tail-up
@@ -2100,7 +2158,7 @@ Racket Describe buffer for that module's version of the
thing.
@kbd{M-x} @code{racket-repl-mode}
-Major mode for Racket REPL.
+Major mode for Racket REPL@.
You may use @code{xref-find-definitions} @kbd{M-.} and
@code{xref-pop-marker-stack} @kbd{M-,} :
@@ -2142,9 +2200,9 @@ identifier bindings and modules from the REPL's namespace.
@item @kbd{C-c C-o}
@tab @code{racket-repl-delete-output}
@item @kbd{C-c C-n}
-@tab @code{racket-repl-next-prompt}
+@tab @code{racket-repl-next-prompt-or-run}
@item @kbd{C-c C-p}
-@tab @code{racket-repl-previous-prompt}
+@tab @code{racket-repl-previous-prompt-or-run}
@item @kbd{C-c C-u}
@tab @code{racket-repl-clear-input}
@item @kbd{C-M-y}
@@ -2167,8 +2225,8 @@ identifier bindings and modules from the REPL's namespace.
-This mode runs the hook @code{racket-repl-mode-hook}, as the final step
-during initialization.
+This mode runs the hook @code{racket-repl-mode-hook}, as the final or
+penultimate step during initialization.
@node racket-run
@subsection racket-run
@@ -2269,8 +2327,8 @@ will correspond to those definitions and match your
expectations.
If you really want to start a REPL for no file in particular,
then you could use this @ref{racket-repl} command. But the resulting
REPL will have a minimal ``#lang racket/base'' namespace. You
-could enter "(require racket)" if you want the equivalent of
-``#lang racket''. You could also "(require racket/enter)" if
+could enter ``(require racket)'' if you want the equivalent of
+``#lang racket''. You could also ``(require racket/enter)'' if
you want things like ``enter!''. But in some sense you'd be
``using it wrong''. If you actually don't want to use Racket
Mode's REPL as intended, then consider using a plain Emacs
@@ -2303,8 +2361,8 @@ examples.
@item
Otherwise, if the identifier is a function, then its
-signature is displayed, for example "(name arg-1-name
-arg-2-name)".
+signature is displayed, for example ``(name arg-1-name
+arg-2-name)''.
@end itemize
@item
@@ -2344,7 +2402,7 @@ identifer defined in the current namespace.
If no such identifer exists, opens the Search Manuals page. In
this case, the variable @ref{racket-documentation-search-location}
determines whether the search is done locally as with @code{raco
- doc}, or visits a URL.
+ doc}, or visits a URL@.
@item
@kbd{C-u} @kbd{C-c C-d}
@@ -2366,7 +2424,7 @@ would like to see documentation for all identifiers named
@node racket-racket
@subsection racket-racket
-@kbd{<C-M-f5>}
+@kbd{C-M-<f5>}
Use command-line racket to run the file.
@@ -2383,7 +2441,7 @@ Like @ref{racket-run-module-at-point} but with profiling.
Results are presented in a @ref{racket-profile-mode} buffer, which
also lets you quickly view the source code.
-You may evaluate expressions in the REPL. They are also profiled.
+You may evaluate expressions in the REPL@. They are also profiled.
Use @code{racket-profile-refresh} to see the updated results. In
other words a possible workflow is: @ref{racket-profile} a .rkt file,
call one its functions in the REPL, and refresh the profile
@@ -2419,9 +2477,9 @@ Major mode for results of @ref{racket-profile}.
-In addition to any hooks its parent mode @code{tabulated-list-mode} might have
run,
-this mode runs the hook @code{racket-profile-mode-hook}, as the final step
-during initialization.
+In addition to any hooks its parent mode @code{tabulated-list-mode} might
+have run, this mode runs the hook @code{racket-profile-mode-hook}, as the
+final or penultimate step during initialization.
@node racket-logger
@subsection racket-logger
@@ -2462,9 +2520,9 @@ For more information see:
-In addition to any hooks its parent mode @code{special-mode} might have run,
-this mode runs the hook @code{racket-logger-mode-hook}, as the final step
-during initialization.
+In addition to any hooks its parent mode @code{special-mode} might have
+run, this mode runs the hook @code{racket-logger-mode-hook}, as the final
+or penultimate step during initialization.
@node racket-debug-mode
@subsection racket-debug-mode
@@ -2473,6 +2531,20 @@ during initialization.
Minor mode for debug breaks.
+This is a minor mode. If called interactively, toggle the
+@code{Racket-Debug mode} mode. If the prefix argument is positive,
+enable the mode, and if it is zero or negative, disable the mode.
+
+If called from Lisp, toggle the mode if ARG is @code{toggle}. Enable
+the mode if ARG is nil, omitted, or is a positive number.
+Disable the mode if ARG is a negative number.
+
+To check whether the minor mode is enabled in the current buffer,
+evaluate @ref{racket-debug-mode}.
+
+The mode's hook is called both when the mode is enabled and when
+it is disabled.
+
This feature is @strong{@strong{EXPERIMENTAL}}!!! It is likely to have
significant limitations and bugs. You are welcome to open an
issue to provide feedback. Please understand that this feature
@@ -2543,14 +2615,14 @@ provides shortcut keys:
@node racket-repl-clear
@subsection racket-repl-clear
-Delete all text in the REPL.
+Delete all text in the REPL@.
A suitable value for the hook @ref{racket-before-run-hook} if you
want the REPL buffer to be cleared before each run, much like
with Dr Racket. To do so you can use @code{customize}, or, add to your
Emacs init file something like:
-(add-hook `racket-before-run-hook #'racket-repl-clear)
+(add-hook 'racket-before-run-hook #'racket-repl-clear)
See also the command @ref{racket-repl-clear-leaving-last-prompt}.
@@ -2572,7 +2644,7 @@ Delete all text in the REPL, except for the last prompt.
@node racket-test
@subsection racket-test
-@kbd{<C-f5>} or @kbd{C-c C-t}
+@kbd{C-<f5>} or @kbd{C-c C-t}
Run the ``test'' submodule.
@@ -2626,21 +2698,21 @@ variable @ref{racket-shell-or-terminal-function}.
@kbd{C-c C-r}
-Send the current region (if any) to the Racket REPL.
+Send the current region (if any) to the Racket REPL@.
@node racket-send-definition
@subsection racket-send-definition
@kbd{C-M-x}
-Send the current definition to the Racket REPL.
+Send the current definition to the Racket REPL@.
@node racket-send-last-sexp
@subsection racket-send-last-sexp
@kbd{C-x C-e}
-Send the expression before point to the Racket REPL.
+Send the expression before point to the Racket REPL@.
The expression may be either an at-expression or an s-expression.
@@ -2722,9 +2794,9 @@ Used by the commands @ref{racket-expand-file},
-In addition to any hooks its parent mode @code{special-mode} might have run,
-this mode runs the hook @code{racket-stepper-mode-hook}, as the final step
-during initialization.
+In addition to any hooks its parent mode @code{special-mode} might have
+run, this mode runs the hook @code{racket-stepper-mode-hook}, as the final
+or penultimate step during initialization.
@node racket-expand-file
@subsection racket-expand-file
@@ -2735,7 +2807,7 @@ Expand the @ref{racket-mode} buffer's file in
@ref{racket-stepper-mode}.
Uses the @code{macro-debugger} package to do the expansion.
-You do need to @ref{racket-run} the file first; the namespace
+You do not need to @ref{racket-run} the file first; the namespace
active in the REPL is not used.
If the file is non-trivial and/or is not compiled to a .zo
@@ -2802,8 +2874,8 @@ context where local variables exist. Examples:
@item
If the code around the breakpoint is something like
-"(for ([n 100]) _)", then a condition like
-"(zero? (modulo n 10))" is every 10 times through the
+``(for ([n 100]) _)'', then a condition like
+``(zero? (modulo n 10))'' is every 10 times through the
loop.
@end itemize
@@ -2872,7 +2944,7 @@ error message due to the bytecode being different
versions.
@end itemize
To revert to compiling on startup, use
-@ref{racket-mode-start-slower}.
+@ref{racket-mode-start-slower}.
@node racket-mode-start-slower
@subsection racket-mode-start-slower
@@ -2906,7 +2978,7 @@ Delete the ``compiled'' directories made by
@ref{racket-mode-start-faster}.
* racket-browse-url-function::
* racket-xp-after-change-refresh-delay::
* racket-xp-highlight-unused-regexp::
-* racket-xp-binding-font-lock-face-modes::
+* racket-xp-add-binding-faces::
* racket-documentation-search-location::
@end menu
@@ -2932,7 +3004,7 @@ their response asychronously.
@node racket-memory-limit
@subsection racket-memory-limit
-Terminate the Racket process if memory use exceeds this value in MB.
+Terminate the Racket process if memory use exceeds this value in MB@.
Changes to this value take effect upon the next @ref{racket-run}. A value
of 0 means no limit.
@@ -3006,7 +3078,7 @@ The following values will @emph{not} work:
@node racket-browse-url-function
@subsection racket-browse-url-function
-Function to call to browse a URL.
+Function to call to browse a URL@.
@node racket-xp-after-change-refresh-delay
@subsection racket-xp-after-change-refresh-delay
@@ -3023,12 +3095,12 @@ Only give @ref{racket-xp-unused-face} to unused
bindings that match this regexp.
The default is to highlight identifiers that do not start with
an underline, which is a common convention.
-@node racket-xp-binding-font-lock-face-modes
-@subsection racket-xp-binding-font-lock-face-modes
+@node racket-xp-add-binding-faces
+@subsection racket-xp-add-binding-faces
-Major modes where @ref{racket-xp-mode} will fontify binding identifier sites.
+Have @ref{racket-xp-mode} fontify binding identifier sites.
-A `font-lock-face property is added for bindings from:
+A 'font-lock-face property is added for bindings from:
@itemize
@item
@@ -3045,7 +3117,7 @@ local definitions, using
@ref{racket-xp-binding-local-face} and
@end itemize
This has a visible effect only when there is @emph{not} also a
-`face property applied by the major mode's fontification.
+'face property applied by the major mode's fontification.
@node racket-documentation-search-location
@subsection racket-documentation-search-location
@@ -3063,7 +3135,7 @@ search page from the local documentation, as with ``raco
doc''.
Otherwise, the value is a string recognizable by @code{format}, with
``%s'' at the point at which to insert the user's search text
after applying @code{url-hexify-string}. Apart from ``%s'', the
-string should be a properly encoded URL.
+string should be a properly encoded URL@.
@end itemize
@node Hash lang variables
@@ -3080,7 +3152,7 @@ string should be a properly encoded URL.
An association list from color-lexer token symbols to face symbols.
Note: In many Racket languages, the lexer classifies tokens for
-identifiers as `symbol. In many programs, a majority of the
+identifiers as 'symbol. In many programs, a majority of the
source consists of identifiers at binding definition and use
sites. Therefore the appearance of ``symbol'' tokens is
significant, and a matter of personal preference.
@@ -3088,17 +3160,16 @@ significant, and a matter of personal preference.
@itemize
@item
If you prefer a ``plainer'' appearance, similar to Dr Racket:
-Add `symbol with the value `default. This gives an
-explicit `face property that prevails over any
-`font-lock-face property that a minor mode might apply to
+Add 'symbol with the value 'default. This gives an
+explicit 'face property that prevails over any
+'font-lock-face property that a minor mode might apply to
enhance the basic fontification.
@item
If you prefer a more ``colorful'' appearance, similar to
-``classic'' @ref{racket-mode}: Do @emph{not} map `symbol tokens in
-this list. Instead enable @ref{racket-xp-mode} and let it do
-``semantic'' highlighting of bindings; see the customization
-variable @ref{racket-xp-binding-font-lock-face-modes}.
+``classic'' @ref{racket-mode}: Do @emph{not} map 'symbol tokens in
+this list. See @ref{racket-hash-lang-module-language-hook} for
+ideas.
@end itemize
Note: Some tokens are hardwired and not customizable by this
@@ -3145,10 +3216,42 @@ plainer @code{electric-pair-mode}.
(paredit-mode 1))
(t
(paredit-mode -1)
+ (setq-local electric-pair-inhibit-predicate
+ #'electric-pair-conservative-inhibit)
(electric-pair-local-mode 1))))
(add-hook 'racket-hash-lang-module-language-hook #'my-hook)
@end lisp
+As another example, if you prefer richer font-lock than just
+tokens, choices include:
+
+@itemize
+@item
+Use some of @ref{racket-mode}s regexp search-based fontification
+for some module languages:
+@end itemize
+
+@lisp
+ (require 'racket-font-lock)
+ ;; When the module-language is rackety
+ (font-lock-add-keywords nil (append racket-font-lock-keywords-2
+ racket-font-lock-keywords-3))
+ ;; Otherwise
+ (font-lock-remove-keywords nil (append racket-font-lock-keywords-2
+ racket-font-lock-keywords-3))
+@end lisp
+
+@itemize
+@item
+Enable @ref{racket-xp-mode} in @code{racket-hash-lang-mode-hook} and in
+the module language hook locally set
+@ref{racket-xp-add-binding-faces}:
+@end itemize
+
+@lisp
+ (setq-local racket-xp-add-binding-faces t)
+@end lisp
+
@node REPL variables
@section REPL variables
@@ -3210,7 +3313,7 @@ It is NOT used by commands that run one specific module,
such as:
@item
@ref{racket-run-module-at-point} @kbd{C-c C-k} or @kbd{C-c C-c}
@item
-@ref{racket-test} @kbd{<C-f5>} or @kbd{C-c C-t}
+@ref{racket-test} @kbd{C-<f5>} or @kbd{C-c C-t}
@item
@ref{racket-profile}
@end itemize
@@ -3229,7 +3332,7 @@ Default value is a regexp to ignore input that is all
whitespace.
@node racket-images-inline
@subsection racket-images-inline
-Whether to display inline images in the REPL.
+Whether to display inline images in the REPL@.
@node racket-imagemagick-props
@subsection racket-imagemagick-props
@@ -3257,7 +3360,7 @@ The image viewer program to use for
@code{racket-view-image}.
@node racket-pretty-print
@subsection racket-pretty-print
-Use pretty-print instead of print in REPL?
+Use pretty-print instead of print in REPL@?
@node Other variables
@section Other variables
@@ -3297,7 +3400,7 @@ file-local variable.
@node racket-pretty-lambda
@subsection racket-pretty-lambda
-Display lambda keywords using λ. This is DEPRECATED.
+Display lambda keywords using λ. This is DEPRECATED@.
Instead use @code{prettify-symbols-mode} in newer verisons of Emacs,
or, use @ref{racket-insert-lambda} to insert actual λ characters.
@@ -3408,7 +3511,7 @@ An ``abnormal hook'' variable to customize
@code{racket-show}.
This is a list of one or more functions.
-Each such function must accept two arguments: STR and POS.
+Each such function must accept two arguments: STR and POS@.
STR is one of:
@@ -3430,11 +3533,11 @@ Otherwise POS is the buffer position -- typically the
end of a
span -- that the non-blank STR describes.
A function that shows STR near POS should position it not to hide
-the span, i.e. below and/or right of POS. Examples:
+the span, i.e. below and/or right of POS@. Examples:
@ref{racket-show-pseudo-tooltip} and @ref{racket-show-pos-tip}.
A function that shows STR in a fixed location may of course
-ignore POS. Examples: @ref{racket-show-echo-area} and
+ignore POS@. Examples: @ref{racket-show-echo-area} and
@ref{racket-show-header-line}
@node Running racket and raco commands in a shell or terminal
@@ -3460,14 +3563,14 @@ Predefined choices include @ref{racket-shell},
@ref{racket-term},
@chapter Configuration functions
@menu
-* Showing information: Showing informationx.
+* Showing information: Showing information (1).
* Associating edit buffers with REPL buffers::
* Browsing file URLs with anchors::
* Configuring back ends::
-* Running racket and raco commands in a shell or terminal: Running racket and
raco commands in a shell or terminalx.
+* Running racket and raco commands in a shell or terminal: Running racket and
raco commands in a shell or terminal (1).
@end menu
-@node Showing informationx
+@node Showing information (1)
@section Showing information
@menu
@@ -3663,7 +3766,7 @@ DIRECTORY can be a local directory like ``/'' or
Note that you need not include a method -- such as the ``ssh'' in
``/ssh:user@@host:'' -- and if you do it is stripped: A back end
-process is always started using SSH. Even if multiple buffers for
+process is always started using SSH@. Even if multiple buffers for
the same user+host+port use different methods, they will share
the same back end.
@@ -3773,7 +3876,7 @@ are a few examples.
:racket-program "xvfb-run racket")
@end lisp
-@node Running racket and raco commands in a shell or terminalx
+@node Running racket and raco commands in a shell or terminal (1)
@section Running racket and raco commands in a shell or terminal
@menu
@@ -3929,42 +4032,42 @@ Face @ref{racket-xp-mode} uses to highlight expressions
in a tail position.
Face @ref{racket-xp-mode} gives to the module language name.
-See the variable @ref{racket-xp-binding-font-lock-face-modes}.
+See the variable @code{nil}.
@node racket-xp-binding-lang-use-face
@subsection racket-xp-binding-lang-use-face
Face @ref{racket-xp-mode} gives uses of bindings imported from the module
language.
-See the variable @ref{racket-xp-binding-font-lock-face-modes}.
+See the variable @code{nil}.
@node racket-xp-binding-import-face
@subsection racket-xp-binding-import-face
Face @ref{racket-xp-mode} gives to imported module names.
-See the variable @ref{racket-xp-binding-font-lock-face-modes}.
+See the variable @code{nil}.
@node racket-xp-binding-import-use-face
@subsection racket-xp-binding-import-use-face
Face @ref{racket-xp-mode} gives uses of imported bindings.
-See the variable @ref{racket-xp-binding-font-lock-face-modes}.
+See the variable @code{nil}.
@node racket-xp-binding-local-face
@subsection racket-xp-binding-local-face
Face @ref{racket-xp-mode} gives to local definitions.
-See the variable @ref{racket-xp-binding-font-lock-face-modes}.
+See the variable @code{nil}.
@node racket-xp-binding-local-use-face
@subsection racket-xp-binding-local-use-face
Face @ref{racket-xp-mode} gives to uses of local definitions.
-See the variable @ref{racket-xp-binding-font-lock-face-modes}.
+See the variable @code{nil}.
@node racket-logger-config-face
@subsection racket-logger-config-face
@@ -4060,5 +4163,4 @@ Face @ref{racket-repl-mode} uses for output to
current-output-port.
Face @ref{racket-repl-mode} uses for output to current-error-port.
-@c Emacs 25.2.2 (Org mode 8.2.10)
@bye
\ No newline at end of file
diff --git a/racket-custom.el b/racket-custom.el
index 8ea917a51d..a38ad0f70c 100644
--- a/racket-custom.el
+++ b/racket-custom.el
@@ -146,8 +146,8 @@ an underline, which is a common convention."
:safe #'stringp
:group 'racket-xp)
-(defcustom racket-xp-binding-font-lock-face-modes '(racket-hash-lang-mode)
- "Major modes where `racket-xp-mode' will fontify binding identifier sites.
+(defcustom racket-xp-add-binding-faces nil
+ "Have `racket-xp-mode' fontify binding identifier sites.
A \\='font-lock-face property is added for bindings from:
@@ -197,9 +197,8 @@ significant, and a matter of personal preference.
- If you prefer a more \"colorful\" appearance, similar to
\"classic\" `racket-mode': Do /not/ map \\='symbol tokens in
- this list. Instead enable `racket-xp-mode' and let it do
- \"semantic\" highlighting of bindings; see the customization
- variable `racket-xp-binding-font-lock-face-modes'.
+ this list. See `racket-hash-lang-module-language-hook' for
+ ideas.
Note: Some tokens are hardwired and not customizable by this
list: Comment tokens use the face `font-lock-comment-face',
diff --git a/racket-font-lock.el b/racket-font-lock.el
index f97c12235b..7003f174fb 100644
--- a/racket-font-lock.el
+++ b/racket-font-lock.el
@@ -230,28 +230,15 @@
(group (1+ (or (syntax word) (syntax symbol) (syntax
punctuation)))))
(1 font-lock-keyword-face nil t)
(2 font-lock-function-name-face nil t))))
- "Parens, modules, function/variable identifiers, syntax-")
+ "Definition forms, let-bound identifiers, module forms.")
(defconst racket-font-lock-keywords-3
(eval-when-compile
`((,(regexp-opt racket-keywords 'symbols) . font-lock-keyword-face)
(,(regexp-opt racket-builtins-1-of-2 'symbols) . font-lock-builtin-face)
(,(regexp-opt racket-builtins-2-of-2 'symbols) . font-lock-builtin-face)
- (,(regexp-opt racket-type-list 'symbols) . font-lock-type-face)
-
- ;; pretty lambda (deprecated)
- (,(rx (syntax open-parenthesis)
- (? (or "case-" "match-" "opt-"))
- (group "lambda")
- (or word-end symbol-end))
- 1
- (ignore
- (when racket-pretty-lambda
- (compose-region (match-beginning 1)
- (match-end 1)
- racket-lambda-char)))
- nil t)))
- "Function/variable identifiers, Typed Racket types.
+ (,(regexp-opt racket-type-list 'symbols) . font-lock-type-face)))
+ "A curated list of popular Racket lang identifiers and Typed Racket types.
Note: To the extent you use #lang racket or #typed/racket, this
may be handy. But Racket is also a tool to make #lang's, and this
diff --git a/racket-hash-lang.el b/racket-hash-lang.el
index 63f37f6509..aa71504d98 100644
--- a/racket-hash-lang.el
+++ b/racket-hash-lang.el
@@ -125,9 +125,35 @@ plainer `electric-pair-mode'.
(paredit-mode 1))
(t
(paredit-mode -1)
+ (setq-local electric-pair-inhibit-predicate
+ #\\='electric-pair-conservative-inhibit)
(electric-pair-local-mode 1))))
(add-hook \\='racket-hash-lang-module-language-hook #\\='my-hook)
#+END_SRC
+
+As another example, if you prefer richer font-lock than just
+tokens, choices include:
+
+- Use some of `racket-mode's regexp search-based fontification
+ for some module languages:
+
+#+BEGIN_SRC elisp
+ (require \\='racket-font-lock)
+ ;; When the module-language is rackety
+ (font-lock-add-keywords nil (append racket-font-lock-keywords-2
+ racket-font-lock-keywords-3))
+ ;; Otherwise
+ (font-lock-remove-keywords nil (append racket-font-lock-keywords-2
+ racket-font-lock-keywords-3))
+#+END_SRC
+
+- Enable `racket-xp-mode' in `racket-hash-lang-mode-hook' and in
+ the module language hook locally set
+ `racket-xp-add-binding-faces':
+
+#+BEGIN_SRC elisp
+ (setq-local racket-xp-add-binding-faces t)
+#+END_SRC
")
(defvar-local racket--hash-lang-id nil
@@ -180,13 +206,28 @@ can contribute more colors; see the customization variable
#'racket-mode-maybe-offer-to-kill-repl-buffer
nil t)
(set-syntax-table racket--plain-syntax-table)
- (setq-local font-lock-defaults nil)
- (font-lock-set-defaults) ;issue #642
- (setq-local syntax-propertize-function nil)
+ ;; Here we do the usual, approved thing: Set `font-lock-defaults'
+ ;; (and let `font-lock-set-defaults' to calculate and set other
+ ;; font-lock-xxx variables correctly).
+ (setq font-lock-defaults
+ (list
+ ;; "keywords": Although we contribute none here (we color
+ ;; solely based on lang lexer tokens), we support other
+ ;; parties using `font-lock-add-keywords', such as a minor
+ ;; mode -- or even an end user adding all the static
+ ;; `racket-mode' font-lock keywords when the hash-lang is
+ ;; racket.
+ nil
+ ;; "keywords-only?": We absolutely don't want any syntactic
+ ;; fontification; see e.g. #679. Any char syntx table we set
+ ;; is intended to hep fit into the Emacs ecosystem for things
+ ;; like `paredit' or `electric-pair-mode'. Using that for
+ ;; font-lock isn't reliable; we trust the lang lexer tokens,
+ ;; only.
+ t))
(setq-local text-property-default-nonsticky
- (append
- (racket--hash-lang-text-prop-list #'cons t)
- text-property-default-nonsticky))
+ (append (list (cons 'racket-token t))
+ text-property-default-nonsticky))
(electric-indent-local-mode -1)
(setq-local electric-indent-inhibit t)
(setq-local blink-paren-function nil)
@@ -227,7 +268,7 @@ can contribute more colors; see the customization variable
(cond
(maybe-id
(setq-local racket--hash-lang-id maybe-id)
- ;; These depend on `racket--hash-lang-id':
+ ;; These need non-nil `racket--hash-lang-id':
(setq-local font-lock-fontify-region-function
#'racket--hash-lang-fontify-region)
(add-hook 'after-change-functions #'racket--hash-lang-after-change-hook
t t)
(add-hook 'kill-buffer-hook #'racket--hash-lang-delete t t)
@@ -356,9 +397,8 @@ lang's attributes that we care about have changed."
;; If the lang uses racket-grouping-position, i.e. it uses
;; s-expressions, then use racket-mode-syntax-table. That way
;; other Emacs features and packages are more likely to work.
- ;; Otherwise, assume nothing about the lang and set a "plain"
- ;; syntax table where no characters are assumed to delimit
- ;; parens, comments, or strings.
+ ;; Otherwise, make a syntax table assuming nothing but what the
+ ;; lang reports for parens and quotes.
(set-syntax-table (if (plist-get plist 'racket-grouping)
racket-mode-syntax-table
(racket--make-non-sexp-syntax-table
@@ -411,7 +451,7 @@ lang's attributes that we care about have changed."
"The back end has processed a change that resulted in new tokens.
All we do here is mark the span as not fontified, then let
-jit-lock do its thing if/when this span ever becomes visible."
+jit-lock do its thing as/when this span ever becomes visible."
;;;(message "racket--hash-lang-on-changed-tokens %s %s %s" _gen beg end)
(save-restriction
(widen)
@@ -420,17 +460,14 @@ jit-lock do its thing if/when this span ever becomes
visible."
;;; Fontification
-(defun racket--hash-lang-fontify-region (beg end loudly)
+(defun racket--hash-lang-fontify-region (beg end _loudly)
"Our value for the variable `font-lock-fontify-region-function'.
-We ask the back end for tokens, and handle its response
-asynchronously in `racket--hash-lang-on-tokens' which does the
-actual application of faces and syntax. It wouldn't be
-appropriate to wait for a response while being called from Emacs
-C redisplay engine."
+Just claim we fontified the region now, and ask the back end for
+tokens asynchronously. Inappropriate to wait for a response while
+being called from Emacs C redisplay engine."
;;;(message "racket--hash-lang-fontify-region %s %s" beg end)
(when racket--hash-lang-id
- (font-lock-default-fontify-region beg end loudly)
(let ((beg (if (markerp beg) (marker-position beg) beg))
(end (if (markerp end) (marker-position end) end)))
(racket--cmd/async nil
@@ -439,66 +476,96 @@ C redisplay engine."
,racket--hash-lang-generation
,beg
,end)
- #'racket--hash-lang-on-tokens))
+ (lambda (tokens)
+ (racket--hash-lang-tokens+fontify beg end tokens))))
`(jit-lock-bounds ,beg . ,end)))
-(defun racket--hash-lang-on-tokens (tokens)
- ;;;(message "racket--hash-lang-on-tokens %S" tokens)
+(defun racket--hash-lang-tokens+fontify (beg end tokens)
+ "Put token properties and do \"normal\" keyword fontification, both.
+
+Although we could have done the normal fontification earlier
+synchronously, and done token propertization here later, the
+result wouldn't always be consistent. It's best to handle both
+together -- and best to token propertize first, since that sets
+syntax-table props for comments and strings, thereby correctly
+preventing keyword fontification inside those.
+
+We only call `font-lock-fontify-keywords-region', not the full
+`font-lock-default-fontify-region'. Why: 1. We only support
+keyword fontification, not syntactic. Even though we set
+`font-lock-keywords-only' true in our mode initialization,
+belt+suspenders here. 2. It makes moot the value of
+`font-lock-extend-region-functions', so that's one less value
+that need be set. "
+ ;;;(message "racket--hash-lang-tokens+fontify %S %S <tokens>" beg end)
+ (with-silent-modifications
+ ;; As this removes face property do it before adding face props
+ ;; from tokens.
+ (save-excursion
+ (font-lock-unfontify-region beg end))
+ (racket--hash-lang-put-tokens tokens)
+ (save-excursion
+ (font-lock-fontify-keywords-region beg end))))
+
+(defun racket--hash-lang-put-tokens (tokens)
+ ;;;(message "racket--hash-lang-put-tokens %S" tokens)
+ ;; Assumes called within dynamic extent of `with-silent-modifications'.
(save-restriction
(widen)
- (with-silent-modifications
- (cl-flet* ((put-face (beg end face) (put-text-property beg end 'face
face))
- (put-stx (beg end stx) (put-text-property beg end
'syntax-table stx))
- (put-fence (beg end stx)
- (put-stx beg (1+ beg) stx)
- (put-stx (1- end) end stx)))
- (dolist (token tokens)
- (pcase-let ((`(,beg ,end ,kinds) token))
- (setq beg (max (point-min) beg))
- (setq end (min end (point-max)))
- (racket--hash-lang-remove-text-properties beg end)
- ;; Add 'racket-token just for me to examine results using
- ;; `describe-char'; use vector b/c `describe-property-list'
- ;; assumes lists of symbols are "widgets".
- (put-text-property beg end 'racket-token (apply #'vector kinds))
- (dolist (kind kinds)
- (pcase kind
- ('comment
- (put-face beg end 'font-lock-comment-face)
- (put-fence beg end '(14)))
- ('sexp-comment ;just the "#;" prefix not following sexp body
- (put-face beg end 'font-lock-comment-face)
- (put-fence beg end '(14)))
- ('string
- (put-face beg end 'font-lock-string-face)
- (put-fence beg end '(15)))
- ;; Note: This relies on the back end supplying `kinds`
- ;; with sexp-comment-body last, so that we can modify
- ;; the face property already set by the previous
- ;; kind(s).
- ('sexp-comment-body
- (put-face beg end (racket--sexp-comment-face
- (get-text-property beg 'face))))
- ('parenthesis (when (facep 'parenthesis)
- (put-face beg end 'parenthesis)))
- ('text (put-stx beg end racket--plain-syntax-table))
- (sym
- (when-let (face (cdr (assq sym
racket-hash-lang-token-face-alist)))
- (put-face beg end face)))))))))))
-
-(defconst racket--hash-lang-text-properties
- '(syntax-table racket-token)
- "The text properties we use.")
-
-(defun racket--hash-lang-text-prop-list (f val)
- (mapcar (lambda (prop-sym) (funcall f prop-sym val))
- racket--hash-lang-text-properties))
+ (cl-flet* ((put-face (beg end face)
+ (add-text-properties beg end
+ (list 'face face
+ 'rear-nonsticky t)))
+ (get-face-at (pos)
+ (get-text-property pos 'face))
+ (remove-face (beg end)
+ (remove-list-of-text-properties beg end
+ (list
+ 'face
+ 'rear-nonsticky)))
+ (put-stx (beg end stx)
+ (put-text-property beg end 'syntax-table stx))
+ (put-fence (beg end stx)
+ (put-stx beg (1+ beg) stx)
+ (put-stx (1- end) end stx)))
+ (dolist (token tokens)
+ (pcase-let ((`(,beg ,end ,kinds) token))
+ (setq beg (max (point-min) beg))
+ (setq end (min end (point-max)))
+ (racket--hash-lang-remove-text-properties beg end)
+ ;; Add a 'racket-token prop used just for me to inspect via
+ ;; `describe-char'. Use a vector of symbols as the value
+ ;; because `describe-property-list' presents lists of
+ ;; symbols as "widgets" in the UI.
+ (put-text-property beg end 'racket-token (apply #'vector kinds))
+ (dolist (kind kinds)
+ (pcase kind
+ ('comment
+ (put-face beg end 'font-lock-comment-face)
+ (put-fence beg end '(14)))
+ ('sexp-comment ;just the "#;" prefix not following sexp body
+ (put-face beg end 'font-lock-comment-face)
+ (put-fence beg end '(14)))
+ ('string
+ (put-face beg end 'font-lock-string-face)
+ (put-fence beg end '(15)))
+ ;; Note: This relies on the back end supplying `kinds`
+ ;; with sexp-comment-body last, so that we can modify
+ ;; the face property already set by the previous
+ ;; kind(s).
+ ('sexp-comment-body
+ (put-face beg end (racket--sexp-comment-face (get-face-at
beg))))
+ ('parenthesis (when (facep 'parenthesis)
+ (put-face beg end 'parenthesis)))
+ ('text (put-stx beg end racket--plain-syntax-table))
+ (kind
+ (if-let (face (cdr (assq kind
racket-hash-lang-token-face-alist)))
+ (put-face beg end face)
+ (remove-face beg end))))))))))
(defun racket--hash-lang-remove-text-properties (beg end)
"Remove `racket--hash-lang-text-properties' from region BEG..END."
- (remove-text-properties beg end
- (apply #'append
- (racket--hash-lang-text-prop-list #'list
nil))))
+ (remove-list-of-text-properties beg end '(syntax-table racket-token)))
;;; Indent
diff --git a/racket-xp.el b/racket-xp.el
index 902cceaef8..4eb10ab004 100644
--- a/racket-xp.el
+++ b/racket-xp.el
@@ -451,83 +451,80 @@ manually."
"Insert text properties."
(with-silent-modifications
(overlay-recenter (point-max))
- (let ((binding-font-lock-face-p (and (memq major-mode
-
racket-xp-binding-font-lock-face-modes)
- t)))
- (dolist (x xs)
- (pcase x
- (`(error ,path ,beg ,end ,str)
- (let ((path (racket-file-name-back-to-front path)))
- (racket--xp-add-error path beg str)
- (when (equal path (racket--buffer-file-name))
- (remove-text-properties
- beg end
- (list 'help-echo nil
- 'racket-xp-def nil
- 'racket-xp-use nil))
- (racket--add-overlay beg end racket-xp-error-face)
- (add-text-properties
- beg end
- (list 'help-echo str)))))
- (`(info ,beg ,end ,str)
- (put-text-property beg end 'help-echo str)
- (when (and (string-equal str "no bound occurrences")
- (string-match-p racket-xp-highlight-unused-regexp
- (buffer-substring beg end)))
- (racket--add-overlay beg end racket-xp-unused-face)))
- (`(unused-require ,beg ,end)
- (put-text-property beg end 'help-echo "unused require")
- (racket--add-overlay beg end racket-xp-unused-face))
- (`(require ,beg ,end ,file)
- (put-text-property beg end 'racket-xp-require file))
- (`(def/uses ,def-beg ,def-end ,req ,id ,uses)
- (let ((def-beg (copy-marker def-beg t))
- (def-end (copy-marker def-end t))
- (uses (mapcar (lambda (use)
- (mapcar (lambda (pos)
- (copy-marker pos t))
- use))
- uses)))
- (put-text-property (marker-position def-beg)
- (marker-position def-end)
- 'racket-xp-def (list req id uses))
- (when binding-font-lock-face-p
- (racket--xp-add-def-face (marker-position def-beg)
- (marker-position def-end)
- req))
- (dolist (use uses)
- (pcase-let* ((`(,use-beg ,use-end) use))
- (put-text-property (marker-position use-beg)
- (marker-position use-end)
- 'racket-xp-use (list def-beg def-end))
- (when binding-font-lock-face-p
- (racket--xp-add-use-face (marker-position use-beg)
- (marker-position use-end)
- req))))))
- (`(target/tails ,target ,calls)
- (let ((target (copy-marker target t))
- (calls (mapcar (lambda (call)
- (copy-marker call t))
- calls)))
- (put-text-property (marker-position target)
- (1+ (marker-position target))
- 'racket-xp-tail-target
- calls)
- (dolist (call calls)
- (put-text-property (marker-position call)
- (1+ (marker-position call))
- 'racket-xp-tail-position
- target))))
- (`(jump ,beg ,end ,path ,subs ,ids)
- (add-text-properties
- beg end
- (list 'racket-xp-visit
- (list (racket-file-name-back-to-front path) subs ids))))
- (`(doc ,beg ,end ,path ,anchor)
- (add-text-properties
- beg end
- (list 'racket-xp-doc
- (list (racket-file-name-back-to-front path) anchor)))))))))
+ (dolist (x xs)
+ (pcase x
+ (`(error ,path ,beg ,end ,str)
+ (let ((path (racket-file-name-back-to-front path)))
+ (racket--xp-add-error path beg str)
+ (when (equal path (racket--buffer-file-name))
+ (remove-text-properties
+ beg end
+ (list 'help-echo nil
+ 'racket-xp-def nil
+ 'racket-xp-use nil))
+ (racket--add-overlay beg end racket-xp-error-face)
+ (add-text-properties
+ beg end
+ (list 'help-echo str)))))
+ (`(info ,beg ,end ,str)
+ (put-text-property beg end 'help-echo str)
+ (when (and (string-equal str "no bound occurrences")
+ (string-match-p racket-xp-highlight-unused-regexp
+ (buffer-substring beg end)))
+ (racket--add-overlay beg end racket-xp-unused-face)))
+ (`(unused-require ,beg ,end)
+ (put-text-property beg end 'help-echo "unused require")
+ (racket--add-overlay beg end racket-xp-unused-face))
+ (`(require ,beg ,end ,file)
+ (put-text-property beg end 'racket-xp-require file))
+ (`(def/uses ,def-beg ,def-end ,req ,id ,uses)
+ (let ((def-beg (copy-marker def-beg t))
+ (def-end (copy-marker def-end t))
+ (uses (mapcar (lambda (use)
+ (mapcar (lambda (pos)
+ (copy-marker pos t))
+ use))
+ uses)))
+ (put-text-property (marker-position def-beg)
+ (marker-position def-end)
+ 'racket-xp-def (list req id uses))
+ (when racket-xp-add-binding-faces
+ (racket--xp-add-def-face (marker-position def-beg)
+ (marker-position def-end)
+ req))
+ (dolist (use uses)
+ (pcase-let* ((`(,use-beg ,use-end) use))
+ (put-text-property (marker-position use-beg)
+ (marker-position use-end)
+ 'racket-xp-use (list def-beg def-end))
+ (when racket-xp-add-binding-faces
+ (racket--xp-add-use-face (marker-position use-beg)
+ (marker-position use-end)
+ req))))))
+ (`(target/tails ,target ,calls)
+ (let ((target (copy-marker target t))
+ (calls (mapcar (lambda (call)
+ (copy-marker call t))
+ calls)))
+ (put-text-property (marker-position target)
+ (1+ (marker-position target))
+ 'racket-xp-tail-target
+ calls)
+ (dolist (call calls)
+ (put-text-property (marker-position call)
+ (1+ (marker-position call))
+ 'racket-xp-tail-position
+ target))))
+ (`(jump ,beg ,end ,path ,subs ,ids)
+ (add-text-properties
+ beg end
+ (list 'racket-xp-visit
+ (list (racket-file-name-back-to-front path) subs ids))))
+ (`(doc ,beg ,end ,path ,anchor)
+ (add-text-properties
+ beg end
+ (list 'racket-xp-doc
+ (list (racket-file-name-back-to-front path) anchor))))))))
(defun racket--xp-add-binding-face (beg end face)
(add-text-properties beg end
@@ -572,6 +569,11 @@ manually."
'racket-xp-visit nil
'racket-xp-doc nil
'racket-xp-require nil
+ ;; TODO: Shouldn't do this
+ ;; unconditionally, need some
+ ;; other prop to record spans
+ ;; where WE added this, and
+ ;; remove only those.
'font-lock-face nil)))))
;;; xref