aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile30
-rw-r--r--doc/forge.skb54
-rw-r--r--doc/skribilo.scm148
3 files changed, 230 insertions, 2 deletions
diff --git a/Makefile b/Makefile
index b4063c4..2fe0dd3 100644
--- a/Makefile
+++ b/Makefile
@@ -17,11 +17,37 @@
# along with guix-forge. If not, see <https://www.gnu.org/licenses/>.
EMACS = emacs
+GUILD = guild
+SKRIBILO = skribilo
-.PHONY: all
+sources = $(wildcard forge/*.scm) $(wildcard forge/*/*.scm)
+doc_skribilo_config = doc/skribilo.scm
+doc_skribilo_config_go = $(doc_skribilo_config:.scm=.go)
+doc_sources = doc/forge.skb
+doc_html = $(doc_sources:.skb=.html)
+
+.PHONY: all html clean
all: ;
-website: website/index.html
+%.go: %.scm
+ $(GUILD) compile -L . -o $@ $<
+
+html: $(doc_html)
+
+$(doc_html): $(doc_sources) $(sources) $(doc_skribilo_config_go)
+ rm -rf $@
+ mkdir -p $@
+ GUILE_LOAD_PATH=$(CURDIR):$(GUILE_LOAD_PATH) GUILE_LOAD_COMPILED_PATH=$(CURDIR):$(GUILE_LOAD_COMPILED_PATH) $(SKRIBILO) --target=html $< --output=$@/index.html
+
+website: website/index.html website/manual/dev/en
website/index.html: README.org build-aux/build-home-page.el
$(EMACS) -Q --batch --load build-aux/build-home-page.el --funcall build-website
+
+website/manual/dev/en: $(doc_html)
+ rm -rf $@
+ mkdir -p $(dir $@)
+ cp -vr $^ $@
+
+clean:
+ rm -f $(doc_skribilo_config_go)
diff --git a/doc/forge.skb b/doc/forge.skb
new file mode 100644
index 0000000..723d47f
--- /dev/null
+++ b/doc/forge.skb
@@ -0,0 +1,54 @@
+;;; guix-forge --- Guix software forge meta-service
+;;; Copyright © 2022 Arun Isaac <arunisaac@systemreboot.net>
+;;;
+;;; This file is part of guix-forge.
+;;;
+;;; guix-forge is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published
+;;; by the Free Software Foundation, either version 3 of the License,
+;;; or (at your option) any later version.
+;;;
+;;; guix-forge is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with guix-forge. If not, see
+;;; <https://www.gnu.org/licenses/>.
+
+(use-modules (doc skribilo))
+
+(document :title [guix-forge]
+ (chapter :title [Introduction]
+ (p [guix-forge is a Guix service that lets you run a complete
+,(ref :url "https://en.wikipedia.org/wiki/Forge_(software)"
+:text "software forge") in the manner of GitHub, GitLab, etc. Unlike
+other free software forges such as GitLab, Gitea, etc., guix-forge is
+not a monolith but is an assemblage of several pieces of server
+software wired up to function as one. In this sense, it is a
+,(emph "meta-service"). guix-forge does for software forges what ,(ref
+:url "https://mailinabox.email/" :text "Mail-in-a-Box") does for
+email.])
+ (p [guix-forge is provided on a best effort basis. Its
+design is unstable, and open to change. We will try our best to not
+break your system configuration often, but it might happen.])
+ (section :title [Philosophy]
+ (p [In order to empower ordinary users, software should not just
+be free (as in freedom), but also be simple and easy to deploy,
+especially for small-scale deployments. guix-forge is therefore
+minimalistic, and does not require running large database servers such
+as MariaDB and PostgreSQL.])
+ (p [While some state is inevitable, server software should
+strive to be as stateless as an old analog television set. You switch
+it on, and it works all the time. There are no pesky software updates,
+and complex hidden state. guix-forge tries to be as stateless as
+possible. Almost all of guix-forge's state can be version controlled,
+and the rest are simple files that can be backed up easily.])
+ (p [,(ref
+:url "https://drewdevault.com/2018/07/23/Git-is-already-distributed.html"
+:text "Git is already federated and decentralized") with
+email. guix-forge acknowledges this and prefers to support git's ,(ref
+:url "https://drewdevault.com/2018/07/02/Email-driven-git.html"
+:text "email driven workflow") with project discussion, bug reports
+and patches all happening over email.]))))
diff --git a/doc/skribilo.scm b/doc/skribilo.scm
new file mode 100644
index 0000000..d97f485
--- /dev/null
+++ b/doc/skribilo.scm
@@ -0,0 +1,148 @@
+;;; guix-forge --- Guix software forge meta-service
+;;; Copyright © 2022 Arun Isaac <arunisaac@systemreboot.net>
+;;;
+;;; This file is part of guix-forge.
+;;;
+;;; guix-forge is free software: you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published
+;;; by the Free Software Foundation, either version 3 of the License,
+;;; or (at your option) any later version.
+;;;
+;;; guix-forge is distributed in the hope that it will be useful, but
+;;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;;; General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with guix-forge. If not, see
+;;; <https://www.gnu.org/licenses/>.
+
+(define-module (doc skribilo)
+ #:use-module (rnrs conditions)
+ #:use-module (rnrs io ports)
+ #:use-module (srfi srfi-28)
+ #:use-module (ice-9 match)
+ #:use-module (ice-9 regex)
+ #:use-module (skribilo ast)
+ #:use-module (skribilo engine)
+ #:use-module (skribilo lib)
+ #:use-module (skribilo writer)
+ #:use-module (skribilo package base)
+ #:use-module (skribilo parameters)
+ #:use-module (skribilo source lisp)
+ #:use-module (skribilo utils keywords)
+ #:export (file
+ command
+ scheme-source
+ scheme-source-form
+ source-ref))
+
+;; Constants
+(define %source-uri-base
+ "https://git.systemreboot.net/guix-forge/tree/")
+
+;; Aliases
+(define file samp)
+(define command code)
+
+;; Abbreviations
+(define-markup (abbr #:rest opts
+ #:key (ident #f) (class "abbr") (short #f) (long #f))
+ (new container
+ (markup 'abbr)
+ (ident (or ident (symbol->string (gensym "abbr"))))
+ (class class)
+ (loc &invocation-location)
+ (required-options '(#:short #:long))
+ (options `((#:short ,short)
+ (#:long ,long)
+ ,@(the-options opts #:ident #:class #:short #:long)))
+ (body (the-body opts))))
+
+;; S-exp source links
+(define (source-uri file start-line end-line)
+ "Return a URI referring to source FILE from START-LINE to END-LINE."
+ (string-append %source-uri-base
+ file
+ "#n"
+ (number->string start-line)))
+
+(define (sexp-position str regexp)
+ "Return (START . END) where START is the start of the match to
+REGEXP in STR and END is the end of the sexp beginning at START. START
+and END are character positions indexed from 0. If multiple matches
+are found, error out."
+ (cond
+ ((string-match regexp str)
+ => (lambda (match-struct)
+ (let ((start (match:start match-struct)))
+ (if (string-match regexp (substring str (1+ start)))
+ (raise-exception (condition (make-message-condition
+ (format "source-ref: regexp ~s found on multiple lines"
+ regexp))
+ (make-irritants-condition regexp)))
+ (cons start
+ (1- (- (string-length str)
+ (string-length
+ (call-with-input-string (substring str start)
+ (lambda (port)
+ (read port)
+ (get-string-all port)))))))))))
+ (else
+ (raise-exception (condition (make-message-condition
+ (format "source-ref: regexp ~s not found" regexp))
+ (make-irritants-condition regexp))))))
+
+(define (position->line-number str position)
+ "Return the line number in STR corresponding to POSITION."
+ (string-fold (lambda (c result)
+ (if (char=? c #\newline)
+ (1+ result)
+ result))
+ 1
+ (substring str 0 position)))
+
+(define (sexp-file-lines file regexp)
+ "Return (START . END) where START is the start of the match to
+REGEXP in STR and END is the end of the sexp beginning at START. START
+and END are line numbers indexed from 1."
+ (let ((str (call-with-input-file file get-string-all)))
+ (match (sexp-position str regexp)
+ ((start . end)
+ (cons (position->line-number str start)
+ (position->line-number str end))))))
+
+(define (source-ref file regexp text)
+ "Link to S-expression in FILE whose beginning matches REGEXP. TEXT
+is the text of the link."
+ (ref #:url (match (sexp-file-lines (search-path (*source-path*) file)
+ regexp)
+ ((start-line . end-line)
+ (source-uri file start-line end-line)))
+ #:text text))
+
+;; Extract forms from scheme source
+(define (scheme-source-form file regexp)
+ "Extract form from scheme source FILE whose beginning matches
+REGEXP. Return it enclosed in a prog form."
+ (prog (match (sexp-file-lines (search-path (*source-path*) file)
+ regexp)
+ ((start . stop)
+ (source #:language scheme
+ #:file file
+ #:start (1- start)
+ #:stop (1- stop))))
+ #:line #f))
+
+;; HTML engine customizations
+(let ((html-engine (find-engine 'html)))
+ (engine-custom-set! html-engine 'css "/style.css")
+ (engine-custom-set! html-engine 'charset "UTF-8")
+ (markup-writer 'abbr html-engine
+ #:options '(#:short #:long)
+ #:action (lambda (markup engine)
+ (display (format "<abbr title=\"~a\">~a</abbr> (~a)"
+ (markup-option markup #:long)
+ (markup-option markup #:short)
+ (markup-option markup #:long))
+ (current-output-port)))))