Skip to content

Commit

Permalink
Many enhancements to racket-describe and racket-describe-search
Browse files Browse the repository at this point in the history
This commit is a squash of a branch with many dozens of commits.

=== racket-describe ===

1. Build/massage shr dom for docs on front end

Previously the back end would read a Racket documentation HTML file,
create an xexpr, convert that to HTML text, and return it to the front
end... which would use libxml-parse-html-region to convert to a shr
"dom", and use shr-insert to add that to the Emacs buffer.

The silly part there is the extra conversion to HTML text and back
again. (It probably made sense in the early days of Racket mode, when
command responses were written into the REPL buffer, and it was more
reliable to handle a single string literal.)

In an interim commit I had the back end directly build the shr dom
needed by the front end. Better. Then I took it a step further: Emacs
is perfectly capable of reading an HTML file to a shr dom, and doing
the same kind of massaging that the back end was doing. (Although
Emacs Lisp pcase is not quite as elegant as Racket match, for the
massaging, it's capable, and the massaging is mostly a non-elegant
pile of hacks, anyway.)

In the common case where we already know the doc path and anchor from
racket-xp-mode having annotated that, this avoids needing to send a
back end command at all. In my testing so far it seems faster;
certainly not slower.

In the remaining cases, we still need to do a back end describe
command. In the case where doc is found, it can simply return the path
and anchor, and the front end loads the same way. Otherwise describe
returns a shr dom describing the signature, type, and/or contract, or
nil if none of those can be found.

2. Render entire doc pages

Previously we would try to return just an excerpt of the HTML -- given
some anchor, return the heading/bluebox for that anchor, up until
another heading/bluebox. The justification of the excerpt approach was
that it could be faster.

Although this worked well for most documentation, it wasn't ideal for
things with very brief descriptions, where the author expected users
could scroll up or down for more context.

Furthermore, racket-describe-search now supports searching any term in
the documentation index (not just exports; see below), and we are now
supporting intra-doc links and anchors (see below). As a result,
sometimes we're returning documentation for things like a techdef.
Here again, sometimes a short section is intended to be understood in
the context of a complete doc page.

As a result, this commit takes the approach of always returning
complete documentation pages. Although this can be slower for very
large doc pages, overall and on balance I think the experience is
better. Certainly it presents the documentation more closely to how
authors expect readers to be able to use it.

Related:

- Show path/anchor in header-line.

- Support extracting the navsettop (top, up, prev, next) links as a
`racket-nav` element to be used as info-mode style navigation
commands.

3. Improve rendering of Racket doc pages

Handle code block tables with single td per row, which is a weird
thing Scribble does, and which shr handles weirdly, by instead
converting them to simple divs. This avoids problems with the initial
line or two of code blocks being indented too much.

Inspect span elements for classes like RktSym, RktVal, and so on, and
use various faces like font-lock-keyword-face and so on.

4. Support intra-doc links

Back end:

- Supply custom HTML tags `racket-anchor`, `racket-doc-link`, and
`racket-ext-link` and for the front end to use.

- Handle all three flavors of local-redirect links.

Front end:

- Support visiting links to other documentation.

- Support forward/back navigation history, including restoring point.

- Add faces to let users customize internal and external links.

=== racket-describe-search ===

1. Name, keybindings

Rename from racket-search-describe to be consistent with e.g.
racket-documentation-search.

Give it a C-c C-s binding in various modes like racket-xp-mode and
racket-repl-mode, as well as racket-describe-mode and
racket-describe-search-mode themselves.

2. Use "streaming" elisp-writeln and thunk for doc index response.

Rather than converting an entire value from Racket to Elisp and
writing that, elisp-writeln now writes the value piece by piece
directly to the current output port.

Furthermore, when a value is a thunk, it calls the thunk which can
elisp-writeln one by one directly out.

Use this capability in the doc-index-names command, which responds
with a very long list of strings. This reduces peak memory use.

Also, refine the front-end UX for racket-search-describe, to wait
about 5 seconds for doc-index-names to respond, otherwise it proceeds
with an empty list of completion candidates. This is a sort of warm
bowl of porridge, in between racket--cmd/async and racket--cmd/await.
Effectively it is a bespoke variation of the latter. (I think this is
probably a good strategy for eliminating the few remaining uses of
racket--cmd/await: Use a timeout amount and default value that is
appropriate for each specific situation -- as opposed to the extremes
of waiting forever or giving a "command timeout" error.)

3. Use xref entry-words

This handles things like for example entries where
exported-index-desc-name is "drracket:unit:frame%" and where
entry-words is a class method name like "add-show-menu-items".

4. Handle all doc index terms, not just exports.
  • Loading branch information
greghendershott committed Oct 5, 2021
1 parent 794f737 commit 46df4d9
Show file tree
Hide file tree
Showing 13 changed files with 1,349 additions and 521 deletions.
2 changes: 1 addition & 1 deletion doc/generate.el
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@
(racket-xp-tail-next-sibling ,racket-xp-mode-map)
(racket-xp-tail-previous-sibling ,racket-xp-mode-map)
racket-documentation-search
racket-search-describe
racket-describe-search
"Run"
racket-repl-mode
racket-run
Expand Down
32 changes: 15 additions & 17 deletions doc/racket-mode.texi
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ Explore
* racket-xp-tail-next-sibling::
* racket-xp-tail-previous-sibling::
* racket-documentation-search::
* racket-search-describe::
* racket-describe-search::
Run
Expand Down Expand Up @@ -725,6 +725,10 @@ Major mode for editing Racket source files.
@tab @ref{racket-unfold-all-tests}
@item @kbd{C-c C-f}
@tab @ref{racket-fold-all-tests}
@item @kbd{C-c C-.}
@tab @ref{racket-describe-search}
@item @kbd{C-c C-s}
@tab @ref{racket-describe-search}
@item @kbd{C-c C-d}
@tab @ref{racket-documentation-search}
@item @kbd{C-c C-p}
Expand Down Expand Up @@ -1219,7 +1223,7 @@ completion candidates, enable the minor mode @ref{racket-xp-mode}.
* racket-xp-tail-next-sibling::
* racket-xp-tail-previous-sibling::
* racket-documentation-search::
* racket-search-describe::
* racket-describe-search::
@end menu

@node racket-xp-mode
Expand Down Expand Up @@ -1391,6 +1395,8 @@ commands directly to whatever keys you prefer.
@tab Binding
@item @kbd{M-.}
@tab @code{xref-find-definitions}
@item @kbd{C-c C-s}
@tab @ref{racket-describe-search}
@item @kbd{C-c C-d}
@tab @ref{racket-xp-documentation}
@item @kbd{C-c C-.}
Expand Down Expand Up @@ -1468,7 +1474,7 @@ Otheriwse behaves like 0.
@item
@kbd{C-u} @kbd{C-u}

This is an alias for @ref{racket-search-describe}, which uses
This is an alias for @ref{racket-describe-search}, which uses
installed documentation in a @code{racket-describe-mode} buffer
instead of an external web browser.
@end enumerate
Expand All @@ -1480,11 +1486,6 @@ something, regardless of whether it has installed documentation
This buffer is also displayed when you use @code{company-mode} and
press F1 or C-h in its pop up completion list.

You can quit the buffer by pressing q. Also, at the bottom of the
buffer are Emacs buttons -- which you may navigate among using
TAB, and activate using RET -- for @code{xref-find-definitions}
and @ref{racket-xp-documentation}.

@node racket-xp-documentation
@subsection racket-xp-documentation

Expand Down Expand Up @@ -1629,10 +1630,10 @@ This command does not try to go directly to the help topic for a
definition provided by any specific module. Instead it goes to
the Racket ``Search Manuals'' page.

@node racket-search-describe
@subsection racket-search-describe
@node racket-describe-search
@subsection racket-describe-search

@kbd{M-x} @code{racket-search-describe}
@kbd{C-c C-.} or @kbd{C-c C-s}

Search installed documentation; view using @code{racket-describe-mode}.

Expand Down Expand Up @@ -1702,6 +1703,8 @@ identifier bindings and modules from the REPL's namespace.
@tab @ref{racket-logger}
@item @kbd{C-c C-z}
@tab @code{racket-repl-switch-to-edit}
@item @kbd{C-c C-s}
@tab @ref{racket-describe-search}
@item @kbd{C-c C-.}
@tab @ref{racket-repl-describe}
@item @kbd{C-c C-d}
Expand Down Expand Up @@ -1880,7 +1883,7 @@ Otheriwse behaves like 0.
@item
@kbd{C-u} @kbd{C-u}

This is an alias for @ref{racket-search-describe}, which uses
This is an alias for @ref{racket-describe-search}, which uses
installed documentation in a @code{racket-describe-mode} buffer
instead of an external web browser.
@end enumerate
Expand All @@ -1889,11 +1892,6 @@ The intent is to give a quick reminder or introduction to
something, regardless of whether it has installed documentation
-- and to do so within Emacs, without switching to a web browser.

You can quit the buffer by pressing q. Also, at the bottom of the
buffer are Emacs buttons -- which you may navigate among using
TAB, and activate using RET -- for @code{xref-find-definitions}
and @ref{racket-repl-documentation}.

@node racket-repl-documentation
@subsection racket-repl-documentation

Expand Down
14 changes: 14 additions & 0 deletions racket-custom.el
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,20 @@ to hide the interesting span in the buffer."
"Face for `racket-debug-mode' result values."
"Racket Debug Result Face")

(defface-racket racket-doc-link-face
'((t (:underline (:color "gray" :style line))))
"Face for `racket-describe-mode' doc links to open in `racket-describe-mode'.
Note: When some special face is already specified by the
documentation, then to avoid visual clutter this face is NOT also
added."
"Racket Doc Link Face")

(defface-racket racket-ext-link-face
'((t (:underline (:style wave) :slant italic :weight bold)))
"Face for `racket-describe-mode' external links.
See the variable `racket-browse-url-function'."
"Racket Ext Link Face")

(provide 'racket-custom)

;; racket-custom.el ends here

0 comments on commit 46df4d9

Please sign in to comment.