diff --git a/include-code-files/Makefile b/include-code-files/Makefile new file mode 100644 index 00000000..6b169e09 --- /dev/null +++ b/include-code-files/Makefile @@ -0,0 +1,10 @@ +DIFF ?= diff --strip-trailing-cr -u + +test: sample.md include-code-files.lua + @pandoc --lua-filter=include-code-files.lua --to=native $< \ + | $(DIFF) expected.native - + +expected.native: sample.md include-code-files.lua + pandoc --lua-filter=include-code-files.lua --output $@ $< + +.PHONY: test diff --git a/include-code-files/README.md b/include-code-files/README.md new file mode 100644 index 00000000..e52ef279 --- /dev/null +++ b/include-code-files/README.md @@ -0,0 +1,54 @@ +# include-code-files + +Filter to include code from source files. + +The filter is largely inspired by [pandoc-include-code](https://github.com/owickstrom/pandoc-include-code). + +## Usage + +The filter recognizes code blocks with the `include` attribute present. It +swaps the content of the code block with contents from a file. + +### Including Files + +The simplest way to use this filter is to include an entire file: + + ```{include="hello.c"} + ``` + +You can still use other attributes, and classes, to control the code blocks: + + ```{.c include="hello.c" numberLines} + ``` + +### Ranges + +If you want to include a specific range of lines, use `startLine` and `endLine`: + + ```{include="hello.c" startLine=35 endLine=80} + ``` + +### Dedent + +Using the `dedent` attribute, you can have whitespaces removed on each line, +where possible (non-whitespace character will not be removed even if they occur +in the dedent area). + + ```{include="hello.c" dedent=4} + ``` + +### Line Numbers + +If you include the `numberLines` class in your code block, and use `include`, +the `startFrom` attribute will be added with respect to the included code's +location in the source file. + + ```{include="hello.c" startLine=35 endLine=80 .numberLines} + ``` + +## Example + +An HTML can be produced with this command: + + pandoc --lua-filter=include-code-files.lua sample.md --output result.html + diff --git a/include-code-files/expected.native b/include-code-files/expected.native new file mode 100644 index 00000000..18e4aca1 --- /dev/null +++ b/include-code-files/expected.native @@ -0,0 +1,8 @@ +[Header 1 ("inclusion",[],[]) [Str "Inclusion"] +,CodeBlock ("",["lua","numberLines"],[]) "--- include-code-files.lua \8211 filter to include code from source files\n---\n--- Copyright: \169 2020 Bruno BEAUFILS\n--- License: MIT \8211 see LICENSE file for details\n\n--- Dedent a line\nlocal function dedent (line, n)\n return line:sub(1,n):gsub(\" \",\"\") .. line:sub(n+1)\nend\n\n--- Filter function for code blocks\nlocal function transclude (cb)\n if cb.attributes.include then\n local content = \"\"\n local fh = io.open(cb.attributes.include)\n if not fh then\n io.stderr:write(\"Cannot open file \" .. cb.attributes.include .. \" | Skipping includes\\n\")\n else\n local number = 1\n local start = 1\n if cb.attributes.startLine then\n cb.attributes.startFrom = cb.attributes.startLine\n start = tonumber(cb.attributes.startLine)\n end\n for line in fh:lines (\"L\")\n do\n if cb.attributes.dedent then\n line = dedent(line, cb.attributes.dedent)\n end\n if number >= start then\n if not cb.attributes.endLine or number <= tonumber(cb.attributes.endLine) then\n content = content .. line\n end\n end\n number = number + 1\n end \n fh:close()\n end \n -- remove key-value pair for used keys\n cb.attributes.include = nil\n cb.attributes.startLine = nil\n cb.attributes.endLine = nil\n cb.attributes.dedent = nil\n -- return final code block\n return pandoc.CodeBlock(content, cb.attr)\n end\nend\n\nreturn {\n { CodeBlock = transclude }\n}\n" +,Header 1 ("ranges",[],[]) [Str "Ranges"] +,CodeBlock ("",["lua","numberLines"],[("startFrom","7")]) "local function dedent (line, n)\n return line:sub(1,n):gsub(\" \",\"\") .. line:sub(n+1)\nend\n" +,Header 1 ("detent",[],[]) [Str "Detent"] +,Para [Code ("",[],[]) "detent",Space,Str "removes",Space,Str "specified",Space,Str "number",Space,Str "of",Space,Str "whitespaces",Space,Str "(and",Space,Str "only",SoftBreak,Str "whitespaces)",Space,Str "from",Space,Str "beginning",Space,Str "of",Space,Str "each",Space,Str "line"] +,CodeBlock ("",["lua","bash","numberLines"],[("startFrom","8")]) "return line:sub(1,n):gsub(\" \",\"\") .. line:sub(n+1)\n" +,CodeBlock ("",["lua","numberLines"],[("startFrom","50")]) "{CodeBlock = transclude }\n"] diff --git a/include-code-files/include-code-files.lua b/include-code-files/include-code-files.lua new file mode 100644 index 00000000..df744bf7 --- /dev/null +++ b/include-code-files/include-code-files.lua @@ -0,0 +1,51 @@ +--- include-code-files.lua – filter to include code from source files +--- +--- Copyright: © 2020 Bruno BEAUFILS +--- License: MIT – see LICENSE file for details + +--- Dedent a line +local function dedent (line, n) + return line:sub(1,n):gsub(" ","") .. line:sub(n+1) +end + +--- Filter function for code blocks +local function transclude (cb) + if cb.attributes.include then + local content = "" + local fh = io.open(cb.attributes.include) + if not fh then + io.stderr:write("Cannot open file " .. cb.attributes.include .. " | Skipping includes\n") + else + local number = 1 + local start = 1 + if cb.attributes.startLine then + cb.attributes.startFrom = cb.attributes.startLine + start = tonumber(cb.attributes.startLine) + end + for line in fh:lines ("L") + do + if cb.attributes.dedent then + line = dedent(line, cb.attributes.dedent) + end + if number >= start then + if not cb.attributes.endLine or number <= tonumber(cb.attributes.endLine) then + content = content .. line + end + end + number = number + 1 + end + fh:close() + end + -- remove key-value pair for used keys + cb.attributes.include = nil + cb.attributes.startLine = nil + cb.attributes.endLine = nil + cb.attributes.dedent = nil + -- return final code block + return pandoc.CodeBlock(content, cb.attr) + end +end + +return { + { CodeBlock = transclude } +} diff --git a/include-code-files/sample.md b/include-code-files/sample.md new file mode 100644 index 00000000..a929adde --- /dev/null +++ b/include-code-files/sample.md @@ -0,0 +1,26 @@ +--- +author: me +title: Including Hello World +--- + +# Inclusion + +``` {include="include-code-files.lua" .lua .numberLines} +``` + +# Ranges + +``` {include="include-code-files.lua" .lua startLine=7 endLine=9 .numberLines} +``` + +# Detent + +`detent` removes specified number of whitespaces (and only +whitespaces) from beginning of each line + +``` {include="include-code-files.lua" .lua startLine=8 endLine=8 dedent=4 .bash .numberLines} +``` + +``` {include="include-code-files.lua" .lua startLine=50 endLine=50 dedent=5 .numberLines} +``` +