Commands provide additional functionality to Markdown files. All commands use the same basic annotation syntax:
{{<name>}{<arg>}...}
There are two classes of commands:
The following substitution commands are supported:
Inside dedicated command arguments variables can be used.
The include command uses the following syntax
{{include}{<filepath>}[{[<startline>][:[<endline>]]}]}
{{include}{<filepath>}{<key>}}
this command included content from some file into the actual markdown file.
It additionally accepts some filtering a substitution options.
The execute command uses the following syntax
{{execute}{<command>}{<arg>}*}
{{execute}{<command>}{<arg>}*{<extract>}[{[<startline>][:[<endline>]]}]}
{{execute}{<command>}{<arg>}*{<extract>}{<key>}}
The command executes the given command with the given arguments and substitutes the output. Every command argument is given as separate argument to the mdref command. The directory of the file containing the command expression is used as current working directory to resolve relative file names.
Optionally the special argument {<extract>} can be used to append
some line selection arguments according to the include command, line range as well as pattern selection and the optional additional filter argument.
The command in directory democmd outputs some
test content:
this is a demo file
// --- begin text ---
some demo text
// --- end text ---
this is line 5 of the demo output
and some other text.
It can be completely substituted (as shown above) with the command
{{execute}{go}{run}{../../../democmd}{text}{some demo text}}
or you can select a dedicated line range with the filter pattern
{{execute}{go}{run}{../../../democmd}{text}{some demo text}{<extract>}{text}}
which produces the following output:
some demo text
A selection by a number range (here just a single line) is possible, also:
{{execute}{go}{run}{../../../democmd}{text}{some demo text}{<extract>}{5}}
substitutes line number 5
this is line 5 of the demo output
Both commands, [{{cmd-include}]] and execute accept an optional filter for the addressed content. Instead of just taking the complete content a subset of the lines is used.
...{[<startline>][:[<endline>]]}
In this first flavor numbering starts from 1, given start and end line are included. If omitted the selection starts from the beginning or is taken to the end.
The include command using this option can be used to embed some content of another file into the Markdown file, for example parts of a Go file to provide some documentation consistent with actual code like in the following example
{{include}{../../../patterns.go}{7:11}}
which extracts the regular expressions used to parse the annotations used by this tool.
var subExp = regexp.MustCompile(`{{{([*]?[A-Za-z][a-z0-9.-]+)}}}`)
var refExp = regexp.MustCompile(`\({{([a-z0-9.-]+)}}\)`)
var lnkExp = regexp.MustCompile(`\[{{([*]?[A-Za-z][a-z0-9.-]*)}}\]`)
var tgtExp = regexp.MustCompile(`{{([a-z][a-z0-9.-]*)(:([a-zA-Z][\p{L}\p{N}- ]+))?}}`)
var cmdExp = regexp.MustCompile(`{{([a-z]+)}((?:{[^}]*})+)}`)...{<key>}
The problem with line numbers is to keep source and include up-to-date. If the content changes the line numbers for the selection filter must be adapted.
In the second flavor the content between two lines containing the pattern
--- begin <key> --- and --- end <key> --- is used instead of using fixed line numbers.
Those pattern pairs MUST occur exactly once. This is more flexible but
requires to prepare the source, for example adding appropriate comments
into a source file.
Let's have a look again at the include command.
{{include}{../../../cmds.go}{include args}}
extracts the lines between the start and end pattern
// --- begin include args ---
var includeExpNum = regexp.MustCompile("^{([^}]+)}(?:{([0-9]+)?(?:(:)([0-9]+)?)?}(?:{([^}]+)}(?:{([^}]+)})?)?)?$")
var includeExpPat = regexp.MustCompile("^{([^}]+)}{([a-zA-Z][a-zA-Z0-9- ]*)}(?:{([^}]+)})?(?:{([^}]+)})?$")
// --- end include args ---
Depending on the kind of source an appropriate comment syntax can be used for this. In Java, Go, C or C++ this can then look like
// --- begin include args ---
...
/* --- end include args --- */Or in HTML or markdown it could be
<!--- begin something --->
...
<!--- end someting --->...{<line filter>}{<pattern>}It filters the selected line range by a regexp pattern.
An optional additional such filter argument can be used to specify a filter regular expression. The selected file range is matched by this regular expression and the matched content of the all matches is concatenated. If the expression uses the multi-line mode, the matches are suffixed with a newline. If the expression contains exactly one capturing group, the matched content for this group is taken.
For example, the previous paragraph is directly taken from a comment in the source file
cmds.go using this include command:
{{include}{../../../cmds.go}{filter}{(?m)^.*// *(.*)$}}
Even this is directly extracted from this markdown source just by surrounding the include command with a line selection filter key.
{{include}{commands.md}{filter}}
If some special character like { or } are required
in the regular expression, they must be encoded a HTML entities: for example
{: {}: }
There are some standard pattern defined as part of the mdref tool. Additional patterns can be defined with the pattern command.
By default, the result of a pattern selection is used, If a capturing group is defined the content of this group instead of the complete match is used. But there is also a possibility to compose the used content completely on capturing groups. If 1 or more groups are used and additional argument can be used to describe a substitution template. (for more than one group the template is required)
{<line selection>}{<regexp>}{<substitution template>}
In the template group variables can be used to refer to the content matched by a capturing group:
$<n>: capturing group<n>, where0describes the complete match.$<name>: name of named capturing group.$(<group>)group number or name$(<group>/<regexp>/<subst>): in the content of the described group the occurrences of the given regular expression are replaced by the given template. This template may again refer to capturing groups of the regular expression.
If sub-sequent arguments should be used without
a line filter it is possible to use {:} to select
all lines.
If a substitution command is idented, this indent is applied to line breaks in the substituted content, also.
-
for example, you can indent included text according a list indentation as shown in the example below
- for example, you can indent included text according a list indentation as shown in the example below ``` {{include}{commands.md}{indent}{(?s)(.*)}{$(1/\s````/ ```)}} ```
Note: It includes itself into the document. To handle the tripple tick correctly, the additional substitution is required.
With definition commands it is possible to define some settings valid for the complete processing.
The following definition commands are supported:
variableDefine variable values usable in command argumentspatternDefine standard pattern usable in substitution commands.termDefine Terms