{"id":13760780,"url":"https://github.com/CDSoft/pp","last_synced_at":"2025-05-10T11:31:51.691Z","repository":{"id":49896981,"uuid":"54962549","full_name":"CDSoft/pp","owner":"CDSoft","description":"PP - Generic preprocessor (with pandoc in mind) - macros, literate programming, diagrams, scripts...","archived":false,"fork":false,"pushed_at":"2023-12-22T15:13:18.000Z","size":4300,"stargazers_count":253,"open_issues_count":18,"forks_count":21,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-08-04T13:05:30.742Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://cdelord.fr/pp","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CDSoft.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2016-03-29T09:18:28.000Z","updated_at":"2024-07-19T03:12:32.000Z","dependencies_parsed_at":"2023-12-26T21:03:30.225Z","dependency_job_id":"dfd91552-890f-4685-aaf3-27fe70e62d72","html_url":"https://github.com/CDSoft/pp","commit_stats":null,"previous_names":[],"tags_count":56,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CDSoft%2Fpp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CDSoft%2Fpp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CDSoft%2Fpp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CDSoft%2Fpp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CDSoft","download_url":"https://codeload.github.com/CDSoft/pp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224957820,"owners_count":17398493,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T13:01:21.614Z","updated_at":"2024-11-16T18:31:31.633Z","avatar_url":"https://github.com/CDSoft.png","language":"Haskell","funding_links":[],"categories":["General Purpose Preprocessor","Haskell"],"sub_categories":["Snippets Manager"],"readme":"# PP - Generic preprocessor (with pandoc in mind)\n\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\") is a\ntext preprocessor designed for Pandoc (and more generally Markdown and\nreStructuredText).\n\nThe [PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\")\npackage used to contain three preprocessors for\n[Pandoc](http://pandoc.org/).\n\nI started using Markdown and [Pandoc](http://pandoc.org/) with\n[GPP](http://en.nothingisreal.com/wiki/GPP). Then I wrote\n[DPP](http://cdelord.fr/dpp \"DPP - Diagram Preprocessor (for Pandoc)\")\nto embed diagrams in Markdown documents. And finally\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\")\nwhich merges the functionalities of\n[GPP](http://en.nothingisreal.com/wiki/GPP) and\n[DPP](http://cdelord.fr/dpp \"DPP - Diagram Preprocessor (for Pandoc)\").\n\n[GPP](http://en.nothingisreal.com/wiki/GPP) and\n[DPP](http://cdelord.fr/dpp \"DPP - Diagram Preprocessor (for Pandoc)\")\nare no longer included in\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\") as\n`pp` can now be used standalone. `dpp` and `gpp` can be found in the\nlegacy\n[DPP](http://cdelord.fr/dpp \"DPP - Diagram Preprocessor (for Pandoc)\")\nrepository.\n\n`pp` now implements:\n\n- macros\n- literate programming\n- [GraphViz](http://graphviz.org/),\n  [PlantUML](http://plantuml.sourceforge.net/),\n  [ditaa](http://ditaa.sourceforge.net/) and\n  [blockdiag](http://blockdiag.com/) diagrams\n- [Asymptote](http://asymptote.sourceforge.net/) and\n  [R](https://www.r-project.org/) figures\n- [Bash](https://www.gnu.org/software/bash/),\n  [Cmd](https://en.wikipedia.org/wiki/Cmd.exe),\n  [PowerShell](https://en.wikipedia.org/wiki/PowerShell),\n  [Python](https://www.python.org/), [Lua](http://www.lua.org/),\n  [Haskell](https://www.haskell.org/) and\n  [R](https://www.r-project.org/) scripts\n- [Mustache](https://github.com/JustusAdam/mustache)\n\n# Warning: PP is not supported anymore\n\nTheir is no plan to support PP from now on. PP is meant to be replaced\nby a combination of:\n\n- [ypp](http://cdelord.fr/ypp): Lua-scriptable PreProcessor\n- [Panda](http://cdelord.fr/panda): Pandoc add-ons (Lua filters for\n  Pandoc)\n\nypp and Panda are written in Lua and are way easier to deploy.\n\n# Open source\n\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\") is\nan Open source software. Anybody can contribute on\n[GitHub](https://github.com/CDSoft/pp) to:\n\n- suggest or add new features\n- report or fix bugs\n- improve the documentation\n- add some nicer examples\n- find new usages\n- …\n\n# Installation\n\n**Compilation**:\n\n1.  Download and extract [pp.tgz](http://cdelord.fr/pp/pp.tgz).\n2.  Run `make`.\n\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\") is\nwritten in [Haskell](https://www.haskell.org/) and is built with\n[Stack](https://docs.haskellstack.org/en/stable/README/). On MacOS,\nrunning `make` requires the GNU version of `tar` which can be installed\nwith `brew install gnu-tar`.\n\n**Docker**:\n\nA Linux docker made by [Joshua Dotson](https://github.com/josdotso) is\navailable here:\n\n- https://hub.docker.com/r/josdotso/pp\n- https://github.com/josdotso/docker-pp\n\n**Installation**:\n\n- Run `make install` to copy `pp` in `~/.local/bin`.\n- or copy `pp` (`pp.exe` on Windows) wherever you want.\n\n`pp` requires (*optionally*) [Graphviz](http://graphviz.org/),\n[blockdiag](http://blockdiag.com/),\n[Asymptote](http://asymptote.sourceforge.net/),\n[R](https://www.r-project.org/) and Java\n([PlantUML](http://plantuml.sourceforge.net/) and\n[ditaa](http://ditaa.sourceforge.net/) are embedded in `pp`).\n\n**Precompiled binaries**:\n\nThe recommended way to get PP binaries is to compile them from the\nsources. Anyway if you have no Haskell compiler, you can try some\nprecompiled binaries.\n\n- Latest Linux and Windows binaries:\n\n  - Fedora Linux 37 (Xfce) (64 bit):\n    \u003chttp://cdelord.fr/pp/pp-linux-x86_64.txz\u003e\n  - Windows (64 bit): \u003chttp://cdelord.fr/pp/pp-win.7z\u003e\n\n- Older version archive:\n\n  - no longer available\n\n- User contributed Mac OS binaries (outdated):\n\n  - Mac OS (64 bit binaries):\n    \u003chttps://github.com/dlardi/pp/releases/download/v1.0/pp-darwin-x86_64.txz\u003e\n\n# Usage\n\n`pp` is a simple preprocessor written in Haskell. It’s mainly designed\nfor Pandoc but may be used as a generic preprocessor. It is not intended\nto be as powerful as GPP, for instance, but is a simple implementation\nfor my own needs, as well as an opportunity to play with Haskell.\n\n`pp` takes strings as input and incrementally builds an environment\nwhich is a lookup table containing variables and various other\ninformation. Built-in macros are Haskell functions that takes arguments\n(strings) and the current environment and build a new environment in the\nIO monad. User defined macros are simple definitions, arguments are\nnumbered 1 to N.\n\n`pp` emits the preprocessed document on the standard output. Inputs are\nlisted on the command line and concatenated, the standard input is used\nwhen no input is specified.\n\n## Command line\n\n`pp` executes arguments in the same order as the command line. It starts\nwith an initial environment containing:\n\n- the environment variables of the current process\n- a `lang` variable containing the current langage (currently only\n  French (`fr`), Italian (`it`), Spanish (`es`) and English (`en`) are\n  supported)\n- a `format` variable containing the current output format (`html`,\n  `pdf`, `odt`, `epub` or `mobi`)\n- a `dialect` variable containing the current dialect (`md` or `rst`)\n\nThe *dialect* is used to format links and images in the output\ndocuments. Currently only Markdown and reStructuredText are supported.\n\nIf no input file is specified, `pp` preprocesses the standard input.\n\nThe command line arguments are intentionally very basic. The user can\ndefine and undefine variables and list input files.\n\n**`-v`**  \ndisplays the current version and exits.\n\n**`-h`**  \ndisplays some help and exits.\n\n**`-help`**  \ndisplays a longer help and exits.\n\n**`-userhelp`**  \ndisplays a longer help for user macros only and exits.\n\n**`-DSYMBOL[=VALUE]`** or **`-D SYMBOL[=VALUE]`**  \nadds the symbol `SYMBOL` to the current environment and associates it to\nthe optional value `VALUE`. If no value is provided, the symbol is\nsimply defined with an empty value.\n\n**`-USYMBOL`** or **`-U SYMBOL`**  \nremoves the symbol `SYMBOL` from the current environment.\n\n**`-img=PREFIX`** or **`-img PREFIX`**  \nchanges the prefix of the images output path.\n\n**`-import=FILE`** or **`-import FILE`**  \npreprocessed `FILE` but discards its output. It only keeps macro\ndefinitions and other side effects.\n\n**`-M TARGET`** or **`-M=TARGET`**  \ntracks dependencies and outputs a make rule listing the dependencies.\nThe target name is necessary since it can not be infered by `pp`. This\noption only lists files that are imported, included and used with\n`mdate` and `csv`macros.\n\n**`-plantuml=FILE`** or **`-plantuml FILE`**  \nuse `FILE` instead of the embedded plantuml.jar file.\n\n**`-ditaa=FILE`** or **`-ditaa FILE`**  \nuse `FILE` instead of the embedded ditaa.jar file.\n\n**`-\u003cmacro\u003e[=\u003carg\u003e]`**  \ncalls a builtin macro with an optional argument (see `pp -help` for the\nfull macro list). Some macros may prevent pp from reading stdin when no\nfile is given on the command line (`langs`, `formats`, `dialects`, `os`,\n`arch`, `macros`, `usermacros`).\n\nOther arguments are filenames.\n\nFiles are read and preprocessed using the current state of the\nenvironment. The special filename “`-`” can be used to preprocess the\nstandard input.\n\n## Macros\n\nBuilt-in macros are hard coded in `pp` and can not be redefined. User\ndefined macros are simple text substitutions that may have any number of\nparameters (named `!1` to `!n`). User macros can be (re)defined on the\ncommand line or in the documents.\n\nMacro names are:\n\n- case sensitive (i.e.: `!my_macro` and `!My_Macro` are different\n  macros)\n- made of letters, digits and underscores (`a-zA-Z0-9_`)\n\nUser macros starting with `_` are not listed in macros lists and help\ntexts.\n\nTo get the value of a variable you just have to write its name after a\n‘`!`’. Macros can be given arguments. Each argument is enclosed in\nparenthesis, curly braces or square brackets. For instance, the macro\n`foo` with two arguments can be called as `!foo(x)(y)`, `!foo{x}{y}` or\neven `!foo[x][y]`. Mixing brackets, braces and parenthesis within a\nsingle macro is not allowed: all parameters must be enclosed within the\nsame type of delimiters. This helps ending a list of arguments in some\nedge cases:\n\n    !macro(x)(y)\n\n    [link]: foo bar\n\n    Here, [link] is not parsed as a third parameter of !macro\n\nArguments are stripped. Removing leading and trailing spaces helps\npreserving line structure in the document.\n\nThe last arguments can be enclosed between lines of tildas or backquotes\n(of the same length) instead of parenthesis, brackets or braces and.\nThis is useful for literate programming, diagrams or scripts (see\n[examples](#examples)). Code block arguments are not stripped: spaces\nand blank lines are preserved.\n\nArguments can be on separate lines but must not be separated by blank\nlines.\n\nYou can choose the syntax that works better with your favorite editor\nand syntax colorization.\n\nFor most of the macros, arguments are preprocessed before executing the\nmacro. Macros results are not preprocessed (unless used as a parameter\nof an outer macro). The `include` macro is an exception: its output is\nalso preprocessed. The `rawinclude` macro can include a file without\npreprocessing it.\n\n**`define`**, **`def`**  \n`!def[ine](SYMBOL)[[(DOC)](VALUE)]` adds the symbol `SYMBOL` to the\ncurrent environment and associate it with the optional value `VALUE`.\nArguments are denoted by `!1` … `!n` in `VALUE`. If `DOC` is given it is\nused to document the macro (see the `-help` option).\n\n**`undefine`**, **`undef`**  \n`!undef[ine](SYMBOL)` removes the symbol `SYMBOL` from the current\nenvironment.\n\n**`defined`**  \n`!defined(SYMBOL)` returns 1 if `SYMBOL` is defined, 0 otherwise.\n\n**`rawdef`**  \n`!rawdef(X)` returns the raw (unevaluated) definition of `X`.\n\n**`ifdef`**  \n`!ifdef(SYMBOL)(TEXT_IF_DEFINED)[(TEXT_IF_NOT_DEFINED)]` returns\n`TEXT_IF_DEFINED` if `SYMBOL` is defined or `TEXT_IF_NOT_DEFINED` if it\nis not defined.\n\n**`ifndef`**  \n`!ifndef(SYMBOL)(TEXT_IF_NOT_DEFINED)[(TEXT_IF_DEFINED)]` returns\n`TEXT_IF_NOT_DEFINED` if `SYMBOL` is not defined or `TEXT_IF_DEFINED` if\nit is defined.\n\n**`ifeq`**  \n`!ifeq(X)(Y)(TEXT_IF_EQUAL)[(TEXT_IF_DIFFERENT)]` returns\n`TEXT_IF_EQUAL` if `X` and `Y` are equal or `TEXT_IF_DIFFERENT` if `X`\nand `Y` are different. Two pieces of text are equal if all non-space\ncharacters are the same.\n\n**`ifne`**  \n`!ifne(X)(Y)(TEXT_IF_DIFFERENT)[(TEXT_IF_EQUAL)]` returns\n`TEXT_IF_DIFFERENT` if `X` and `Y` are different or `TEXT_IF_EQUAL` if\n`X` and `Y` are equal.\n\n**`if`**  \n`!if(EXPR)(TEXT_IF_EXPR_IS_TRUE)[(TEXT_IF_EXPR_IS_FALSE)]` returns\n`TEXT_IF_EXPR_IS_TRUE` if `EXPR` is true or `TEXT_IF_EXPR_IS_FALSE` if\n`EXPR` is false.\n\n**`eval`**  \n`!eval(EXPR) evaluates`EXPR\\`.\n\n**`info`**  \n`!info(MESSAGE) prints`MESSAGE\\` on stderr.\n\n**`warning`**, **`warn`**  \n`!warn[ing](MESSAGE) prints`MESSAGE\\` on stderr.\n\n**`error`**  \n`!error[(CODE)](MESSAGE) prints`MESSAGE`on stderr and exits with error code`CODE\\`.\n\n**`exit`**  \n`!exit(CODE) exits with error code`CODE\\`.\n\n**`import`**  \n`!import(FILENAME)` works as `!include(FILENAME)` but returns nothing.\nThis is useful to import macro definitions.\n\n**`include`**, **`inc`**  \n`!inc[lude](FILENAME)` preprocesses and returns the content of the file\nnamed `FILENAME` and includes it in the current document. If the file\npath is relative it is searched first in the directory of the current\nfile then in the directory of the main file.\n\n**`raw`**  \n`!raw(TEXT)` returns `TEXT` without any preprocessing.\n\n**`rawinclude`**, **`rawinc`**  \n`!rawinc[lude](FILE)` returns the content of `FILE` without any\npreprocessing.\n\n**`comment`**  \n`!comment(TEXT)` considers `TEXT` as well as any additional parameters\nas comment. Nothing is preprocessed or returned.\n\n**`quiet`**  \n`!quiet(TEXT)` quietly preprocesses `TEXT` and returns nothing. Only the\nside effects (e.g. macro definitions) are kept in the environment.\n\n**`pp`**  \n`!pp(TEXT)` preprocesses and return `TEXT`. This macro is useful to\npreprocess the output of script macros for instance (`!sh`, `!python`,\n…).\n\n**`mustache`**  \n`!mustache(JSON/YAML file)(TEMPLATE)` preprocesses `TEMPLATE` with\nmustache, using a `JSON/YAML file`.\n\n**`mdate`**  \n`!mdate(FILES)` returns the modification date of the most recent file.\n\n**`main`**  \n`!main` returns the name of the main file (given on the command line).\n\n**`file`**  \n`!file` returns the name of the current file.\n\n**`root`**  \n`!root` returns the directory name of the main file.\n\n**`cwd`**  \n`!cwd` returns the directory name of the current file.\n\n**`lang`**  \n`!lang` returns the current language.\n\n**`langs`**  \n`!langs` lists the known languages (en, fr, it, es).\n\n**`en`**  \n`!en(TEXT)` returns `TEXT` if the current language is `en`.\n\n**`fr`**  \n`!fr(TEXT)` returns `TEXT` if the current language is `fr`.\n\n**`it`**  \n`!it(TEXT)` returns `TEXT` if the current language is `it`.\n\n**`es`**  \n`!es(TEXT)` returns `TEXT` if the current language is `es`.\n\n**`format`**  \n`!format` returns the current output format.\n\n**`formats`**  \n`!formats` lists the known formats (html, pdf, odf, epub, mobi).\n\n**`html`**  \n`!html(TEXT)` returns `TEXT` if the current format is `html`.\n\n**`pdf`**  \n`!pdf(TEXT)` returns `TEXT` if the current format is `pdf`.\n\n**`odf`**  \n`!odf(TEXT)` returns `TEXT` if the current format is `odf`.\n\n**`epub`**  \n`!epub(TEXT)` returns `TEXT` if the current format is `epub`.\n\n**`mobi`**  \n`!mobi(TEXT)` returns `TEXT` if the current format is `mobi`.\n\n**`dialect`**  \n`!dialect` returns the current output dialect.\n\n**`dialects`**  \n`!dialects` lists the kown output dialects (md, rst).\n\n**`md`**  \n`!md(TEXT)` returns `TEXT` if the current dialect is `md`.\n\n**`rst`**  \n`!rst(TEXT)` returns `TEXT` if the current dialect is `rst`.\n\n**`env`**  \n`!env(VARNAME)` preprocesses and returns the value of the process\nenvironment variable `VARNAME`.\n\n**`os`**  \n`!os` returns the OS name (e.g. `linux` on Linux, `darwin` on MacOS,\n`windows` on Windows).\n\n**`arch`**  \n`!arch` returns the machine architecture (e.g. `x86_64`, `i386`, …).\n\n**`add`**  \n`!add(VARNAME)[(INCREMENT)]` computes `VARNAME+INCREMENT` and stores the\nresult to `VARNAME`. The default value of the increment is 1.\n\n**`append`**  \n`!append(VARNAME)[(TEXT)]` appends `TEXT` to `!VARNAME` and stores the\nresult to `VARNAME`.\n\n**`exec`**  \n`!exec(COMMAND)` executes a shell command with the default shell (`sh`\nor `cmd` according to the OS).\n\n**`rawexec`**  \n`!rawexec` is *deprecated*. See exec.\n\n**`sh`**  \n`!sh(CMD)` executes `CMD` in a `sh` shell.\n\n**`bash`**  \n`!bash(CMD)` executes `CMD` in a `bash` shell.\n\n**`zsh`**  \n`!zsh(CMD)` executes `CMD` in a `zsh` shell.\n\n**`fish`**  \n`!fish(CMD)` executes `CMD` in a `fish` shell.\n\n**`cmd`**  \n`!cmd(CMD)` executes `CMD` in a Windows shell (cmd.exe).\n\n**`bat`**  \n`!bat` is *deprecated*. See cmd.\n\n**`python`**  \n`!python(CMD)` executes `CMD` with the default Python interpretor.\n\n**`python2`**  \n`!python2(CMD)` executes `CMD` with Python 2.\n\n**`python3`**  \n`!python3(CMD)` executes `CMD` with Python 3.\n\n**`lua`**  \n`!lua(CMD)` executes `CMD` with Lua.\n\n**`haskell`**  \n`!haskell(CMD)` executes `CMD` as a Haskell script with `runhaskell`.\n\n**`stack`**  \n`!stack(CMD)` executes `CMD` as a Haskell script with `stack`.\n\n**`Rscript`**  \n`!Rscript(CMD)` executes `CMD` as a R script with Rscript.\n\n**`powershell`**  \n`!cmd(CMD)` executes `CMD` in a Windows shell (Powershell).\n\n**`dot`**  \n`!dot(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a dot image with\nGraphviz.\n\n**`neato`**  \n`!neato(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a neato image with\nGraphviz.\n\n**`twopi`**  \n`!twopi(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a twopi image with\nGraphviz.\n\n**`circo`**  \n`!circo(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a circo image with\nGraphviz.\n\n**`fdp`**  \n`!fdp(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a fdp image with\nGraphviz.\n\n**`sfdp`**  \n`!sfdp(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a sfdp image with\nGraphviz.\n\n**`patchwork`**  \n`!patchwork(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a patchwork\nimage with Graphviz.\n\n**`osage`**  \n`!osage(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a osage image with\nGraphviz.\n\n**`uml`**  \n`!uml(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a uml image with\nPlantUML.\n\n**`ditaa`**  \n`!ditaa(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a ditaa image with\nDitaa.\n\n**`blockdiag`**  \n`!blockdiag(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a blockdiag\nimage with BlockDiag.\n\n**`seqdiag`**  \n`!seqdiag(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a seqdiag image\nwith BlockDiag.\n\n**`actdiag`**  \n`!actdiag(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a actdiag image\nwith BlockDiag.\n\n**`nwdiag`**  \n`!nwdiag(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a nwdiag image\nwith BlockDiag.\n\n**`rackdiag`**  \n`!rackdiag(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a rackdiag image\nwith BlockDiag.\n\n**`packetdiag`**  \n`!packetdiag(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a packetdiag\nimage with BlockDiag.\n\n**`asy`**  \n`!asy(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a asy image with\nAsymptote.\n\n**`Rplot`**  \n`!Rplot(IMAGE)[(LEGEND)](GRAPH DESCRIPTION)` renders a Rplot image with\nR.\n\n**`literate`**, **`lit`**  \n`!lit[erate](FILENAME)[(LANG)][(CONTENT)]` appends `CONTENT` to the file\n`FILENAME`. If `FILENAME` starts with `@` it’s a macro, not a file. The\noutput is highlighted using the programming language `LANGUAGE`. The\nlist of possible languages is given by\n`pandoc --list-highlight-languages`. Files are actually written when all\nthe documents have been successfully preprocessed. Macros are expanded\nwhen the files are written. This macro provides basic literate\nprogramming features. If `LANG` is not given, pp uses the previously\ndefined language for the same file or macro or a default language\naccording to its name. If `CONTENT`is not given, pp returns the current\ncontent of `FILENAME`.\n\n**`flushliterate`**, **`flushlit`**  \n`!flushlit[erate]` writes files built with `!lit` before reaching the\nend of the document. This macro is automatically executed before any\nscript execution or file inclusion with `!src`.\n\n**`source`**, **`src`**  \n`!source(FILENAME)[(LANG)]` or `!src(FILENAME)[(LANG)]` formats an\nexisting source file in a colorized code block.\n\n**`codeblock`**  \n`!codeblock(LENGTH)[(CHAR)]` sets the default line separator for code\nblocks. The default value is a 70 tilda row (`!codeclock(70)(~)`).\n\n**`indent`**  \n`!indent[(N)](BLOCK)` indents each line of a block with `N` spaces. The\ndefault value of `N` is 4 spaces.\n\n**`csv`**  \n`!csv(FILENAME)[(HEADER)]` converts a CSV file to a Markdown or\nreStructuredText table. `HEADER` defines the header of the table, fields\nare separated by pipes (`|`). If `HEADER` is not defined, the first line\nof the file is used as the header of the table.\n\n**`macrochars`**  \n`!macrochars(CHARS)` defines the chars used to call a macro. The default\nvalue is `\"!\"`. Any non space character can start a macro call\n(e.g. after `!macrochars(!\\)` both `!foo` and `\\foo` are valid macro\ncalls.\n\n**`macroargs`**  \n`!macroargs(CHARS)` defines the chars used to separate macro arguments.\nThe default value is `\"(){}[]\"` (e.g. after `!macroargs(()«»)` both\n`!foo(...)` and `!foo«...»` are valid macro calls).\n\n**`macroblockargs`**  \n`!macroblockargs(CHARS)` defines the chars used to separate macro block\narguments. The default value is `` \"~`\" ``.\n\n**`literatemacrochars`**  \n`!literatemacrochars(CHARS)` defines the chars used to identify literate\nprogramming macros. The default value is `\"@\"`. Any non space character\ncan start a literate programming macro (e.g. after\n`!literatemacrochars(@\u0026)` both `@foo` and `\u0026foo` are valid macro calls.\n\n**`macros`**  \n`!macros` lists the builtin macros.\n\n**`usermacros`**  \n`!usermacros` lists the user macros.\n\n**`help`**  \n`!help` prints built-in macro help.\n\n**`userhelp`**  \n`!userhelp` prints user macro help.\n\n# Expressions\n\nThe `!if` and `!eval` macros take an expression and evaluate it.\nExpressions are made of:\n\n- integers\n- string (`\"...\"`)\n- integer operators (`+`, `-`, `*`, `/`)\n- boolean operators (`!`, `not`, `\u0026\u0026`, `and`, `||`, `or`, `xor`)\n- relational operators (`==`, `/=`, `!=`, `\u003c`, `\u003c=`, `\u003e`, `\u003e=`)\n- parentheses, brackets and braces\n\nBoolean values are coded as integers or string (`0` and `\"\"` are false,\nother values are true).\n\nMacros can be called in expressions. They are preprocessed before\nevaluating the expression.\n\ne.g.:\n\n    !if( !defined(FOO) or !BAR == 42 ) (say something)\n\n# Literate programming example\n\nThe main program just prints some messages:\n\n    !lit(main.c)(C)\n    ~~~~~~~~~~~~~~~~~~~~\n    @includes\n    void main()\n    {\n    @messages\n    }\n    ~~~~~~~~~~~~~~~~~~~~\n\nFirst we need to be able to print messages:\n\n    !lit(@includes)(C)\n    ~~~~~~~~~~~~~~~~~~~~\n    #include \u003cstdio.h\u003e\n    ~~~~~~~~~~~~~~~~~~~~\n\nThe program must first say “Hello” :\n\n    !lit(@messages)(C)\n    ~~~~~~~~~~~~~~~~~~~~\n        puts(\"Hello...\\n\");\n    ~~~~~~~~~~~~~~~~~~~~\n\nAnd also finally “Goodbye”:\n\n    !lit(@messages)\n    ~~~~~~~~~~~~~~~~~~~~\n        puts(\"Goodbye.\");\n    ~~~~~~~~~~~~~~~~~~~~\n\n# Diagram and script examples\n\n## Diagrams\n\nDiagrams are written in code blocks as argument of a diagram macro. The\nfirst line contains the macro:\n\n- the diagram generator (the macro name)\n- the image name with or without the extension (first argument)\n  - the default format is `svg` if no extension is provided (unless for\n    ditaa diagrams which support `png` only)\n  - the supported formats are `png`, `svg` and ‘pdf’ (PDF support is\n    partial and may not work with PlantUML)\n- the legend (second optional argument)\n\nBlock delimiters are made of three or more tilda or back quotes, at the\nbeginning of the line (no space and no tab). The end delimiter must at\nleast as long as the beginning delimiter.\n\n    !dot(path/imagename)(optional legend)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n        graph {\n            \"source code of the diagram\"\n        }\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis extremely meaningful diagram is rendered as `path/imagename.svg`\nand looks like:\n\n![optional legend](doc/img/pp-syntax.svg)\n\nThe image file extension can be `.svg`, `.png` or `pdf`. `SVG` is the\ndefault format if no extension is provided (unless for ditaa diagrams).\n`!dot(path/imagename.svg)(optional legend)` or\n`!dot(path/imagename)(optional legend)` are rendered as\n`path/imagename.svg`. `!dot(path/imagename.png)(optional legend)` is\nrendered as `path/imagename.png`.\n`!dot(path/imagename.pdf)(optional legend)` is rendered as\n`path/imagename.pdf` (if supported).\n\nThe image link in the output markdown document may have to be different\nthan the actual path in the file system. This happens when then `.md` or\n`.html` files are not generated in the same path than the source\ndocument. Brackets can be used to specify the part of the path that\nbelongs to the generated image but not to the link in the output\ndocument. For instance a diagram declared as:\n\n    !dot([mybuildpath/]img/diag42)...\n\nwill be actually generated in:\n\n    mybuildpath/img/diag42.png\n\nand the link in the output document will be:\n\n    img/diag42.png\n\nFor instance, if you use Pandoc to generate HTML documents with diagrams\nin a different directory, there are two possibilities:\n\n1.  the document is a self contained HTML file (option\n    `--self-contained`), i.e. the CSS and images are stored inside the\n    document:\n    - the CSS path shall be the actual path where the CSS file is stored\n    - the image path in diagrams shall be the actual path where the\n      images are stored (otherwise Pandoc won’t find them)\n    - e.g.: `outputpath/img/diag42`\n2.  the document is not self contained, i.e. the CSS and images are\n    stored apart from the document:\n    - the CSS path shall be relative to the output document\n    - the image path in diagrams shall be relative to output document in\n      HTML links and shall also describe the actual path where the\n      images are stored.\n    - e.g.: `[outputpath/]img/diag42`\n\nPandoc also accepts additional attributes on images (`link_attributes`\nextension). These attributes can be added between curly brackets to the\nfirst argument. e.g.:\n\n    !dot(image.png { width=50 % })(caption)(...)\n\nwill generate the following link in the markdown output:\n\n    ![caption](image.png){ width=50 % }\n\nThe diagram generator can be:\n\n- dot\n- neato\n- twopi\n- circo\n- fdp\n- sfdp\n- patchwork\n- osage\n- uml\n- ditaa\n- blockdiag\n- seqdiag\n- actdiag\n- nwdiag\n- rackdiag\n- packetdiag\n- asy\n- Rplot\n\n`pp` will not create any directory, the path where the image is written\nmust already exist.\n\n![](doc/img/pp-generators.svg)\n\n## Scripts\n\nScripts are also written in code blocks as arguments of a macro.\n\n    !bash\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    echo Hello World!\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nWith no surprise, this script generates:\n\n    Hello World!\n\nThe script language macro can be:\n\n- `sh`, `bash`, `zsh`, `fish` or any other shell with `sh` and a\n  [shebang header](https://en.wikipedia.org/wiki/Shebang_(Unix))\n- `python`\n- `lua`\n- `haskell` (or `stack`)\n- `Rscript`\n- `cmd` (DOS/Windows batch language)\n- `powershell` (Windows only)\n\n`pp` will create a temporary script before calling the associated\ninterpretor.\n\n![](doc/img/pp-scripts.svg)\n\n## Examples\n\nThe [source code](pp.md) of this document contains some diagrams.\n\nHere are some simple examples. For further details about diagrams’\nsyntax, please read the documentation of\n[GraphViz](http://graphviz.org/),\n[PlantUML](http://plantuml.sourceforge.net/),\n[ditaa](http://ditaa.sourceforge.net/) and\n[blockdiag](http://blockdiag.com/).\n\n### Graphviz\n\n[GraphViz](http://graphviz.org/) is executed when one of these keywords\nis used: `dot`, `neato`, `twopi`, `circo`, `fdp`, `sfdp`, `patchwork`,\n`osage`\n\n    !twopi(doc/img/pp-graphviz-example)(This is just a GraphViz diagram example)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    digraph {\n        O -\u003e A\n        O -\u003e B\n        O -\u003e C\n        O -\u003e D\n        D -\u003e O\n        A -\u003e B\n        B -\u003e C\n        C -\u003e A\n    }\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n- `twopi` is the kind of graph (possible graph types: `dot`, `neato`,\n  `twopi`, `circo`, `fdp`, `sfdp`, `patchwork`).\n- `doc/img/pp-graphviz-example` is the name of the image. `pp` will\n  generate `doc/img/pp-graphviz-example.dot` and\n  `doc/img/pp-graphviz-example.png`.\n- the rest of the first line is the legend of the graph.\n- other lines are written to `doc/img/pp-graphviz-example.dot` before\n  running [Graphviz](http://graphviz.org/).\n- if the command line argument `-img=prefix`, `prefix` is added at the\n  beginning of the image path.\n\nOnce generated the graph looks like:\n\n![This is just a GraphViz diagram\nexample](doc/img/pp-graphviz-example.svg)\n\n[GraphViz](http://graphviz.org/) must be installed.\n\n### PlantUML\n\n[PlantUML](http://plantuml.sourceforge.net/) is executed when the\nkeyword `uml` is used. The lines `@startuml` and `@enduml` required by\n[PlantUML](http://plantuml.sourceforge.net/) are added by `pp`.\n\n    !uml(pp-plantuml-example)(This is just a PlantUML diagram example)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    Alice -\u003e Bob: Authentication Request\n    Bob --\u003e Alice: Authentication Response\n    Alice -\u003e Bob: Another authentication Request\n    Alice \u003c-- Bob: another authentication Response\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce generated the graph looks like:\n\n![This is just a PlantUML diagram\nexample](doc/img/pp-plantuml-example.svg)\n\n[PlantUML](http://plantuml.sourceforge.net) is written in Java and is\nembedded in `pp`. Java must be installed.\n\n### Ditaa\n\n[ditaa](http://ditaa.sourceforge.net/) is executed when the keyword\n`ditaa` is used.\n\n    !ditaa(pp-ditaa-example)(This is just a Ditaa diagram example)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n        +--------+   +-------+    +-------+\n        |        | --+ ditaa +--\u003e |       |\n        |  Text  |   +-------+    |diagram|\n        |Document|   |!magic!|    |       |\n        |     {d}|   |       |    |       |\n        +---+----+   +-------+    +-------+\n            :                         ^\n            |       Lots of work      |\n            +-------------------------+\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce generated the graph looks like:\n\n![This is just a Ditaa diagram example](doc/img/pp-ditaa-example.svg)\n\n[ditaa](http://plantuml.sourceforge.net) is written in Java and is\nembedded in `pp`. Java must be installed.\n\n### BlockDiag\n\n[blockdiag](http://blockdiag.com/) is executed when one of these\nkeywords is used: `blockdiag`, `seqdiag`, `actdiag`, `nwdiag`,\n`rackdiag`, `packetdiag`\n\n    !blockdiag(pp-blockdiag-example)(This is just a blockdiag diagram example)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n        A -\u003e B -\u003e C -\u003e D\n        A -\u003e E -\u003e F -\u003e D\n        F -\u003e F\n        D -\u003e A\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce generated the graph looks like:\n\n![This is just a blockdiag diagram\nexample](doc/img/pp-blockdiag-example.svg)\n\n[blockdiag](http://blockdiag.com/) (`blockdiag`, `seqdiag`, `actdiag`\nand `nwdiag`) must be installed.\n\n### Asymptote\n\n[Asymptote](http://asymptote.sourceforge.net/) is executed when the\nkeyword `asy` is used.\n\n    !asy(pp-asy-example)\n        (This is just an Asymptote example from \u003chttp://asy.marris.fr/asymptote/Sciences_physiques/index.html\u003e)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    import geometry;\n    size(7.5cm,0);\n\n    // Affichage du repère par défaut (O,vec{i},vec_{j})\n    show(defaultcoordsys);\n\n    real a=5, b=4, theta=-27, poids=3;\n    ellipse el = ellipse(origin, a, b);\n    arc     ar = arc(el,(0,-b),(a,0),CCW);\n    path p = (0,-b-1)--ar--(a+1,0)--(a+1,-b-1)--cycle;\n    point pO = (0,0), pM=angpoint(ar,90+theta);\n    abscissa abscM = nodabscissa(el,pM);\n    real     timeM = abscM.x;\n    vector utangM = -dir(el,timeM),\n        unormM = rotate(90)*utangM,\n        vpoids=(0,-poids),\n        vreactionN = -dot(vpoids,unormM)*unormM,\n        vfrottement = -dot(vpoids,utangM)*utangM;\n\n    filldraw(p,lightgray,blue);\n    draw(pO--pM,dashed);\n    markangle(\"$\\theta$\",1.5cm,pM,origin,(1,0));\n\n    // Affichage d'un nouveau repère (M,vec{u_{\\theta}},vec_{u_{r}})\n    coordsys R=cartesiansystem(pM,i=utangM,j=unormM);\n    show(\"$M$\", \"$\\vec{u_{\\theta}}$\", \"$\\vec{u_{r}}$\", R, xpen=invisible);\n\n    // Affichage des trois vecteurs dans le repère R\n    point RpM=changecoordsys(R, pM);\n    show(Label(\"$\\vec{f}$\",EndPoint),RpM+vfrottement);\n    show(Label(\"$\\vec{R}$\",EndPoint),RpM+vreactionN);\n    show(Label(\"$\\vec{P}$\",EndPoint),RpM+vpoids);\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce generated the figure looks like:\n\n\u003cfigure\u003e\n\u003cimg src=\"doc/img/pp-asy-example.svg\" style=\"width:50.0%\"\nalt=\"This is just an Asymptote example from http://asy.marris.fr/asymptote/Sciences_physiques/index.html\" /\u003e\n\u003cfigcaption aria-hidden=\"true\"\u003eThis is just an Asymptote example from \u003ca\nhref=\"http://asy.marris.fr/asymptote/Sciences_physiques/index.html\"\nclass=\"uri\"\u003ehttp://asy.marris.fr/asymptote/Sciences_physiques/index.html\u003c/a\u003e\u003c/figcaption\u003e\n\u003c/figure\u003e\n\n**Note**: Asymptote handles transparency in PDF format only, which is\nconverted to PNG by `pp`. If you need transparency, you must use the\n`.png` or `pdf` format (PNG images are generated by converting the PDF\noutput of Asymptote). If you need scalable images, you must use the\n`.svg` format, which is the default format for Asymptote diagrams.\n\n### R (plot)\n\n[R](https://www.r-project.org/) is executed when the keyword `Rplot` is\nused.\n\n    !Rplot(rplot-test)(This is just an R plot example)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    plot(pressure)\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nOnce generated the image looks like:\n\n![This is just an R plot example](doc/img/rplot-test.svg)\n\n### Bash\n\n[Bash](https://www.gnu.org/software/bash/) is executed when the keyword\n`bash` is used.\n\n    !bash\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    echo \"Hi, I'm $SHELL $BASH_VERSION\"\n    RANDOM=42 # seed\n    echo \"Here are a few random numbers: $RANDOM, $RANDOM, $RANDOM\"\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis script outputs:\n\n    Hi, I'm bash 5.2.15(1)-release\n    Here are a few random numbers: 17772, 26794, 1435\n\n**Note**: the keyword `sh` executes `sh` which is generally a link to\n`bash`.\n\n### Cmd\n\nWindows’ [command-line\ninterpreter](https://en.wikipedia.org/wiki/Cmd.exe) is executed when the\nkeyword `cmd` is used.\n\n    !cmd\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    echo Hi, I'm %COMSPEC%\n    ver\n    if \"%WINELOADER%%WINELOADERNOEXEC%%WINEDEBUG%\" == \"\" (\n        echo This script is run from wine under Linux\n    ) else (\n        echo This script is run from a real Windows\n    )\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis script outputs:\n\n    Hi, I'm C:\\windows\\system32\\cmd.exe\n\n    Microsoft Windows 6.1.7601\n    This script is run from wine under Linux\n\n### Python\n\n[Python](https://www.python.org/) is executed when the keyword `python`\nis used.\n\n    !python\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    import sys\n    import random\n\n    if __name__ == \"__main__\":\n        print(\"Hi, I'm Python %s\"%sys.version)\n        random.seed(42)\n        randoms = [random.randint(0, 1000) for i in range(3)]\n        print(\"Here are a few random numbers: %s\"%(\", \".join(map(str, randoms))))\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis script outputs:\n\n    Hi, I'm Python 3.11.1 (main, Dec  7 2022, 00:00:00) [GCC 12.2.1 20221121 (Red Hat 12.2.1-4)]\n    Here are a few random numbers: 654, 114, 25\n\n### Lua\n\n[Lua](http://www.lua.org/) is executed when the keyword `lua` is used.\n\n    !lua\n    ~~~~~\n    print(\"Hi, I'm \".._VERSION)\n    math.randomseed(42)\n    t = {}\n    for i = 1, 3 do table.insert(t, math.random(0, 999)) end\n    print(\"Here are a few random numbers: \"..table.concat(t, \", \"))\n    ~~~~~\n\nThis script outputs:\n\n    Hi, I'm Lua 5.4\n    Here are a few random numbers: 741, 49, 331\n\n### Haskell\n\n[Haskell](https://www.haskell.org/) is executed when the keyword\n`haskell` is used.\n\n    !haskell\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    import System.Info\n    import Data.Version\n    import Data.List\n\n    primes = filterPrime [2..]\n        where filterPrime (p:xs) =\n                p : filterPrime [x | x \u003c- xs, x `mod` p /= 0]\n\n    version = showVersion compilerVersion\n\n    main = do\n        putStrLn $ \"Hi, I'm Haskell \" ++ version\n        putStrLn $ \"The first 10 prime numbers are: \" ++\n                    intercalate \" \" (map show (take 10 primes))\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis script outputs:\n\n    Hi, I'm Haskell 9.2\n    The first 10 prime numbers are: 2 3 5 7 11 13 17 19 23 29\n\n### Stack\n\n[Haskell](https://www.haskell.org/) is also executed when the keyword\n`stack` is used. In this case stack meta data must be added at the\nbeginning of the script.\n\n    !stack\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    {- stack script --resolver lts-20.6 --package base -}\n\n    import System.Info\n    import Data.Version\n    import Data.List\n\n    primes = filterPrime [2..]\n        where filterPrime (p:xs) =\n                p : filterPrime [x | x \u003c- xs, x `mod` p /= 0]\n\n    version = showVersion compilerVersion\n\n    main = do\n        putStrLn $ \"Hi, I'm Haskell \" ++ version\n        putStrLn $ \"The first 10 prime numbers are: \" ++\n                    intercalate \" \" (map show (take 10 primes))\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nThis script outputs:\n\n    Hi, I'm Haskell 9.2\n    The first 10 prime numbers are: 2 3 5 7 11 13 17 19 23 29\n\n### R (script)\n\n[R](https://www.r-project.org/) is executed when the keyword `Rscript`\nis used.\n\n    !Rscript\n    ~~~~~\n    model = lm(dist~speed, data = cars)\n    summary(model)\n    ~~~~~\n\nThis script outputs:\n\n\n    Call:\n    lm(formula = dist ~ speed, data = cars)\n\n    Residuals:\n        Min      1Q  Median      3Q     Max \n    -29.069  -9.525  -2.272   9.215  43.201 \n\n    Coefficients:\n                Estimate Std. Error t value Pr(\u003e|t|)    \n    (Intercept) -17.5791     6.7584  -2.601   0.0123 *  \n    speed         3.9324     0.4155   9.464 1.49e-12 ***\n    ---\n    Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1\n\n    Residual standard error: 15.38 on 48 degrees of freedom\n    Multiple R-squared:  0.6511,    Adjusted R-squared:  0.6438 \n    F-statistic: 89.57 on 1 and 48 DF,  p-value: 1.49e-12\n\n# Mustache templates\n\n`pp` uses a builtin Haskell\n[Mustache](https://github.com/JustusAdam/mustache) implementation that\nreads JSON or YAML files and generates text from a Mustache template.\n\n[Mustache](https://github.com/JustusAdam/mustache) is executed when the\nkeyword `mustache` is used.\n\n    !mustache(../package.yaml)\n    ```````````````````````````````````````\n    This is the documentation for `{{name}}` version {{version}} by {{author}}.\n    Copyright !bold({{copyright}}).\n    ```````````````````````````````````````\n\n`package.yaml` contains:\n\n    name:                pp\n    version:             \"2.14.4\"\n    github:              \"CDSoft/pp\"\n    license:             GPL-3\n    author:              \"Christophe Delord\"\n    maintainer:          \"cdelord.fr\"\n    copyright:           \"2015-2023 Christophe Delord\"\n\nLambdas are not supported but the template is preprocessed by `pp`\nbefore calling Mustache. E.g. `!bold` can be defined as\n`!def(bold)(**!1**)`. These “*lambda macros*” can be defined in the\nYAML/JSON data file as well, which is a non standard way to define\nMustache lambdas that works with `pp` only.\n\nThis outputs:\n\n    This is the documentation for `pp` version 2.14.4 by Christophe Delord.\n    Copyright **2015-2023 Christophe Delord**.\n\n# CSV tables\n\nCSV files can be included in documents and rendered as Markdown or\nreStructuredText tables. The field separator is inferred from the\ncontent of the file. It can be a comma, a semicolon, tabulation or a\npipe.\n\n## Files with a header line\n\nThis file:\n\n    Year,Make,Model,Description,Price\n    1997,Ford,E350,\"ac, abs, moon\",3000.00\n    1999,Chevy,\"Venture \"\"Extended Edition\"\"\",\"\",4900.00\n    1999,Chevy,\"Venture \"\"Extended Edition, Very Large\"\"\",,5000.00\n    1996,Jeep,Grand Cherokee,\"MUST SELL!\n    air, moon roof, loaded\",4799.00\n\nis rendered by `!csv(file.csv)` as:\n\n| Year | Make  | Model                                  | Description                       |   Price |\n|-----:|:------|:---------------------------------------|:----------------------------------|--------:|\n| 1997 | Ford  | E350                                   | ac, abs, moon                     | 3000.00 |\n| 1999 | Chevy | Venture “Extended Edition”             |                                   | 4900.00 |\n| 1999 | Chevy | Venture “Extended Edition, Very Large” |                                   | 5000.00 |\n| 1996 | Jeep  | Grand Cherokee                         | MUST SELL! air, moon roof, loaded | 4799.00 |\n\n## Files without any header line\n\nThis file:\n\n    1997,Ford,E350,\"ac, abs, moon\",3000.00\n    1999,Chevy,\"Venture \"\"Extended Edition\"\"\",\"\",4900.00\n    1999,Chevy,\"Venture \"\"Extended Edition, Very Large\"\"\",,5000.00\n    1996,Jeep,Grand Cherokee,\"MUST SELL!\n    air, moon roof, loaded\",4799.00\n\nis rendered by `!csv(file.csv)(Year|Make|Model|Description|Price)` as:\n\n| Year | Make  | Model                                  | Description                       |   Price |\n|-----:|:------|:---------------------------------------|:----------------------------------|--------:|\n| 1997 | Ford  | E350                                   | ac, abs, moon                     | 3000.00 |\n| 1999 | Chevy | Venture “Extended Edition”             |                                   | 4900.00 |\n| 1999 | Chevy | Venture “Extended Edition, Very Large” |                                   | 5000.00 |\n| 1996 | Jeep  | Grand Cherokee                         | MUST SELL! air, moon roof, loaded | 4799.00 |\n\n# OS support\n\nPP is meant to be portable and multi platform. To be OS agnostic, the\nuse of free script languages is strongly recommended. For instance, bash\nscripts are preferred to proprietary closed languages because they can\nrun on any platform. It is standard on Linux and pretty well supported\non Windows (Cygwin, MSYS/Mingw, Git Bash, BusyBox, …). Python is also a\ngood choice.\n\nAnyway, if some documents require portability and specific tools, PP\nprovides some macros to detect the OS (`!os`, `!arch`). E.g.:\n\n    !quiet\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n    !ifeq(!os)(linux)\n    `````````````````````\n    !def(linux)(!1)\n    !def(win)()\n    `````````````````````\n    !ifeq(!os)(windows)\n    `````````````````````\n    !def(linux)()\n    !def(win)(!1)\n    `````````````````````\n    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n    !win(Sorry, you're running Windows)\n    !linux(Hello, happy GNU/Linux user)\n\nThe `!exec` macro is also OS aware. It runs the *default* shell\naccording to the OS (`sh` on Linux and MacOS, `cmd` on Windows).\n\n# Tests\n\n`make test` will test most of pp capabilities. They have been designed\nto run on Linux and require a bunch of softwares:\n\n- a decent Linux distribution\n- [Stack](https://docs.haskellstack.org/en/stable/README/)\n- [Pandoc](http://pandoc.org/)\n- [Meld](https://meldmerge.org/)\n- [Bash](https://www.gnu.org/software/bash/),\n  [zsh](http://www.zsh.org/), [fish](https://fishshell.com/)\n- [Wine](https://www.winehq.org/)\n- [Python](https://www.python.org/)\n- [Lua](http://www.lua.org/)\n- [GraphViz](http://graphviz.org/)\n- [Asymptote](http://asymptote.sourceforge.net/)\n- [R](https://www.r-project.org/)\n- [Haskell](https://www.haskell.org/)\n- [blockdiag](http://blockdiag.com/)\n- [gcc](https://gcc.gnu.org/)\n- … and everything I have forgotten\n\n*note*: blockdiag is written in Python. According to your Python\nversion, scripts may or may not be suffixed by `2` or `3`. In this case,\nyou may have to add appropriate links:\n\n\u003e ``` sh\n\u003e sudo ln -vs /usr/bin/blockdiag3 /usr/bin/blockdiag\n\u003e sudo ln -vs /usr/bin/seqdiag3 /usr/bin/seqdiag\n\u003e sudo ln -vs /usr/bin/actdiag3 /usr/bin/actdiag\n\u003e sudo ln -vs /usr/bin/nwdiag3 /usr/bin/nwdiag\n\u003e sudo ln -vs /usr/bin/rackdiag3 /usr/bin/rackdiag\n\u003e sudo ln -vs /usr/bin/packetdiag3 /usr/bin/packetdiag\n\u003e ```\n\nSome tests may fail if the script interpreters’ versions are different.\n`make ref` will open `meld` to show the differences and fix the expected\nresults.\n\n# Third-party documentations, tutorials and macros\n\n- [PP\n  tutorial](https://github.com/tajmone/markdown-guide/tree/master/pp) by\n  [tajmone](https://github.com/tajmone): a good starting point for\n  beginners.\n- [Pandoc-Goodies PP-Macros\n  Library](https://github.com/tajmone/pandoc-goodies/tree/master/pp) by\n  [tajmone](https://github.com/tajmone): an ongoing collaborative effort\n  to build a library of PP macros.\n\n# Licenses\n\n## PP\n\nCopyright (C) 2015-2023 Christophe Delord \u003cbr\u003e \u003chttp://cdelord.fr/pp\u003e\n\nPP is free software: you can redistribute it and/or modify it under the\nterms of the GNU General Public License as published by the Free\nSoftware Foundation, either version 3 of the License, or (at your\noption) any later version.\n\nPP is distributed in the hope that it will be useful, but WITHOUT ANY\nWARRANTY; without even the implied warranty of MERCHANTABILITY or\nFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for\nmore details.\n\nYou should have received a copy of the GNU General Public License along\nwith PP. If not, see \u003chttp://www.gnu.org/licenses/\u003e.\n\n## PlantUML\n\nPlantUML.jar is integrated in\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\").\n[PlantUML](http://plantuml.sourceforge.net/) is distributed under the\n[GPL license](http://www.gnu.org/copyleft/gpl.html). See\n\u003chttp://plantuml.sourceforge.net/faq.html\u003e.\n\nThe current version of [PlantUML](http://plantuml.sourceforge.net/)\nembedded in\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\") is:\n\n![](doc/img/PP-plantuml-version.svg)\n\n## ditaa\n\nditaa.jar is integrated in\n[PP](http://cdelord.fr/pp \"PP - Generic Preprocessor (for Pandoc)\").\n[ditaa](http://ditaa.sourceforge.net/) is distributed under the [GNU\nGeneral Public License version 2.0\n(GPLv2)](http://sourceforge.net/directory/license:gpl/). See\n\u003chttp://sourceforge.net/projects/ditaa/\u003e.\n\n# Feedback\n\nYour feedback and contributions are welcome. You can contact me at\n\u003chttp://cdelord.fr\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCDSoft%2Fpp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FCDSoft%2Fpp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FCDSoft%2Fpp/lists"}