deduplicate, reorganize some utility functions, inline docs

This commit is contained in:
pho4cexa 2022-12-10 13:33:38 -08:00 committed by m455
parent 75b7406508
commit ab241899d4

110
main.scm
View file

@ -19,22 +19,60 @@
(define DESCRIPTION (or (get-environment-variable "REPO2HTML_DESCRIPTION") "my git repositories")) (define DESCRIPTION (or (get-environment-variable "REPO2HTML_DESCRIPTION") "my git repositories"))
(define H1 (or (get-environment-variable "REPO2HTML_H1") "git.example.com")) (define H1 (or (get-environment-variable "REPO2HTML_H1") "git.example.com"))
(define (populate-html-template repository-name source-files-list source-file display-body-thunk) ;; small utilities ---------------------------------
(define-values (source-directory source-filename source-extension)
(decompose-pathname source-file)) ;; return the first x in xs for which (pred? member) is true,
(define-values (base-origin base-directory directory-elements) ;; or #f if no such member is found.
(if source-directory (define (first-if pred? xs)
(decompose-directory source-directory) (cond ((null? xs) #f)
(values #f #f '()))) ((pred? (car xs)) (car xs))
(define relative-root (else (first-if pred? (cdr xs)))))
;; (bail [message [exit-status]])
;; end the program immediately.
;; if a message is provided, print it to the screen.
;; exit-status defaults to 1.
(define (bail . args)
(let-optionals args ((msg "") (status 1))
(unless (equal? "" msg) (print msg))
(exit status)))
;; decompose a path s into its constituent parts. returns values:
;;
;; root: "/" if it's an absolute path, "" if relative
;; directory-elements: a list of each directory from root, () if none
;; basename: the filename with extension removed like "readme" or ".bashrc"
;; extension: the file extension with the dot, like ".txt" or "" if none
;; relative-root: the relative path from the given path to the root
;; e.g foo/bar/baz.html -> ../../
;;
;; this is intended to provide default values that make for easier reassembly
;; into filenames.
;;
;; typical use:
;; (->> source-file
;; (pathparts)
;; (define-values (root elements basename extension relative-root)))
;;
(define (pathparts s)
(define-values (dirname basename extension)
(decompose-pathname s))
(define-values (origin root directory-elements)
(decompose-directory (or dirname "")))
;; discarding origin because idgaf about windows
(values (or root "")
(or directory-elements '())
basename
(if extension (string-append "." extension) "")
(->> (->>
directory-elements (or directory-elements '())
(map (lambda (_) "../")) (map (constantly "../"))
;; why is there no inverse function for decompose-directory in pathname? (apply string-append))))
;; idgas about portability but a portable program would refer to the
;; current platform's directory-separator here. ;; main code ---------------------------------
(apply string-append)
)) (define (populate-html-template repository-name source-files-list source-file display-body-thunk)
(define-values (_ _ _ _ relative-root) (pathparts source-file))
(display #<#string-block (display #<#string-block
<!DOCTYPE html> <!DOCTYPE html>
@ -107,7 +145,7 @@ string-block
(define (in-git-directory?) (define (in-git-directory?)
(not (eof-object? (call-with-input-pipe "git rev-parse --git-dir" read-line)))) (not (eof-object? (call-with-input-pipe "git rev-parse --git-dir" read-line))))
(define (is-text? path) (define (git-file-is-text? path)
(not (equal? (not (equal?
"-\t-\t" "-\t-\t"
(call-with-input-pipe (call-with-input-pipe
@ -124,15 +162,9 @@ string-block
(string-intersperse "\n"))) (string-intersperse "\n")))
(define (display-source-html source-file) ;; src/main.scm (define (display-source-html source-file) ;; src/main.scm
(define-values (source-directory source-filename source-extension) (define-values (_ _ basename extension _) (pathparts source-file))
(decompose-pathname source-file))
(define-values (base-origin base-directory directory-elements)
(if source-directory
(decompose-directory source-directory)
(values #f #f '())))
(define (image-link) (define (image-link)
(format #t "<p><img src=\"~a\" /></p>" (make-pathname "" source-filename source-extension))) (format #t "<p><img src=\"~a~a\" /></p>" basename extension))
(define (plaintext) (define (plaintext)
(display "<pre>") (display "<pre>")
(display-escaped-html (git-file->string source-file)) (display-escaped-html (git-file->string source-file))
@ -140,10 +172,8 @@ string-block
(define (binary) (define (binary)
(display "<p>(Binary file)</p>")) (display "<p>(Binary file)</p>"))
(format #t "<p id=\"file-path\">~a</p>" source-file) (format #t "<p id=\"file-path\">~a</p>" source-file)
(case (string->symbol (or source-extension source-filename)) (case (string->symbol extension)
;; markdown files get rendered in-place, unless there's an error, in which ((.md .markdown)
;; case escaped plaintext inside a <pre>
((md markdown)
(handle-exceptions exn (handle-exceptions exn
(begin (begin
(display "Error parsing " (current-error-port)) (display "Error parsing " (current-error-port))
@ -152,14 +182,14 @@ string-block
(display "<p><b>There was an error parsing this file as Markdown.</b></p>") (display "<p><b>There was an error parsing this file as Markdown.</b></p>")
(plaintext)) (plaintext))
(markdown->html (git-file->string source-file)))) (markdown->html (git-file->string source-file))))
((jpg jpeg png gif webp webm apng avif svgz ico) ((.jpg .jpeg .png .gif .webp .webm .apng .avif .svgz .ico)
(image-link)) (image-link))
((svg) ((.svg)
(image-link) (plaintext)) (image-link) (plaintext))
((gz pack idx) ((.gz .pack .idx)
(binary)) (binary))
(else (else
(if (is-text? source-file) (if (git-file-is-text? source-file)
(plaintext) (plaintext)
(binary))))) (binary)))))
@ -191,15 +221,10 @@ string-block
(tr (th "Author") (th "Commits")) (tr (th "Author") (th "Commits"))
,(map ,(map
(lambda (line) (lambda (line)
(let-values (((commits . author) (apply values (string-split line "\t")))) (let-values (((commits author) (apply values (string-split line "\t"))))
`(tr (td ,author) (td ,commits)))) `(tr (td ,author) (td ,commits))))
(call-with-input-pipe "git shortlog -ns HEAD" read-lines)))))) (call-with-input-pipe "git shortlog -ns HEAD" read-lines))))))
(define (first-if pred lst)
(cond ((null? lst) #f)
((pred (car lst)) (car lst))
(else (first-if pred (cdr lst)))))
(define (generate-html-files html-repo-path) (define (generate-html-files html-repo-path)
(let ((source-files-list (git-repository->paths-list)) (let ((source-files-list (git-repository->paths-list))
(repository-name (pathname-strip-directory (string-chomp html-repo-path "/")))) (repository-name (pathname-strip-directory (string-chomp html-repo-path "/"))))
@ -238,19 +263,14 @@ string-block
(make-pathname html-repo-path "index.html") (make-pathname html-repo-path "index.html")
#t))) #t)))
(define (bail . args)
(let-optionals args ((status 1) (msg ""))
(unless (equal? "" msg) (print msg))
(exit status)))
(define (main args) (define (main args)
(let-optionals args ((html-repo-path "")) (let-optionals args ((html-repo-path ""))
(when (equal? html-repo-path "") (when (equal? html-repo-path "")
(bail 1 "please specify a destination directory for html files")) (bail "please specify a destination directory for html files"))
(unless (in-git-directory?) (unless (in-git-directory?)
(bail 1 "woops this isn't a git directory")) (bail "woops this isn't a git directory"))
(generate-html-files html-repo-path))) (generate-html-files html-repo-path)))