;;; metaspec.el --- Info version of dpANS3R Common Lisp standard -*- lexical-binding: t; coding:utf-8 -*-

;; Author: Daniel Lowe <dlowe@dlowe.net>
;; URL: https://metaspec.dev/
;; Keywords: docs, languages, lisp
;; Package-Requires: ((emacs "25.1"))

;;; Commentary:

;; This package carries the Metaspec Info manual -- the Texinfo
;; rendering of the draft proposed ANSI Common Lisp standard.
;; `C-h S' on a symbol in a Lisp buffer will open that symbol's
;; dictionary entry, and `C-M-i' completes against the symbol index.

;;; Code:

(require 'info-look)
(require 'seq)
(require 'thingatpt)

(defconst metaspec-symbol-regexp "[^][()`',\" \t\n]+"
  "Regexp matching the possible characters in a Common Lisp symbol.")

(defconst metaspec-repl-modes '(sly-mrepl-mode slime-repl-mode)
  "Lisp REPL modes that search for symbols in the same manner
that `lisp-mode' does.")

(defun metaspec-symbol-at-point ()
  "The symbol at point with package qualifiers removed."
  (let ((symbol (thing-at-point 'symbol t)))
    (when symbol
      (replace-regexp-in-string "\\`\\(?:[^:]+::?\\)" "" symbol))))

(defun metaspec-forget-cached-lookups (modes)
  "Drop MODES from `info-lookup-cache'.
The cache holds the completion table built from a mode's doc-spec the
first time a symbol is looked up in it, and `info-lookup-add-help' does
not disturb it: replacing a spec in a session that has already looked
one up would otherwise keep answering out of the old manual until Emacs
is restarted."
  (dolist (topic info-lookup-cache)
    (setcdr topic (seq-remove (lambda (entry) (memq (car entry) modes))
                              (cdr topic)))))

;;;###autoload
(defun metaspec-setup-info-lookup ()
  "Configure `info-lookup-symbol' to find Common Lisp symbols in the
Metaspec.  Overrides the existing `lisp-mode' entry, which points at the
Emacs Lisp manuals by default."
  (info-lookup-add-help
   :mode 'lisp-mode
   :regexp metaspec-symbol-regexp
   :parse-rule #'metaspec-symbol-at-point
   :ignore-case t
   :doc-spec '(("(metaspec)Symbol Index" nil nil nil)
               ("(metaspec)Concept Index" nil nil nil)))
  (dolist (mode metaspec-repl-modes)
    (info-lookup-maybe-add-help :mode mode :other-modes '(lisp-mode)))
  (metaspec-forget-cached-lookups (cons 'lisp-mode metaspec-repl-modes)))

;;;###autoload
(with-eval-after-load 'info-look
  (metaspec-setup-info-lookup))

(provide 'metaspec)
;;; metaspec.el ends here
