emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/geiser-stklos 5ab06e9 11/30: Add autodoc and symbol docume


From: Philip Kaludercic
Subject: [nongnu] elpa/geiser-stklos 5ab06e9 11/30: Add autodoc and symbol documentation support
Date: Sun, 1 Aug 2021 18:32:41 -0400 (EDT)

branch: elpa/geiser-stklos
commit 5ab06e9a6b43a67b5885c91f6c2660984743680a
Author: Jeronimo Pellegrini <j_p@aleph0.info>
Commit: Jeronimo Pellegrini <j_p@aleph0.info>

    Add autodoc and symbol documentation support
    
    And some tests!
---
 geiser-stklos-test.stk |  52 +++++++++++++++++
 geiser-stklos.el       |   2 +-
 geiser.stk             | 149 +++++++++++++++++++++++++++++++++++++++++++------
 3 files changed, 186 insertions(+), 17 deletions(-)

diff --git a/geiser-stklos-test.stk b/geiser-stklos-test.stk
index c8c16a4..e66062c 100644
--- a/geiser-stklos-test.stk
+++ b/geiser-stklos-test.stk
@@ -1,6 +1,7 @@
 
 (load "./test.stk")
 (load "./geiser.stk")
+(import GEISER)
 
 (test-init "TEST.LOG")
 
@@ -88,6 +89,57 @@
       (values)
       (geiser:no-values))
 
+
+((in-module STKLOS-COMPILER compiler:generate-signature) #t)
+
+(define (f a b . c) "doc for f" a)
+
+(test "geiser:symbol-documentation"
+      '(("signature" f ("args" (("required" a b)
+                                ("optional" "...")
+                                ("key"))))
+        ("docstring" . "A procedure in module stklos.\ndoc for f"))
+      (geiser:symbol-documentation 'f))
+
+
+
+(test-subsection "internal procedures")
+
+(select-module GEISER)
+
+(test "bound? no"
+      #f
+      (bound? (gensym) (current-module)))
+
+(define a -1)
+(test "bound? yes"
+      #t
+      (bound? 'a (current-module)))
+
+(define x (list-copy '(a b . c)))
+(define y (list-copy '(a b c)))
+(test "nullify-last-cdr! improper"
+      '(a b)
+      (begin
+       (nullify-last-cdr! x)
+       x))
+
+(test "nullify-last-cdr! improper"
+      '(a b c)
+      (begin
+       (nullify-last-cdr! y)
+       y))
+
+(define (f a b . c) "doc for f" a)
+(test "geiser:procedure-signature"
+      '(f ("args" (("required" a b)
+                   ("optional" "...")
+                   ("key")))
+          ("module" stklos))
+      ((in-module GEISER geiser:procedure-signature) 'f 'stklos))
+
+(select-module stklos)
+
 (test-section-end)
 
 (test-end)
diff --git a/geiser-stklos.el b/geiser-stklos.el
index 5d62080..959d49f 100644
--- a/geiser-stklos.el
+++ b/geiser-stklos.el
@@ -300,7 +300,7 @@ This function uses `geiser-stklos-init-file' if it exists."
   (check-buffer           geiser-stklos--guess)
   (keywords               geiser-stklos--keywords)       ; ok
   (case-sensitive         geiser-stklos-case-sensitive)  ; ok
-  (unsupported            '(autodoc callers callees))    ; doesn't seem to 
make any difference?
+  (unsupported            '(callers callees))            ; doesn't seem to 
make any difference?
   )
 
 ;; STklos files are .stk, and we may wat to open .scm files with STklos also:
diff --git a/geiser.stk b/geiser.stk
index 9746388..f1ec616 100644
--- a/geiser.stk
+++ b/geiser.stk
@@ -78,12 +78,14 @@
     
     (newline)))
 
-;; to log forms, use the following:
+;; to log forms, uncomment the following line and the
+;; lines that were commented out in the write-to-log
+;; procedure below:
 ;; (define log (open-output-file "geiser-log.txt"))
 
 (define (write-to-log form)
 ;;  (write form log)
-;;  (newline log))
+;;  (newline log)
   (values))
 
 ;; evaluates form inside a module.
@@ -217,21 +219,136 @@
         (else '())))
 
 
-;; returns the documentation for a symbol
-(define (geiser:symbol-documentation name)
-  (with-output-to-string
-    (lambda () (help (eval (eval name))))))
-
-;; used for autodoc. returns the documentation for a symbol.
+;; formats the signature of a procedure in the format required by Geiser.
+;;
+;; (define (f a b . c) a)
+;; (geiser:procedure-signature 'f 'stklos)
+;; =>  (f ("args" (("required" a b)
+;;                 ("optional" "...")
+;;                 ("key")))
+;;        ("module" stklos))
+;; 
+(define (geiser:procedure-signature name mod-name)
+  (let ((sig (list-copy (%procedure-signature (eval name (find-module 
mod-name))))))
+    (if sig
+        (let ((proper (list? sig)))
+          (let ((optional-args (if proper '() '("..."))))
+            (when (not proper) (nullify-last-cdr! sig))
+            `(,name  ("args" (("required" ,@sig)
+                              ("optional" ,@optional-args)
+                              ("key")))
+                     ("module" ,mod-name))))
+        ""))) ;; if there's no signature, don't show anything
+
+
+;; returns the documentation for a symbol, which includes
+;; the docstring for a procedure, and the value for variables.
+;;
+;; (define (f a b . c) "the documentation for f..." a)
+;; (geiser:symbol-documentation 'f 'stklos)
+;; => (("signature" f ("args" (("required" a b)
+;;                             ("optional" "...")
+;;                             ("key"))))
+;;     ("docstring" . "A procedure in module GEISER.\nthe documentation for 
f..."))
+;;
+;; (define x #(10 20 30))
+;; (geiser:symbol-documentation 'x 'stklos)
+;; => (("signature" x ("args"))
+;;     ("docstring" . "An object in module GEISER.\n\nValue:\n #(10 20 30)"))
+;;
+(define (geiser:symbol-documentation name . rest)
+  (let ((mod-name (if (null? rest)
+                      (module-name (current-module))
+                      (car rest))))
+    (cond ((procedure? (eval name (find-module mod-name)))
+           (let ((sig (geiser:procedure-signature name mod-name))
+                 (doc (%procedure-doc (eval name (find-module mod-name)))))
+             (let ((res
+             `(("signature" ,name ,(assoc "args" (cdr sig)))
+               ("docstring" . ,(string-append "A procedure in module "
+                                              (symbol->string mod-name) ".\n"
+                                              (if doc doc ""))))))
+               (write-to-log res)
+               res)))
+          ((bound? name mod-name) ; variable
+           `(("signature" ,name ("args"))
+             ("docstring" . ,(string-append "An object in module "
+                                            (symbol->string mod-name)
+                                             ".\n\nValue:\n "
+                                             (with-output-to-string
+                                               (lambda () (eval `(write ,name)
+                                                           (find-module 
mod-name))))))))
+          (else ""))))
+
+;; predicate - returns #t if id is bound in module.
+(define (bound? id module)
+  (cond ((string? module)
+         (bound? id (find-module (string->symbol module))))
+        ((symbol? module)
+         (let ((flag (gensym "it-is-unbound")))
+           (not (eq? (symbol-value id (find-module module) flag)
+                     flag))))
+        ((module? module)
+         (bound? id (module-name module)))
+        (else #f))) ;; really?
+
+
+;; nullify-last-cdr! turns improper lists into proper lists by removing
+;; the last element and putting '() in its place.
+;;
+;; *** The lists MUST BE MUTABLE! (hence the user of
+;;     "list-copy" in the examples below ***
+;;
+;; (define a (list-copy '(1 2 . 3)))
+;; (define b (list-copy '(1 2 3)))
+;; (nullify-last-cdr! a)
+;; (nullify-last-cdr! b)
+;; a => (1 2)
+;; b => (1 2 3)
+(define (nullify-last-cdr! lst)
+  (cond ((not (or (list? lst)
+                  (pair? lst)))
+         (error 'set-last-cdr! "Not a cons cell: ~S" lst))
+        ((pair? (cdr lst))
+         (nullify-last-cdr! (cdr lst)))
+        (else
+         (set-cdr! lst '()))))
+
+(define (geiser-build-autodoc name module)
+  (let ((mod-name (cond ((string? module) (string->symbol module))
+                        ((module? module) (module-name module))
+                        ((symbol? module) module))))
+    (cond ((not (bound? name mod-name))
+           "")
+          ((procedure? (eval name (find-module mod-name)))
+           (geiser:procedure-signature name mod-name))
+          (else ;; it's a variable?
+           `(,name  ("value" . ,(eval name (find-module mod-name)))
+                    ("module" ,mod-name))))))
+
+;; autodoc receives a list of names, and possibly a module name.
+;; it returns a list of documentations for each name:
+;;
+;; (define (f a c) a)
+;; (define (g a b :optional (c 1))
+;; (define a #(1 2 3))
+;;
+;; (geiser:autodoc '(f g a))
+;;  =>
+;; ((f ("args" (("required" a c)     ("optional")       ("key"))) ("module" 
stklos))
+;;  (g ("args" (("required" . #void) ("optional" "...") ("key"))) ("module" 
stklos))
+;;  (a ("value" . #(1 2 3)) ("module" stklos)))
+;;
 (define (geiser:autodoc names . rest)
-  #f)
-;;  (cond ((null? names) '())
-;;        ((not (list? names))
-;;         (geiser:autodoc (list names)))
-;;        ((symbol? (car names))
-;;         (with-output-to-string
-;;           (lambda () (help (car names)))))
-;;        (else "")))
+  (cond ((null? names) '())
+        ((symbol? names)
+         (geiser:autodoc (list names)))
+        ((list? names)
+         (let ((module (if (null? rest)
+                           (current-module)
+                           (car rest))))
+           (map (lambda (n) (geiser-build-autodoc n module)) names)))
+        (else "")))
 
 ;; The no-values identity
 (define (geiser:no-values)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]