;;AUTOLOAD: doc-autoloadables
;;AUTODOC: doc-autoloadables "prints the complete documentation of autoloadabel functions"
;;(doc-autoloadables [:paged lines])
;;
;;lists on stdout the doc of all klone functions provided in the distribution
;;or locally via the transparent autoloading mecanism
;;If lines is not given, the docs are just printed on the stdout, if a page 
;;length in lines is given, it is formatted for prettier output for this page 
;;length
;;To print onto file Autodocs.txt for 66 lines pages, do:
;;(with (*standard-output* (open "Autodocs.txt" :direction :output 
;;      :if-exists :supersede)) (doc-autoloadables :paged 66))

(defun doc-autoloadables (&key paged &aux
    apropos-lines
    (fd (open (copy "") :type :string :direction :io))
    (re (regcomp "^([^ ]+) - "))
    (names (list))
    (descs (list))
    docs doc doclen line i
    (pos 0)
  )
  (if (not paged) (setq paged *maxint*))
  (with (*standard-output* fd)		;get all the autoloadable docs into fd
    (apropos "" :from code)
  )
  (file-position fd 0)			;rewind fd and get all function names
  (while (setq line (read-line fd ()))
    (if (regexec re line) (progn
	(lappend names (regsub re 1))
	(lappend descs line)
  )))
  (sort names compare-nocase)		;sorts names
  (sort descs compare-nocase)
  (dolist (desc descs)			;prints table of contents
    (write-line desc)
    (incf pos)
  )
  (setq pos (mod pos paged))
  (if (and (/= paged *maxint*) (/= 0 pos))
    (dotimes (i (- paged pos)) (write-line "")))
  (setq pos 0)
  (dolist (name names)			;prints all docs
    (setq docs (apply smartdoc:help (list name)))
    (if (setq doc (getn docs 0)) (progn	;print first entry
	(setq doclen (+ 4 (doc-autoloadables:count-lines doc)))
	(if (>= (+ doclen pos (if (= 0 pos) 0 1)) paged);goto next page
	  (progn (dotimes (i (- paged pos)) (write-line ""))
	    (setq pos 0)
	))
	(if (/= 0 pos) (progn (write-line "") (incf pos))) ;blank line
	(write-line (make-string 76 #\#))
	(print-format "#%1%0%2#\n" name
	  (make-string (setq i (/ (- 77 (+ 2 (length name))) 2)))
	  (make-string (- 76 (+ 2 (length name) i)))
	)
	(write-line (make-string 76 #\#))
	(write-line "")
	(? doc)
	(incf pos (+ 4 (doc-autoloadables:count-lines doc)))
	(setq pos (mod pos paged))
    ))
    (dolist (doc (subseq docs 1))	;print rest of entries
      (if (< (- paged pos) 4)	;goto next page if < 4 lines left
	(progn (dotimes (i (- paged pos)) (write-line ""))(setq pos 0))
      )
      (if (/= 0 pos) (write-line "") (incf pos -1))
      (print-format "%1  %0  %2\n" name
	(make-string (setq i (/ (- 77 (+ 4 (length name))) 2)) #\*)
	(make-string (- 76 (+ 4 (length name) i)) #\*)
      )
      (write-line "")
      (incf pos (+ 3 (doc-autoloadables:count-lines doc)))
      (? doc)
      (setq pos (mod pos paged))
  ))
  ()
)
    
(defun doc-autoloadables:count-lines (s &aux (n 0))
  (dolist (c s)
    (if (= #\newline c)
      (incf n)
  ))
  n
)
