various doc fixes apply patch from gxt:
noop commit for testing
give explicit link descriptions so they render nicely in HTML
Automatically render code and documentation from org when you git commit
.
This is handy to generate README.md (and .txt, and .html, …?) from README.org. It can also be used to "build" all of the programs in a project from a single file, as in the case of this project, itself.
Use this to render documentation, program sources, or a mix of the two, from org format to "pure code" files, markdown, and HTML.
Jump to
Writing your project's README in org is nearly identical to writing (directly) in Markdown. Org includes more expressive syntax to describe more flexible intents. For example, org allows us to conditionally render parts of a document based on the target extort format (e.g. Markdown, HTML, or "raw" text) and to specify which file code in a given source block is for/from.
The ubiquity of the Markdown (MD/md) format makes maintaining a project README in Org format slightly inconvenient. While some forges support rendering web-portal content directly from Org documents, others do not, potentially leading to vendor lock-in.
This project helps to mitigate that concern though automation.
The default configuration (given a quick start), enables automatic
generation of README.md (and README.html and README.txt) from
README.org automatically upon commit. The supplied post-commit
script appends the generated files to the (prior) commit, so the
effect is transparent for the purposes of git history, blame, etc.
Using Emacs to edit org files is convent, but not required. Org files are plan text files. Various (other) editors can format, highlight ("font-lock"), and otherwise integrate support for Org.
The programs use a "stock" (disro- package-manager or GNU supplied) emacs in batch mode (a shell interaction/scripting interface); thus, no direct user interaction with Emacs is expressly required/implied.
Any authoritative version (e.g. from GNU or your OS distro vendor) is likely fine. I suspect that using this in conjunction with a derivative distribution (e.g. Spacemacs) would work; not tested.
Control which files rendered (and post-fixed to each commit) with environment variables.
The programs expect these variables to be setup by .env
which is
generally a shell script in the project's root folder. The project
includes a sample .env
file which only sets these variables. You can
append this to any existing .env file in your project, or simply edit
your existing .env
file to define and export them.
The table below lists these shell variables while the subsections following describe how to use them.
Variable | Default | Valid Value(s) |
---|---|---|
`ORG_GIT_EXPORT` | README.org | file including proj rel path, or several space separated |
`ORG_GIT_TANGLE` | README.org | As above. |
`ORG_GIT_FORMAT` | md html txt | one or more of "md", "txt", or "html" |
Control which files will be exported (converted from org to other
formats) by changing the value of ORG_GIT_EXPORT
, usually by editing
.env
. script.
The value should be a file or list of files. Each file name should be given including path, relative to the project root. If you list several files, they should separated by spaces and the entire list enclosed in quotes. It is acceptable but not necessary to enclose a single file/path in quotes.
Extra spaces preceding/following/separating shouldn't be a problem.
In most OSes you can use either single ('
) or double ("
) quotes:
windows users will want to sick to double-quotes.
Tangling is the process of rendering "pure-code files" (programs) from an org document. By default each file exported is also tangled.
This is controlled by ORG_GIT_TANGLE
exported from the
.env
script. Simply replace this line:
ORG_GIT_TANGLE=ORG_GIT_EXPORT
Edit it to another file or list as for setting ORGGITEXPORT.
ORG_GIT_TANGLE="docs/README.org examples/README.org"
We can export in three formats, of which we do all by default. It is not possible to select formats per a given org source file.
Control the formats output by setting ORG_GIT_FORMATS
, usually by
editing the .env file. You may edit to remove some entries.
Valid values are:
Support for other formats would likely welcome back into this project, noting that requirements outside of "stock" emacs should be guarded; the base project should work with only Emacs as provided by our OS distributions' upstream packaging network. Please see Contribuiting.
To make contact, whether for questions, comments, code suggestions, etc., please
Patches are most welcome, with the caveat that I would like things to work nicely for people with only a OSs "stock" Emacs, e.g. no patches that would introduce hard/noisy deps on non-core Emacs packages.
Thank you.
The README.org file in the root of this projects git repository is used to generate the rest of the project. That is to say, all of the source for this project is (given you are reading the README.org vs README.md, etc.) contained in this file.
That can be quite handy, for example searching this file for a variable name, message or phrase, is guaranteed to turn up all related code and documentation expressly related.
Following the CONTRIBUTING section (notwithstanding the License
boilerplate at the end) the rest of this file contains and explains
this projects' source-code. This file contains the complete source
for all programs in this project; however, exported versions such as
README.md
omit most top-of-program commentary.
Changing the code means editing this file.
This will involve editing program code contained within blocks of mark-up that delineate the sources from narrative ("written for humans") and sources for separate programs built within the same org document.
The mark-up wires-up both the "code generation" and "formatted document rendering" for each source block.
Header directives (given in the opening phrase for the block) give the programming language, a file to save program content to, and (in some cases) whether to suppress quoting source the passage when exporting.
A org source block might look like:
#+BEGIN_SRC sh :file pre-commit
touch .commit
#+END_SRC
To make and test your changes
make your edits to README.org
manually tangle README.org
emacs -batch -exec "(progn (require 'org) (find-file \"README.org\") (org-babel-tangle))"
manually execute build.el
emacs -batch -l build.el
manually review/test the files create by build.el
create a patch, e.g.
git format-patch master
Default shell environment setup file, in case the target project doesn't have one.
This sets up a couple of environment variables:
ORG_GIT_EXPORT
a project root relative file path or a quoted, space separated list of theseORG_GIT_TANGLE
samemd
, html
, and txt
.The programs created by tangling this README.org
each have these
variables defined when running. This program (the .env
file) is
simply a shell script and can contain other code, for example to
calculate the values used to set the above shell/env variables.
When a given project already has a .env
, appended this projects to
that one, or (perhaps more legibly,) manually edit the target
project's .env
file to set and export the variables.
This is a script file for Emacs.
Generate pure-code files from sources (org-babel-tangle
) and export
documentation (org-X-export-to-X
) in multiple output formats.
We use the functionality built into org (which is a core component
of Emacs), to first to render pure-code files from this README.org
("tangle"), and then to export this README.org
into other formats,
such as HTML, Markdown, and ASCII text.
Following is the complete program source (excluding top-of-file comments, which aren't shown in exported versions such README.md).
(require 'ox-md) ;; maybe something to install ox-md from MELPA?
;; Tangle first in case we are generating the org files to export
(dolist (orgfile (split-string (getenv "ORG_GIT_TANGLE")))
(find-file orgfile)
(org-babel-tangle))
(let ((expfmtstr (downcase (getenv "ORG_GIT_FORMAT")))
(expmap '(("md" . org-md-export-to-markdown)
("html" . org-html-export-to-html)
("txt" . org-ascii-export-to-ascii))))
(dolist (orgfile (split-string (getenv "ORG_GIT_EXPORT")))
(find-file orgfile)
(dolist (expitem expmap)
(when (string-match-p (car expitem) expfmtstr)
(funcall (cdr expitem))))))
(provide 'build)
This shell script is called before each git commit. It creates a
"semaphore", touching a file. The post-commit
script will
predicate running build.el
on the existence of that file, removing
it if it acts. The semaphore file is .build
in the project root,
meaning commuters must have write permission to the project root.
In theory, we can add additional logic to this script. For example, we could check if the commit contains any .org files indented for processing prior to creating the semaphore file.
touch .commit
Shell script executed after each git commit.
If the "semaphore" file created by the pre-commit
script exists,
invoke Emacs in batch mode and run build.el
and append each file
created/updated to the commit.
# do nothing when .commit file is missing
if [ -e .commit ]; then
# "source" the .env file to create our environment variables
. ./.env
# tangle and export
/bin/env emacs -batch -l build.el
# clean-up the commit file
rm .commit
# list of the files to add
ORG_GIT_TMP=""
for orgfile in $ORG_GIT_EXPORT $ORG_GIT_TANGLE; do
# grep our list so we only add a given file once
if [[ -r $orgfile ]]; then
for ext in $ORG_GIT_FORMAT; do
addfile="$(dirname $orgfile)/$(basename $orgfile .org).$ext"
if [[ -z "$(echo \"$ORG_GIT_TMP\" | grep \"\\b$addfile\\b\")" ]]; then
ORG_GIT_TMP="$ORG_GIT_TMP $addfile"
fi
done
fi
done
# add then append to the prior commit
if [[ -n "$(echo '$ORG_GIT_TMP' | perl -pe 's/\s+//')" ]]; then
git add $ORG_GIT_TMP
git commit --amend -C HEAD --no-verify;
fi
fi
exit
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program 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 Affero Public License along with this program. If not, see https://www.gnu.org/licenses/.