AtlatestRepositorysigil-docs
sigil-docs / tree / src / sigil / docslookup.sgl
1
;;; (sigil docs lookup) - JSON-based Documentation Lookup2
;;;3
;;; Loads and queries documentation from JSON files generated during4
;;; compilation. JSON doc files are co-located with .sgb bytecode files5
;;; and are found using the same load path search as module loading.6
;;;7
;;; Example:8
;;; (load-module-details '(sigil string))9
;;; => <module-details> struct with exports list10
;;;11
;;; (get-export-details '(sigil string) 'string-split)12
;;; => <export-details> struct with name, kind, doc, signature14
(define-library (sigil docs lookup)15
(import (sigil string)16
(sigil path)17
(sigil fs)18
(sigil io)19
(sigil json)20
(sigil resources)21
(sigil docs types))22
(export23
;; Re-export types for convenience24
module-details25
module-details?26
module-details-name27
module-details-file28
module-details-package29
module-details-description30
module-details-exports31
module-details-syntaxes32
module-details-examples34
export-details35
export-details?36
export-details-name37
export-details-kind38
export-details-signature39
export-details-description40
export-details-examples41
export-details-source-module42
export-details-line44
syntax-details45
syntax-details?46
syntax-details-name47
syntax-details-patterns48
syntax-details-description49
syntax-details-examples51
;; Core lookup functions52
load-module-details53
get-export-details54
get-module-description56
;; Path utilities57
find-doc-file58
module-name->doc-path60
;; Cache management61
clear-doc-cache)63
(begin65
;; ============================================================66
;; Documentation Cache67
;; ============================================================69
;; Cache of loaded module details: module-name -> module-details struct70
(define *doc-cache* '())72
;;; Clear the documentation cache.73
;;;74
;;; Use this to force reloading of documentation files after75
;;; they have been regenerated.76
(define (clear-doc-cache)77
(set! *doc-cache* '()))79
;; Look up in cache80
(define (cache-lookup module-name)81
(let ((entry (assoc module-name *doc-cache*)))82
(if entry (cdr entry) #f)))84
;; Add to cache85
(define (cache-store module-name details)86
(set! *doc-cache* (cons (cons module-name details) *doc-cache*))87
details)89
;; ============================================================90
;; Path Resolution91
;; ============================================================93
;;; Convert a module name to its documentation file path (relative).94
;;;95
;;; The path matches the .sgb bytecode location but with .json extension.96
(define (module-name->doc-path module-name)97
(string-append98
(string-join (map symbol->string module-name) "/")99
".json"))101
;;; Check if documentation exists for a module.102
;;;103
;;; Uses the unified resource resolution (project -> bundle -> system).104
(define (find-doc-file module-name)105
(let ((relative-path (module-name->doc-path module-name)))106
(if (resource-exists? 'lib relative-path)107
relative-path108
#f)))110
;; ============================================================111
;; JSON to Struct Conversion112
;; ============================================================114
;; Convert JSON export dict to export-details struct115
;; Note: JSON parser creates keyword symbols (name:, kind:, etc.)116
(define (json->export-details json-export)117
(export-details118
name: (string->symbol (dict-ref json-export name: ""))119
kind: (let ((k (dict-ref json-export kind: "variable")))120
(string->symbol k))121
signature: (let ((sig (dict-ref json-export signature: #f)))122
(if (and sig (not (equal? sig 'null)))123
sig124
#f))125
description: (let ((doc (dict-ref json-export description: #f)))126
(if (and doc (not (equal? doc 'null)))127
doc128
#f))129
examples: '()130
source-module: (let ((src (dict-ref json-export source_module: #f)))131
(if (and src (not (equal? src 'null)))132
src133
#f))134
line: (let ((ln (dict-ref json-export line: 0)))135
(if (integer? ln) ln 0))))137
;; Convert JSON module dict to module-details struct138
(define (json->module-details json-doc module-name doc-path)139
(let* ((exports-array (dict-ref json-doc exports: #f))140
(exports (if exports-array141
(array->list exports-array)142
'()))143
;; Prefer the absolute source path emitted by the compiler144
;; (the "source" field); fall back to the doc path if missing.145
(source-file (let ((s (dict-ref json-doc source: #f)))146
(if (and s (string? s) (not (equal? s 'null)))147
s148
doc-path))))149
(module-details150
name: module-name151
file: source-file152
package: (let ((pkg (dict-ref json-doc package: #f)))153
(if (and pkg (not (equal? pkg 'null)))154
pkg155
#f))156
description: (let ((doc (dict-ref json-doc description: #f)))157
(if (and doc (not (equal? doc 'null)))158
doc159
#f))160
exports: (map json->export-details exports)161
syntaxes: '()162
examples: '())))164
;; ============================================================165
;; Loading Documentation166
;; ============================================================168
;;; Load documentation for a module from its JSON file.169
;;;170
;;; Returns a <module-details> struct, or #f if no documentation file171
;;; is found. The result is cached for subsequent lookups.172
(define (load-module-details module-name)173
;; Check cache first174
(let ((cached (cache-lookup module-name)))175
(if cached176
cached177
;; Not cached, try to load via resource resolution178
(let ((doc-path (module-name->doc-path module-name)))179
(let ((content (read-resource 'lib doc-path)))180
(if (not content)181
#f182
(let* ((json-doc (json-decode content))183
(details (json->module-details json-doc module-name doc-path)))184
(cache-store module-name details))))))))186
;; ============================================================187
;; Querying Documentation188
;; ============================================================190
;;; Get the module-level documentation string.191
;;;192
;;; Returns the module's docstring, or #f if not found.193
(define (get-module-description module-name)194
(let ((details (load-module-details module-name)))195
(if details196
(module-details-description details)197
#f)))199
;;; Get documentation for a specific export from a module.200
;;;201
;;; Returns an <export-details> struct, or #f if the module or export202
;;; is not found.203
(define (get-export-details module-name export-name)204
(let ((details (load-module-details module-name)))205
(if (not details)206
#f207
(let loop ((exports (module-details-exports details)))208
(cond209
((null? exports) #f)210
((eq? (export-details-name (car exports)) export-name)211
(car exports))212
(else (loop (cdr exports))))))))214
))