The POSIX sh text preprocessor
pp expands inline shell commands:
- UNIX philosophy:
stdinfor input,stdoutfor output - Nothing new: flexible and familiar by design by accepting shell commands
- Minimal: shellcheck linted <30 s.l.o. POSIX sh script
Today (!{date '+%Y-%m-%d'}!) there's a lot to do:
!! cat ~/tasks.txt
Tomorrow's tasks can wait. !{# Change wording? }!
becomes
Today (2022-04-11) there's a lot to do:
* Wash clothes
* Read pure sh bible
* Write README
Tomorrow's tasks can wait.
Check out more examples.
- Pre-processing markdown files before compilation (e.g. pipe into pandoc pandoc
cat file.md | pp | pandoc -o file.pdf) extending markdown to add anything that may appear in stdout. - Writing a book/static website in markdown? Import text from different files, using a common header/footer with a custom body (see examples)
- Create always up to date, dynamic notebooks. Want a date at the top of the file that is always correct? A short up to date git log statement? Enter the commands and every time pp is run on the file, the output is up to date.
See the manpage PP(1).
Use the install script to copy the pp script to your user bin and compile the markdown manpage, outputting at the user man path.
git clone https://github.com/jhjn/pp
cd pp/
./install.sh
NOTE: The manpage pp.1 build requires pandoc.
Use the command line syntax to insert command output
!! which ls
Use the section command syntax to insert inline output.
foo !{command}! bar
Print the $line to keep the macro command in the output when run. Begin your command with:
!! echo "$line" && command
To import text into a document (instructions.txt) during pre-processing, the cat command can be used:
The following metadata, stored at /etc/mydata.txt, will be used:
!! cat /etc/mydata.txt
This is updated nightly...
running cat instruction.txt | pp gives the output,
The following metadata, stored at /etc/mydata.txt, will be used:
name time location
----------------------
ava 2301 upstairs
bob 1832 downstairs
----------------------
This is updated nightly...
For more complicated inline expressions a separate script in the repository can be used. For instance,
Check out all this data:
!! bash ./scripts/gen-data.sh
This was calculated automatically when creating the document.
Similarly, using environment variable control, a single template file can be expanded into a full html page. The pattern may look like:
<head>
...
</head>
!! markdown $INPUT_FILE
<footer>
...
</footer>
running cat template.html | INPUT_FILE=blog.md pp > blog.html could be used to fill the template with the desired content at runtime.
Note that the # character is used for shell comments, this still applies in macros. Therefore,
!!# This document is written by Tom
Important !{#Make bold?}! content
becomes,
Important content
The stdin-stdout model is well suited to chains of processing. For instance, a markdown file could be processed using awk, piped into pp and finally compiled into html. This pattern would look like:
for file in $(ls *.md); do
awk -f $file | INPUT=$file pp | cmark > ${file%%.md}.html
done
foo
!! pp next.md
bar
Multiple pp instances can be nested like above.
Pull requests welcome!