Add documentation and generator. 0.1
authorFrank Duncan <frank@kank.net>
Thu, 13 Aug 2015 10:06:41 +0000 (05:06 -0500)
committerFrank Duncan <frank@kank.net>
Thu, 13 Aug 2015 11:41:25 +0000 (06:41 -0500)
README.md
bin/generatedocs.sh [new file with mode: 0755]
bin/travis.lisp
resources/success1.lisp
resources/success1.md
src/main/docgen.lisp
src/main/func.lisp
src/main/package.lisp
src/main/struc.lisp
src/test/main.lisp
wiki

index c059be9e2b54a1ba891c95a59475855899a86a93..3d8714a02b839d29ea44e9f1a01de76502703095 100644 (file)
--- a/README.md
+++ b/README.md
@@ -1,3 +1,72 @@
 # Common Lisp Document Generator
 
-Enforcement of documentation guidelines for my Common Lisp Projects, as well as conversion to markdown for github repositories.
+Enforcement of documentation guidelines for my Common Lisp Projects, as well as conversion to markdown for my github repositories.
+
+I wish I had aspirations for this being some standard that someone else might follow, but realistically I'm just irritated at my own laziness with regard to documentation, so I wrote a solution.  The forceful nature of the validator is really just because I didn't want to write a smarter parser.  As an added bonus, all the docs now look the same when I look at them in the repl, so that's kind of nice.
+
+## Usage
+
+See the [wiki](https://github.com/frankduncan/docgen/wiki) for usage information (generated by this package).
+
+To see how that page was created, take a look at bin/generatedocs.sh
+
+## Package documentation
+
+Packages are documented by sections broken up by one empty line, with the first section limited to 120 characters.
+
+## Structure/Condition documentation
+
+Requirements are the same as the package
+
+## Function documentation
+
+Functions should follow the template:
+
+````
+FUNC PATH => RESULT
+
+  RESULT: SUCCESS-RESULTS | FAILURE-RESULT
+  SUCCESS-RESULTS: SUCCESS-RESULT*
+  SUCCESS-RESULT: (:success FILENAME)
+  FAILURE-RESULT: (:failure FILENAME MSG)
+
+ARGUMENTS AND VALUES:
+
+  PATH: a pathname
+  FILENAME: the file this func was run on
+  MSG: a string containing the failure message
+
+DESCRIPTION:
+
+  FUNC runs all the things against a file located at PATH and returns
+  as soon as the first func error is found.
+
+EXAMPLES:
+
+  (func #P\"path/to/file.lisp\" t) => (:success \"path/to/file.lisp\")
+  (func #P\"path/to/error.lisp\" nil) => (:failure \"path/to/error.lisp\" \"Error msg\")
+````
+
+There are four sections to each function definition:
+
+### Header section
+
+Arguments should all be upper case, but &rest, &optional, and &key should be lower case.  Arguments are seperated by a space.
+
+Results should also be upper case, and in the case of values, separated by commas.
+
+Types can be further elucidated by providing more information either as a list of options seperated by pipes, a tuple contained in parens, or a list denoted by an *
+
+### Arguments and values section:
+
+All the types that weren't broken down into subtypes must be explained.  The form is type name in all upper case, a colon, then a description.  That description can have upper case type names in it which will then get italicized later.
+
+### Description
+
+Descriptins should be indented two spaces, and not longer than 120 characters wide.  Like the arguments and values, upper cased types will be italicized later.
+
+### Examples
+
+This section is optional.
+
+Examples are of the form:  example-code => example result
diff --git a/bin/generatedocs.sh b/bin/generatedocs.sh
new file mode 100755 (executable)
index 0000000..69ceeff
--- /dev/null
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+sbcl \
+  --eval "(asdf:load-system :docgen)" \
+  --eval "(format t \"----~%\")" \
+  --eval "(format t \"~A\" (docgen:export-package :docgen))" \
+  --eval "(quit)" 2> /dev/null | sed -n '/^----$/,$p' | tail -n +2 > wiki/Home.md
index 6a3ed0f3c313805e9d084a9d595b6a8ebf9f5097..608bdca649fd31f32296d981b391d7dbd279ff30 100644 (file)
 (when (not (syntax-checker:pretty-print-check-directory "src"))
  (format t "~c[1;31mFailed style check!~c[0m~%" #\Esc #\Esc)
  (sb-ext:exit :code 1))
+(format t "~c[1;32m- Style Passed!~c[0m~%" #\Esc #\Esc)
 
-(format t "~c[1;32mSuccess!~c[0m~%" #\Esc #\Esc)
+(format t "~%~c[1;33mChecking Docs~c[0m~%" #\Esc #\Esc)
+(when (not (docgen:pretty-print-validate-packages :docgen))
+ (format t "~c[1;31mFailed doc check!~c[0m~%" #\Esc #\Esc)
+ (sb-ext:exit :code 1))
+(format t "~c[1;32m- Doc Check Passed!~c[0m~%" #\Esc #\Esc)
+
+(format t "~c[1;30m--------------~c[0m~%" #\Esc #\Esc)
+(format t "~c[1;32mBuild Success!~c[0m~%" #\Esc #\Esc)
 (sb-ext:exit :code 0)
index 338b5b63afe3f13d72291159ef76b4a480749bcb..716dda6e8429c872f37aca487185fc3537b5a433 100644 (file)
@@ -58,7 +58,7 @@ ARGUMENTS AND VALUES:
 
 DESCRIPTION:
 
-  NOARGS runs all the things against a file and returns
+  RESULT-LIST runs all the things against a file and returns
   as soon as the first func error is found."
   nil)
 
index c3a91d1b82072f2ee7488d8dfbece2653a74ecb1..f0bf81d29f40ac795351dba5c0d97445644a0639 100644 (file)
@@ -4,6 +4,18 @@ This defines a simple successful package.
 
 This is should all get pulled in and the markdown.md should be equal to success1.md.
 
+## Contents
+
+* **function [func-that-does-stuff](#function-func-that-does-stuff)** - _func-that-does-stuff_ runs all the things against a file and returns as soon as the first func error is found.
+* **function [has-keywords](#function-has-keywords)** - _has-keywords_ runs all the things against a file and returns as soon as the first func error is found.
+* **function [has-no-examples](#function-has-no-examples)** - _has-no-examples_ runs all the things against a file and returns as soon as the first func error is found.
+* **function [has-optional](#function-has-optional)** - _has-optional_ runs all the things against a file and returns as soon as the first func error is found.
+* **function [has-rest](#function-has-rest)** - _has-rest_ runs all the things against a file and returns as soon as the first func error is found.
+* **function [noargs](#function-noargs)** - _noargs_ runs all the things against a file and returns as soon as the first func error is found.
+* **function [result-list](#function-result-list)** - _result-list_ runs all the things against a file and returns as soon as the first func error is found.
+* **condition [test-condition](#condition-test-condition)** - Simple documentation.
+* **function [values-result](#function-values-result)** - _values-result_ runs all the things against a file and returns as soon as the first func error is found.
+
 ## Function **FUNC-THAT-DOES-STUFF**
 
 #### Syntax:
@@ -160,7 +172,7 @@ _msg_---a string containing the failure message
 
 #### Description:
 
-NOARGS runs all the things against a file and returns as soon as the first func error is found.
+_result-list_ runs all the things against a file and returns as soon as the first func error is found.
 
 ## Condition TEST-CONDITION
 
index b3d251e907e0b1c30867bc6dd1f53a878eaa86d9..655b6bd9a2332a6f5a04f0f47cc56baf2ca4c2e3 100644 (file)
@@ -1,6 +1,7 @@
 (in-package #:docgen)
 
-(define-condition validation-failure nil ((msg :initarg :msg :reader validation-failure-msg)))
+(define-condition validation-failure nil ((msg :initarg :msg :reader validation-failure-msg))
+ (:documentation "Used internally for docgen parts to signal a validation error."))
 
 (defun get-symb-type (symb)
  (cond
   ((documentation symb 'function) :function)))
 
 (defun validate-package (pkg)
+ "VALIDATE-PACKAGE PKG => FAILURES
+
+  FAILURES: FAILURE*
+  FAILURE: (:failure SYMB MSG)
+
+ARGUMENTS AND VALUES:
+
+  PKG: A package symbol
+  SYMB: Symbol the check failed on
+  MSG: Message containing information about the failure
+
+DESCRIPTION:
+
+  VALIDATE-PACKAGE takes in PKG and validates that all the external symbols
+  adhere to documentation guidelines, exist, and can be parsed to be used
+  for exporting.
+
+  Only one error per symbol will be reported at a time, all concatenated to
+  a list in the aforementioned form."
  (macrolet
-  ((with-success-check (&rest f)
+  ((with-success-check (symb &rest f)
     `(handler-case
       (progn ,@f :success)
-      (validation-failure (v) (list :failure (validation-failure-msg v))))))
+      (validation-failure (v) (list :failure ,symb (validation-failure-msg v))))))
   (let
    ((symbs nil))
    (do-external-symbols (symb pkg) (push symb symbs))
    (setf symbs (sort symbs #'string< :key #'symbol-name))
    (remove :success
     (append
-     (list (with-success-check (docgen-pkg:doc->ast (find-package pkg))))
+     (list (with-success-check pkg (docgen-pkg:doc->ast (find-package pkg))))
      (mapcar
       (lambda (symb)
-       (with-success-check
+       (with-success-check symb
         (case (get-symb-type symb)
          (:function (docgen-func:doc->ast symb))
          (:structure (docgen-struc:doc->ast symb))
       symbs))))))
 
 (defun pretty-print-validate-packages (&rest pkgs)
- (mapcar
-  (lambda (pkg)
-   (let
-    ((failures (validate-package pkg)))
-    (mapcar
-     (lambda (failure)
-      (format t "In package ~A, documentation error found:~%  ~A" pkg (cadr failure)))
-     failures)
-    (not failures)))
-  pkgs))
+ "PRETTY-PRINT-VALIDATE-PACKAGES &rest PKGS => SUCCESS
+
+  PKGS: PKG*
+
+ARGUMENTS AND VALUES:
+
+  SUCCESS: Whether or not all symbols passed validation
+  PKG: A package symbol
+
+DESCRIPTION:
+
+  PRETTY-PRINT-VALIDATE-PACKAGES takes PKGS and runs validation on all of them.
+  It dumps to standard out failures as it comes upon them, finally returning
+  whether it was successful or not.
+
+  This can be used in travis tests to ensure that documentation can be generated
+  at a later date.
+
+EXAMPLES:
+
+  (pretty-print-validate-packages :pkg1 :pkg2) => t"
+ (some
+  #'identity
+  (mapcar
+   (lambda (pkg)
+    (let
+     ((failures (validate-package pkg)))
+     (mapcar
+      (lambda (failure)
+       (format t "In ~A : ~A, documentation error found:~%  ~A~%" pkg (second failure) (third failure)))
+      failures)
+     (not failures)))
+   pkgs)))
+
+(defun table-of-contents (pkg)
+ (format nil "## Contents~%~%~{~{* **~A [~A](#~A)** - ~A~}~%~}"
+  (let
+   ((symbs nil))
+   (do-external-symbols (symb pkg) (push symb symbs))
+   (setf symbs (sort symbs #'string< :key #'symbol-name))
+   (mapcar
+    (lambda (symb)
+     (case (get-symb-type symb)
+      (:function
+       (list
+        (docgen-func:ast->category-name (docgen-func:doc->ast symb))
+        (docgen-func:ast->short-name (docgen-func:doc->ast symb))
+        (docgen-func:ast->link (docgen-func:doc->ast symb))
+        (docgen-func:ast->short-desc (docgen-func:doc->ast symb))))
+      (:structure
+       (list
+        (docgen-struc:ast->category-name (docgen-struc:doc->ast symb))
+        (docgen-struc:ast->short-name (docgen-struc:doc->ast symb))
+        (docgen-struc:ast->link (docgen-struc:doc->ast symb))
+        (docgen-struc:ast->short-desc (docgen-struc:doc->ast symb))))))
+    symbs))))
 
 (defun export-package (pkg)
+ "EXPORT-PACKAGE PKG => MARKDOWN
+
+ARGUMENTS AND VALUES:
+
+  PKG: A package symbol
+  MARKDOWN: A string containing the markdown representation of this packages documentation
+
+DESCRIPTION:
+
+  EXPORT-PACKAGE takes in PKG and converts all the documentation for the symbols
+  into markdown with the hope of emulating the hyperspec style.
+
+  It should only be run after the package has been validated, as it assumes that
+  all documentation it gets will be valid."
  (let
   ((symbs nil))
   (do-external-symbols (symb pkg) (push symb symbs))
   (setf symbs (sort symbs #'string< :key #'symbol-name))
   (with-output-to-string (str)
    (format str "~A~%~%" (docgen-pkg:ast->md (docgen-pkg:doc->ast (find-package pkg))))
+   (format str "~A~%" (table-of-contents pkg))
    (format str "~{~A~^~%~}"
     (mapcar
      (lambda (symb)
-      (format t "HAHAHAH ~A ~A~%" symb (get-symb-type symb))
       (case (get-symb-type symb)
        (:function (docgen-func:ast->md (docgen-func:doc->ast symb)))
        (:structure (docgen-struc:ast->md (docgen-struc:doc->ast symb)))))
index d3540a6a7f97f4b712cd1a218bc720bc6afa6513..b3926a12be7156be199689ff4c4dad9cbe969313 100644 (file)
    (format-args-and-values (get-section :arguments-and-values))
    (format-description (get-section :description))
    (format-examples (get-section :examples)))))
+
+(defun ast->category-name (ast)
+ (declare (ignore ast))
+ "function")
+
+(defun ast->short-name (ast)
+ (format nil "~(~A~)" (second (find :function ast :key #'car))))
+
+(defun ast->link (ast)
+ (format nil "function-~(~A~)" (second (find :function ast :key #'car))))
+
+(defun ast->short-desc (ast)
+ (format-text (car (cadr (find :description ast :key #'car)))))
index 00c3bb7faf1c23398001c795653870a98091018a..119922bc26a4f5849963add7f22d077b71fdd746 100644 (file)
@@ -1,11 +1,16 @@
 (defpackage #:docgen (:use :cl)
- (:export #:validate-package #:export-package #:validation-failure #:pretty-print-validate-packages))
+ (:export #:validate-package #:export-package #:validation-failure #:pretty-print-validate-packages)
+ (:documentation "Main docgen package.
+
+Use docgen to validate that documentation strings on external symbols adhere to
+a strict format and exist, so that they can be output to markdown format, while
+looking decent when used within a common lisp process."))
 
 (defpackage #:docgen-func (:use :cl)
- (:export #:doc->ast #:ast->md))
+ (:export #:doc->ast #:ast->md #:ast->link #:ast->short-name #:ast->short-desc #:ast->category-name))
 
 (defpackage #:docgen-pkg (:use :cl)
  (:export #:doc->ast #:ast->md))
 
 (defpackage #:docgen-struc (:use :cl)
- (:export #:doc->ast #:ast->md))
+ (:export #:doc->ast #:ast->md #:ast->link #:ast->short-name #:ast->short-desc #:ast->category-name))
index a616ee97cbff9fd7f63118cbf8cc9c8d693e0556..6a792ed470608e2c9a1c80a258b3ab1d5c1e0e7b 100644 (file)
   (first ast)
   (second ast)
   (cddr ast)))
+
+(defun ast->category-name (ast)
+ (case (first ast)
+  (:condition "condition")
+  (t "structure")))
+
+(defun ast->short-name (ast)
+ (format nil "~(~A~)" (second ast)))
+
+(defun ast->link (ast)
+ (format nil "~(~A-~A~)" (first ast) (second ast)))
+
+(defun ast->short-desc (ast)
+ (third ast))
index a73dd7bac468278c8ede478c842736f19bdc24a6..572636ef8441419a4781a0698a7c53ca35609e8b 100644 (file)
@@ -70,6 +70,6 @@
 
 (defsuccesstest :success1 "resources/success1.lisp" "resources/success1.md")
 (deffailuretest :emptydocs "resources/emptydocs.lisp"
'((:failure "Package EMPTYDOCS has no documentation")
-   (:failure "Symbol NO-DOC-CONDITION has no documentation")
-   (:failure "Symbol NO-DOC-FUNC has no documentation")))
`((:failure :emptydocs "Package EMPTYDOCS has no documentation")
+   (:failure ,(intern "NO-DOC-CONDITION" :emptydocs) "Symbol NO-DOC-CONDITION has no documentation")
+   (:failure ,(intern "NO-DOC-FUNC" :emptydocs) "Symbol NO-DOC-FUNC has no documentation")))
diff --git a/wiki b/wiki
index 1a8916ff9faac67cbb461da9cc939d8bee63bf25..06c150fca744ae5052741ca676e09d7081d0eefe 160000 (submodule)
--- a/wiki
+++ b/wiki
@@ -1 +1 @@
-Subproject commit 1a8916ff9faac67cbb461da9cc939d8bee63bf25
+Subproject commit 06c150fca744ae5052741ca676e09d7081d0eefe