M BUZZ CRAZE NEWS
// news

How to include a file when writing a custom man page?

By Jessica Wood

Currently I just copy the source file for my custom man page into place like this:

SOURCE=man/myManPage.1
DEST_DIR=/usr/local/share/man/man.1
sudo install -g 0 -o 0 -m 0644 "$SOURCE" "$DEST_DIR/"
yes | sudo gzip "$DEST_DIR/myManPage.1"

Works fine.

Now I want to be able to include a file containing a footer. Looks like using the .so macro in my man page source file might be one way forward:

.so footer.tmac

The .mso macro might be another option:

.mso footer.tmac

The problem with both of those approaches is that I am not actually running groff when moving the man page into place, I just copy the source into a .gz file and the include file is not around on the user machine so the footer does not display.

Perhaps I need to preprocess the man source somehow so a complete file is generated?

2 Answers

There is a soelim command provided with groff to do exactly this.

soelim reads files and replaces lines of the form .so file by the contents of file.

1

Here is my solution, using soelim as suggested by @meuh:

#!/bin/bash
# Publishes man.1 files in ~/myman/
# Preprocesses .so statements by including the specified files
INCLUDED=included
function publish { SOURCE="~/myman/$INCLUDED/$1" if [[ ! -f "$SOURCE" ]]; then echo "Fatal: '$SOURCE' does not exist" exit 2 fi I="${1##*.}" DEST_DIR=/usr/local/share/man/man${I} sudo mkdir -p ${DEST_DIR} sudo rm -f "$DEST_DIR/$1.gz" sudo install -g 0 -o 0 -m 0644 "$SOURCE" "$DEST_DIR/" echo "Creating $DEST_DIR/$1.gz" yes | sudo gzip "$DEST_DIR/$1"
}
cd "~/myman"
mkdir -p ${INCLUDED}
for CMD in *.1; do soelim -I ./ $CMD > $INCLUDED/$CMD pushd ${INCLUDED} > /dev/null publish "${CMD}" popd > /dev/null
done
sudo mandb

Here is a man source file with two .so include directives:

.TH man-course 1 "03 May 2019" "1.0" "cad-course man page"
.SH NAME
cad-course \- Cadenza Client command for authoring course content
.SH SYNOPSIS
cad course id aa | audioFromTitles | dw | fetch [-r] | gitNewRepo | publish | pp | status
.SH DESCRIPTION
\fBcad-course\fR is a Cadenza Client curriculum management command for authoring course-level content.
.so cad-description.tmac
.SH OPTIONS
The cad-course command takes sub-commands and options.
.SH EXAMPLES cad course 40 dw # Launch DreamWeaver on content for course #40 (Intro to Scala)
.PP cad course 40 dw # Launch DreamWeaver on content for course #40
.PP cad course 40 audioFromTitles # Build a new Adobe Audition audio project from course #40 transcript titles
.PP cad course 40 gitNewRepo # Wipe out any existing GitHub project for course #40 and make a new one,
check in current stuff. Use regular git commands as content is authored.
.PP cad course 40 fetch # (Re)download all of the content for course #40's courses from the active database and the active S3 buckets.
If uncommitted changes to course's git repo, ask user if the changes should
be committed before fetching. If no git repo, makes one.
.PP cad course -r 40 fetch # Also recurses by fetching sections & their lectures.
.so cad-footer.tmac

Here is cad-description.tmac:

The complete list of curriculum management commands is: cad-site, cad-group, cad-course, cad-section and cad-lecture.

Here is cad-footer.tmac:

.SH SEE ALSO cad-course(1),cad-group(1),cad-install(1),cad-lecture(1),cad-publish(1),cad-section(1),cad-site(1),cad-status(1),cad-status(1),bash(8)
.SH BUGS
No known bugs.
.SH AUTHOR
Michael Slinn ()

This is the output from man cad:

man(1) cad man page man(1)
NAME cad - Cadenza Client command-line interface
SYNOPSIS cad install status # TODO What other options might apply?
DESCRIPTION cad is a command-line interface for cadenzaClient
OPTIONS The cad command takes sub-commands and options.
EXAMPLES cad -h
SEE ALSO cad-course(1),cad-group(1),cad-install(1),cad-lecture(1),cad-publish(1),cad-section(1),cad-site(1),cad-status(1),cad-status(1),bash(8)
BUGS No known bugs.
AUTHOR Michael Slinn ()
1.0 03 May 2019 man(1)

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy