Skip to content

Commit

Permalink
racket-describe: Surface "On this page" links via imenu
Browse files Browse the repository at this point in the history
  • Loading branch information
greghendershott committed Aug 31, 2024
1 parent dba66c4 commit 27fda40
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 32 deletions.
4 changes: 3 additions & 1 deletion racket-company-doc.el
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@
path anchor)
(let* ((tramp-verbose 2) ;avoid excessive messages
(dom (racket--html-file->dom path))
(body (racket--scribble-body dom))
(body (racket--scribble-path->shr-dom path))
(_ (pcase (dom-by-class dom "tocset")
(`(,node . ,_) (dom-remove-node body node))))
(elems (racket--company-elements-for-anchor body anchor))
(dom `(div () ,@elems))
(dom (racket--walk-dom dom)))
Expand Down
63 changes: 53 additions & 10 deletions racket-describe.el
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ anchor. If numberp, move to that position."
(racket-ext-link . ,#'racket-render-tag-racket-ext-link)
(racket-anchor . ,#'racket-render-tag-racket-anchor)
(racket-nav . ,#'racket-render-tag-racket-nav))))
(shr-insert-document dom))
(shr-insert-document
(racket--describe-handle-toc-nodes dom)))
;; See doc string for `racket--scribble-temp-nbsp'.
(goto-char (point-min))
(while (re-search-forward (string racket--scribble-temp-nbsp) nil t)
Expand All @@ -177,19 +178,57 @@ text. We want point left where `racket-search-describe' can use
((numberp goto)
goto)
((stringp goto)
(or (let ((i nil)) ;silence byte-compiler warning...
i ;...on all versions of emacs
(cl-loop for i being the intervals
if (equal (get-text-property (car i) 'racket-anchor)
goto)
return (cl-loop for j from (car i) to (point-max)
if (not (get-text-property j 'racket-anchor))
return j)))
(or (racket--describe-anchor->position goto)
(point-min)))
(t (point-min))))
(setq racket--describe-here
(cons (car racket--describe-here) (point))))

(defun racket--describe-anchor->position (anchor)
(let ((i nil)) ;silence byte-compiler warning...
i ;...on all versions of emacs
(cl-loop for i being the intervals
if (equal (get-text-property (car i) 'racket-anchor)
anchor)
return (cl-loop for j from (car i) to (point-max)
if (not (get-text-property j 'racket-anchor))
return j))))

(defvar-local racket--describe-on-this-page nil)

(defun racket--describe-handle-toc-nodes (dom)
"Handle nodes that render as a \"left nav panel\" in a web browser.
These aren't effective in a shr buffer, due to window width and
lack of independent scrolling columns. Instead:
- \"tocview\": Just delete it. User can nav up to see.
- \"tocsub\" a.k.a. \"On this page:\": Useful, but present via
`imenu'.
Both are children of a \"tocscet\" div."
(setq-local
racket--describe-on-this-page
(pcase (dom-by-class dom "tocsub")
(`(,node . ,_)
(dom-remove-node dom node)
(seq-map (lambda (node)
(cons (dom-texts node "")
(dom-attr node 'anchor)))
(dom-search node
(lambda (node)
(eq 'racket-doc-link (dom-tag node))))))))
(pcase (dom-by-class dom "tocset")
(`(,node . ,_) (dom-remove-node dom node)))
dom)

(defun racket--describe-imenu-create-index ()
(seq-map (lambda (v)
(cons (car v)
(racket--describe-anchor->position (cdr v))))
racket--describe-on-this-page))

(defconst racket--shr-faces
'(("RktSym" . font-lock-keyword-face)
("RktVal" . font-lock-constant-face)
Expand Down Expand Up @@ -474,7 +513,11 @@ browser program -- are given `racket-describe-ext-link-face'.
\\{racket-describe-mode-map}"
(setq show-trailing-whitespace nil)
(setq-local revert-buffer-function #'racket-describe-mode-revert-buffer)
(buffer-disable-undo))
(buffer-disable-undo)
(setq-local imenu-create-index-function
#'racket--describe-imenu-create-index)
(when (boundp 'imenu-auto-rescan)
(setq-local imenu-auto-rescan t)))

;;; Search and disambiguation using local docs

Expand Down
39 changes: 18 additions & 21 deletions racket-scribble.el
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,24 @@

;; SPDX-License-Identifier: GPL-3.0-or-later

(require 'dom)
(require 'seq)
(require 'shr)
(require 'subr-x)
(require 'url-util)
(require 'tramp)

(unless (fboundp 'dom-remove-node) ;added circa Emacs 27
(defun dom-remove-node (dom node)
"Remove NODE from DOM."
;; If we're removing the top level node, just return nil.
(dolist (child (dom-children dom))
(cond
((eq node child)
(delq node dom))
((not (stringp child))
(dom-remove-node child node))))))

(defconst racket--scribble-temp-nbsp #x2020
"Character we substitute for #xA0 non-breaking-space.
Expand All @@ -38,7 +50,7 @@ the effect of being non-breaking.")
(let* ((tramp-verbose 2) ;avoid excessive messages
(base (file-name-directory path))
(dom (racket--html-file->dom path))
(body (racket--scribble-body dom))
(body (dom-child-by-tag dom 'body))
(body (racket--massage-scribble-dom path base body)))
`(html ()
(head () (base ((href . ,base))))
Expand All @@ -49,26 +61,6 @@ the effect of being non-breaking.")
(insert-file-contents-literally path)
(libxml-parse-html-region (point-min) (point-max))))

(defun racket--scribble-body (dom)
"Return a body with the interesting elements in DOM.
With a normal Racket documentation page produced by Scribble,
these are only elements from the maincolumn/main div -- not the
tocset sibling.
With other doc pages, e.g. from r5rs, these are simply all the
body elements."
(pcase (seq-some (lambda (v)
(pcase v (`(body . ,_) v)))
dom)
(`(body ,_
(div ((class . "tocset")) . ,_)
(div ((class . "maincolumn"))
(div ((class . "main")) . ,xs))
. ,_)
`(body () ,@xs))
(body body)))

;; Dynamically bound (like Racket parameters).
(defvar racket--scribble-file nil)
(defvar racket--scribble-base nil)
Expand Down Expand Up @@ -251,6 +243,11 @@ In some cases we resort to returning custom elements for
(`(span ((style . "font-style: italic")) . ,xs)
`(i () ,@(mapcar #'racket--walk-dom xs)))

;; <span class="mywbr"> </span> added in e.g. "tocsub" for
;; "case/equal". As render in shr, undesired space.
(`(span ((class . "mywbr")) ,_)
"")

;; Delete some things that produce unwanted blank lines and/or
;; indents.
(`(blockquote ((class . ,(or "SVInsetFlow" "SubFlow"))) . ,xs)
Expand Down

0 comments on commit 27fda40

Please sign in to comment.