From b73cfcec0e90675c074fdef12ac1feb2675c7930 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Wed, 20 May 2026 12:15:42 +0200 Subject: initial commit --- .gitignore | 0 README.md | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ foo.1.adoc | 37 +++++++++++ 3 files changed, 259 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 foo.1.adoc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..0dc1b1e --- /dev/null +++ b/README.md @@ -0,0 +1,222 @@ +# Writing Man Pages with AsciiDoc + +A workflow for authoring Unix man pages in AsciiDoc and installing them into +the local man database on Debian (and Debian-derived) systems. + +## Why AsciiDoc + +Native `roff` is terse and unforgiving. AsciiDoc is plain-text, version-control +friendly, and `asciidoctor` ships a dedicated `manpage` backend that produces +groff source indistinguishable from a hand-written page. + +## Prerequisites + +```sh +sudo apt install asciidoctor +``` + +Confirm the manpage backend is available: + +```sh +asciidoctor --backend=manpage --help >/dev/null && echo OK +``` + +## Source File Structure + +Name the source `.
.adoc`, where the section is one of: + +| Section | Contents | +|---------|--------------------------------| +| 1 | User commands | +| 5 | File formats and conventions | +| 7 | Miscellaneous / overviews | +| 8 | System administration commands | + +A minimal template (`foo.1.adoc`): + +```adoc += foo(1) +Author Name +:doctype: manpage +:manmanual: FOO Manual +:mansource: FOO 1.0 + +== NAME + +foo - one-line summary of what foo does + +== SYNOPSIS + +*foo* [_OPTIONS_] _ARGUMENT_ + +== DESCRIPTION + +Longer prose description of the command. + +== OPTIONS + +*-h*, *--help*:: + Print help and exit. + +*-v*, *--version*:: + Print version and exit. + +*-f* _FILE_, *--file*=_FILE_:: + Read input from _FILE_. + +== EXIT STATUS + +*0*:: + Success. + +*1*:: + General error. + +== EXAMPLES + +Run foo against a file: + + foo -f /etc/hosts + +== ENVIRONMENT + +*FOO_CONFIG*:: + Path to the configuration file. + +== FILES + +_~/.config/foo/config_:: + User configuration. + +== SEE ALSO + +*bar*(1), *baz*(5) + +== AUTHORS + +Author Name + +== BUGS + +Report bugs at https://example.org/foo/issues +``` + +### Mandatory elements + +- **Title line** `= name(section)` sets the page name and section number. +- **`:doctype: manpage`** selects the manpage backend. +- **`NAME`, `SYNOPSIS`, `DESCRIPTION`** headers (uppercase, `==`) are required. + +### Useful conventions + +- `*bold*` renders as bold (commands, flags). +- `_italic_` renders as underline in terminals (variables, arguments, file + paths). +- `*cmd*(N)` for cross-references to other man pages. +- `::` after a term starts a definition list (options, environment vars). +- Indented lines in `EXAMPLES` are preformatted blocks. + +## Building + +Convert AsciiDoc to groff man source: + +```sh +asciidoctor -b manpage foo.1.adoc +``` + +Output: `foo.1` in the same directory. + +Preview without installing: + +```sh +man -l ./foo.1 +``` + +## Installing Locally + +Debian's `man-db` reads `~/.local/share/man` automatically (it is part of the +default `MANPATH` derivation). No `manpath` edit required. + +```sh +mkdir -p ~/.local/share/man/man1 +cp foo.1 ~/.local/share/man/man1/ +``` + +After installation: + +```sh +man foo # works immediately +``` + +For `apropos` and `whatis` to find the new page, rebuild the index: + +```sh +mandb -u # incremental update of the user index +``` + +The user-level index lives in `~/.local/share/man/index.db`; no root needed. + +## System-Wide Installation (optional) + +For pages that should be visible to all users: + +```sh +sudo cp foo.1 /usr/local/share/man/man1/ +sudo mandb +``` + +Use `/usr/local/share/man`, not `/usr/share/man` (the latter is reserved for +distribution-packaged pages). + +## Verification + +```sh +man -w foo # prints the path man would open +man -k 'one-line summary' # apropos search; requires mandb update +whatis foo +``` + +## Automating with Make + +A minimal `Makefile`: + +```makefile +PREFIX ?= $(HOME)/.local +MAN1DIR := $(PREFIX)/share/man/man1 + +SOURCES := $(wildcard *.1.adoc) +PAGES := $(SOURCES:.adoc=) + +all: $(PAGES) + +%.1: %.1.adoc + asciidoctor -b manpage $< + +install: all + install -d $(MAN1DIR) + install -m 644 $(PAGES) $(MAN1DIR)/ + mandb -u + +clean: + rm -f $(PAGES) + +.PHONY: all install clean +``` + +Usage: `make`, `make install`, `make clean`. + +## Troubleshooting + +| Symptom | Cause / Fix | +|-------------------------------------------|------------------------------------------------------------------| +| `man foo` reports "No manual entry" | File not in MANPATH; check `manpath` and `man -w foo` | +| `apropos foo` finds nothing | Run `mandb -u` | +| Page renders but options look misaligned | Ensure `::` is on the same logical line as the term it defines | +| Cross-references not linked in HTML build | Manpage backend renders them as `name(N)` text only; this is OK | +| Asciidoctor warns about missing `NAME` | The required headers must be uppercase and start with `==` | + +## References + +- `asciidoctor(1)`, `man(1)`, `man-pages(7)`, `mandb(8)` +- Asciidoctor manpage backend: +- File Hierarchy Standard, §4.11 (manual pages) diff --git a/foo.1.adoc b/foo.1.adoc new file mode 100644 index 0000000..8692d9e --- /dev/null +++ b/foo.1.adoc @@ -0,0 +1,37 @@ += foo(1) +Łukasz Kasprzak +:doctype: manpage +:manmanual: FOO Manual +:mansource: FOO 1.0 + +== NAME + +foo - one-line description + +== SYNOPSIS + +*foo* [_OPTIONS_] _ARG_ + +== DESCRIPTION + +Longer description. + +== OPTIONS + +*-h*, *--help*:: + Show help. + +*-v*, *--version*:: + Print version. + +== EXAMPLES + + foo -v + +== SEE ALSO + +*bar*(1), *baz*(5) + +== AUTHOR + +Łukasz Kasprzak -- cgit v1.3