4Copyright © 2017–2018 Albert Krewinkel
6Permission to use, copy, modify, and/or distribute this software for any purpose
7with or without fee is hereby granted, provided that the above copyright notice
8and this permission notice appear in all copies.
10THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
12FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
14OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
20-- Lua functions for pandoc scripts.
22-- @author Albert Krewinkel
23-- @copyright © 2017–2018 Albert Krewinkel
27local List = require 'pandoc.List'
29------------------------------------------------------------------------
32-- Create metatables which allow to access numerical indices via accessor
37--- Create a new indexing function.
38-- @param template function template
39-- @param indices list of indices, starting with the most deeply nested
40-- @return newly created function
42function make_indexing_function(template, indices)
43 local loadstring = loadstring or load
45 for i = 1, #indices do
46 bracketed[i] = string.format('[%d]', indices[#indices - i + 1])
48 local fnstr = string.format('return ' .. template, table.concat(bracketed))
49 return assert(loadstring(fnstr))()
52--- Create accessor functions using a function template.
53-- @param fn_template function template in which '%s' is replacd with indices
54-- @param accessors list of accessors
55-- @return mapping from accessor names to accessor functions
57local function create_accessor_functions (fn_template, accessors)
59 function add_accessors(acc, ...)
60 if type(acc) == 'string' then
61 res[acc] = make_indexing_function(fn_template, {...})
62 elseif type(acc) == 'table' and #acc == 0 and next(acc) then
63 local name, substructure = next(acc)
64 res[name] = make_indexing_function(fn_template, {...})
65 add_accessors(substructure, ...)
67 for i = 1, #(acc or {}) do
68 add_accessors(acc[i], i, ...)
72 add_accessors(accessors)
76--- Get list of top-level fields from field descriptor table.
77-- E.g.: `top_level_fields{'foo', {bar='baz'}, {'qux', 'quux'}}`
78-- gives {'foo, 'bar', 'qux', 'quux'}
80local function top_level_fields (fields)
81 local result = List:new{}
82 for _, v in ipairs(fields) do
83 if type(v) == 'string' then
84 table.insert(result, v)
85 elseif type(v) == 'table' and #v == 0 and next(v) then
86 table.insert(result, (next(v)))
88 result:extend(top_level_fields(v))
94--- Creates a function which behaves like next, but respects field names.
96local function make_next_function (fields)
97 local field_indices = {}
98 for i, f in ipairs(fields) do
102 return function (t, field)
103 local raw_idx = field == nil and 0 or field_indices[field]
104 local next_field = fields[raw_idx + 1]
105 return next_field, t[next_field]
109--- Create a new table which allows to access numerical indices via accessor
112local function create_accessor_behavior (tag, accessors)
113 local behavior = {tag = tag}
114 behavior.getters = create_accessor_functions(
115 'function (x) return x.c%s end',
118 behavior.setters = create_accessor_functions(
119 'function (x, v) x.c%s = v end',
122 behavior.__index = function(t, k)
123 if getmetatable(t).getters[k] then
124 return getmetatable(t).getters[k](t)
126 return getmetatable(t)["tag"]
128 return getmetatable(t)[k]
131 behavior.__newindex = function(t, k, v)
132 if getmetatable(t).setters[k] then
133 getmetatable(t).setters[k](t, v)
138 behavior.__pairs = function (t)
139 if accessors == nil then
142 local iterable_fields = type(accessors) == 'string'
144 or top_level_fields(accessors)
145 return make_next_function(iterable_fields), t
151------------------------------------------------------------------------
152-- The base class for types
162 setmetatable(obj, self)
166Type.behavior.__index = Type.behavior
168--- Set a new behavior for the type, inheriting that of the parent type if none
169--- is specified explicitly
170-- @param behavior the behavior object for this type.
172function Type:set_behavior (behavior)
173 behavior = behavior or {}
174 behavior.__index = rawget(behavior, '__index') or behavior
175 behavior.__type = self
176 if not getmetatable(behavior) and getmetatable(self) then
177 setmetatable(behavior, getmetatable(self).behavior)
179 self.behavior = behavior
182--- Create a new subtype, using the given table as base.
183-- @param name name of the new type
184-- @param[opt] behavior behavioral object for the new type.
187function Type:make_subtype(name, behavior)
188 local newtype = setmetatable({}, self)
190 newtype.__index = newtype
191 newtype:set_behavior(behavior)
196------------------------------------------------------------------------
197-- The base class for pandoc's AST elements.
200local AstElement = Type:make_subtype 'AstElement'
201AstElement.__call = function(t, ...)
202 local success, ret = pcall(t.new, t, ...)
204 return setmetatable(ret, t.behavior)
206 error(string.format('Constructor for %s failed: %s\n', t.name, ret))
210--- Make a new subtype which constructs a new value when called.
212function AstElement:make_subtype(...)
213 local newtype = Type.make_subtype(self, ...)
214 newtype.__call = self.__call
218--- Create a new constructor
220-- @param tag Tag used to identify the constructor
221-- @param fn Function to be called when constructing a new element
222-- @param accessors names to use as accessors for numerical fields
223-- @return function that constructs a new element
224function AstElement:create_constructor(tag, fn, accessors)
225 local constr = self:make_subtype(tag, create_accessor_behavior(tag, accessors))
226 function constr:new(...)
227 return setmetatable(fn(...), self.behavior)
229 self.constructor = self.constructor or {}
230 self.constructor[tag] = constr
234--- Convert AstElement input into a list if necessary.
236local function ensureList (x)
238 -- Lists are not tagged, but all elements are
245--- Ensure a given object is an Inline element, or convert it into one.
247local function ensureInlineList (x)
248 if type(x) == 'string' then
249 return List:new{M.Str(x)}
255------------------------------------------------------------------------
259--- A complete pandoc document
261-- @tparam {Block,...} blocks document content
262-- @tparam[opt] Meta meta document meta data
263M.Pandoc = AstElement:make_subtype'Pandoc'
264function M.Pandoc:new (blocks, meta)
266 blocks = ensureList(blocks),
271-- DEPRECATED synonym:
274------------------------------------------------------------------------
278--- Create a new Meta object. It sets the metatable of the given table to
281-- @tparam meta table table containing document meta information
282M.Meta = AstElement:make_subtype'Meta'
283function M.Meta:new (meta) return meta end
286------------------------------------------------------------------------
289M.MetaValue = AstElement:make_subtype('MetaValue')
292-- @function MetaBlocks
293-- @tparam {Block,...} blocks blocks
294M.MetaBlocks = M.MetaValue:create_constructor(
296 function (content) return ensureList(content) end
300-- @function MetaInlines
301-- @tparam {Inline,...} inlines inlines
302M.MetaInlines = M.MetaValue:create_constructor(
304 function (content) return ensureInlineList(content) end
309-- @tparam {MetaValue,...} meta_values list of meta values
310M.MetaList = M.MetaValue:create_constructor(
313 if content.tag == 'MetaList' then
316 return ensureList(content)
319for k, v in pairs(List) do
320 M.MetaList.behavior[k] = v
325-- @tparam table key_value_map a string-indexed map of meta values
326M.MetaMap = M.MetaValue:create_constructor(
328 function (mm) return mm end
331--- Creates string to be used in meta data.
332-- Does nothing, lua strings are meta strings.
333-- @function MetaString
334-- @tparam string str string value
335function M.MetaString(str)
339--- Creates boolean to be used in meta data.
340-- Does nothing, lua booleans are meta booleans.
342-- @tparam boolean bool boolean value
343function M.MetaBool(bool)
347------------------------------------------------------------------------
352M.Block = AstElement:make_subtype'Block'
354--- Creates a block quote element
355-- @function BlockQuote
356-- @tparam {Block,...} content block content
357-- @treturn Block block quote element
358M.BlockQuote = M.Block:create_constructor(
360 function(content) return {c = ensureList(content)} end,
364--- Creates a bullet (i.e. unordered) list.
365-- @function BulletList
366-- @tparam {{Block,...},...} content list of items
367-- @treturn Block bullet list element
368M.BulletList = M.Block:create_constructor(
370 function(content) return {c = ensureList(content)} end,
374--- Creates a code block element
375-- @function CodeBlock
376-- @tparam string text code string
377-- @tparam[opt] Attr attr element attributes
378-- @treturn Block code block element
379M.CodeBlock = M.Block:create_constructor(
381 function(text, attr) return {c = {attr or M.Attr(), text}} end,
382 {{attr = {"identifier", "classes", "attributes"}}, "text"}
385--- Creates a definition list, containing terms and their explanation.
386-- @function DefinitionList
387-- @tparam {{{Inline,...},{Block,...}},...} content list of items
388-- @treturn Block definition list element
389M.DefinitionList = M.Block:create_constructor(
391 function(content) return {c = ensureList(content)} end,
395--- Creates a div element
397-- @tparam {Block,...} content block content
398-- @tparam[opt] Attr attr element attributes
399-- @treturn Block div element
400M.Div = M.Block:create_constructor(
402 function(content, attr)
403 return {c = {attr or M.Attr(), ensureList(content)}}
405 {{attr = {"identifier", "classes", "attributes"}}, "content"}
408--- Creates a header element.
410-- @tparam int level header level
411-- @tparam {Inline,...} content inline content
412-- @tparam[opt] Attr attr element attributes
413-- @treturn Block header element
414M.Header = M.Block:create_constructor(
416 function(level, content, attr)
417 return {c = {level, attr or M.Attr(), ensureInlineList(content)}}
419 {"level", {attr = {"identifier", "classes", "attributes"}}, "content"}
422--- Creates a horizontal rule.
423-- @function HorizontalRule
424-- @treturn Block horizontal rule
425M.HorizontalRule = M.Block:create_constructor(
427 function() return {} end
430--- Creates a line block element.
431-- @function LineBlock
432-- @tparam {{Inline,...},...} content inline content
433-- @treturn Block line block element
434M.LineBlock = M.Block:create_constructor(
436 function(content) return {c = ensureList(content)} end,
440--- Creates a null element.
442-- @treturn Block null element
443M.Null = M.Block:create_constructor(
445 function() return {} end
448--- Creates an ordered list.
449-- @function OrderedList
450-- @tparam {{Block,...},...} items list items
451-- @param[opt] listAttributes list parameters
452-- @treturn Block ordered list element
453M.OrderedList = M.Block:create_constructor(
455 function(items, listAttributes)
456 listAttributes = listAttributes or M.ListAttributes()
457 return {c = {listAttributes, ensureList(items)}}
459 {{listAttributes = {"start", "style", "delimiter"}}, "content"}
462--- Creates a para element.
464-- @tparam {Inline,...} content inline content
465-- @treturn Block paragraph element
466M.Para = M.Block:create_constructor(
468 function(content) return {c = ensureInlineList(content)} end,
472--- Creates a plain element.
474-- @tparam {Inline,...} content inline content
475-- @treturn Block plain element
476M.Plain = M.Block:create_constructor(
478 function(content) return {c = ensureInlineList(content)} end,
482--- Creates a raw content block of the specified format.
484-- @tparam string format format of content
485-- @tparam string text string content
486-- @treturn Block raw block element
487M.RawBlock = M.Block:create_constructor(
489 function(format, text) return {c = {format, text}} end,
493--- Creates a table element.
495-- @tparam {Inline,...} caption table caption
496-- @tparam {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
497-- @tparam {int,...} widths column widths
498-- @tparam {Block,...} headers header row
499-- @tparam {{Block,...}} rows table rows
500-- @treturn Block table element
501M.Table = M.Block:create_constructor(
503 function(caption, aligns, widths, headers, rows)
506 ensureInlineList(caption),
514 {"caption", "aligns", "widths", "headers", "rows"}
518------------------------------------------------------------------------
522--- Inline element class
523M.Inline = AstElement:make_subtype'Inline'
525--- Creates a Cite inline element
527-- @tparam {Inline,...} content List of inlines
528-- @tparam {Citation,...} citations List of citations
529-- @treturn Inline citations element
530M.Cite = M.Inline:create_constructor(
532 function(content, citations)
533 return {c = {ensureList(citations), ensureInlineList(content)}}
535 {"citations", "content"}
538--- Creates a Code inline element
540-- @tparam string text code string
541-- @tparam[opt] Attr attr additional attributes
542-- @treturn Inline code element
543M.Code = M.Inline:create_constructor(
545 function(text, attr) return {c = {attr or M.Attr(), text}} end,
546 {{attr = {"identifier", "classes", "attributes"}}, "text"}
549--- Creates an inline element representing emphasised text.
551-- @tparam {Inline,..} content inline content
552-- @treturn Inline emphasis element
553M.Emph = M.Inline:create_constructor(
555 function(content) return {c = ensureInlineList(content)} end,
559--- Creates a Image inline element
561-- @tparam {Inline,..} caption text used to describe the image
562-- @tparam string src path to the image file
563-- @tparam[opt] string title brief image description
564-- @tparam[opt] Attr attr additional attributes
565-- @treturn Inline image element
566M.Image = M.Inline:create_constructor(
568 function(caption, src, title, attr)
570 attr = attr or M.Attr()
571 return {c = {attr, ensureInlineList(caption), {src, title}}}
573 {{attr = {"identifier", "classes", "attributes"}}, "caption", {"src", "title"}}
576--- Create a LineBreak inline element
577-- @function LineBreak
578-- @treturn Inline linebreak element
579M.LineBreak = M.Inline:create_constructor(
581 function() return {} end
584--- Creates a link inline element, usually a hyperlink.
586-- @tparam {Inline,..} content text for this link
587-- @tparam string target the link target
588-- @tparam[opt] string title brief link description
589-- @tparam[opt] Attr attr additional attributes
590-- @treturn Inline image element
591M.Link = M.Inline:create_constructor(
593 function(content, target, title, attr)
595 attr = attr or M.Attr()
596 return {c = {attr, ensureInlineList(content), {target, title}}}
598 {{attr = {"identifier", "classes", "attributes"}}, "content", {"target", "title"}}
601--- Creates a Math element, either inline or displayed.
603-- @tparam "InlineMath"|"DisplayMath" mathtype rendering specifier
604-- @tparam string text Math content
605-- @treturn Inline Math element
606M.Math = M.Inline:create_constructor(
608 function(mathtype, text)
609 return {c = {mathtype, text}}
613--- Creates a DisplayMath element (DEPRECATED).
614-- @function DisplayMath
615-- @tparam string text Math content
616-- @treturn Inline Math element
617M.DisplayMath = M.Inline:create_constructor(
619 function(text) return M.Math("DisplayMath", text) end,
622--- Creates an InlineMath inline element (DEPRECATED).
623-- @function InlineMath
624-- @tparam string text Math content
625-- @treturn Inline Math element
626M.InlineMath = M.Inline:create_constructor(
628 function(text) return M.Math("InlineMath", text) end,
632--- Creates a Note inline element
634-- @tparam {Block,...} content footnote block content
635M.Note = M.Inline:create_constructor(
637 function(content) return {c = ensureList(content)} end,
641--- Creates a Quoted inline element given the quote type and quoted content.
643-- @tparam "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used
644-- @tparam {Inline,..} content inline content
645-- @treturn Inline quoted element
646M.Quoted = M.Inline:create_constructor(
648 function(quotetype, content) return {c = {quotetype, ensureInlineList(content)}} end,
649 {"quotetype", "content"}
651--- Creates a single-quoted inline element (DEPRECATED).
652-- @function SingleQuoted
653-- @tparam {Inline,..} content inline content
654-- @treturn Inline quoted element
656M.SingleQuoted = M.Inline:create_constructor(
658 function(content) return M.Quoted(M.SingleQuote, content) end,
659 {"quotetype", "content"}
661--- Creates a single-quoted inline element (DEPRECATED).
662-- @function DoubleQuoted
663-- @tparam {Inline,..} content inline content
664-- @treturn Inline quoted element
666M.DoubleQuoted = M.Inline:create_constructor(
668 function(content) return M.Quoted("DoubleQuote", content) end,
669 {"quotetype", "content"}
672--- Creates a RawInline inline element
673-- @function RawInline
674-- @tparam string format format of the contents
675-- @tparam string text string content
676-- @treturn Inline raw inline element
677M.RawInline = M.Inline:create_constructor(
679 function(format, text) return {c = {format, text}} end,
683--- Creates text rendered in small caps
684-- @function SmallCaps
685-- @tparam {Inline,..} content inline content
686-- @treturn Inline smallcaps element
687M.SmallCaps = M.Inline:create_constructor(
689 function(content) return {c = ensureInlineList(content)} end,
693--- Creates a SoftBreak inline element.
694-- @function SoftBreak
695-- @treturn Inline softbreak element
696M.SoftBreak = M.Inline:create_constructor(
698 function() return {} end
701--- Create a Space inline element
703-- @treturn Inline space element
704M.Space = M.Inline:create_constructor(
706 function() return {} end
709--- Creates a Span inline element
711-- @tparam {Inline,..} content inline content
712-- @tparam[opt] Attr attr additional attributes
713-- @treturn Inline span element
714M.Span = M.Inline:create_constructor(
716 function(content, attr)
717 return {c = {attr or M.Attr(), ensureInlineList(content)}}
719 {{attr = {"identifier", "classes", "attributes"}}, "content"}
722--- Creates a Str inline element
724-- @tparam string text content
725-- @treturn Inline string element
726M.Str = M.Inline:create_constructor(
728 function(text) return {c = text} end,
732--- Creates text which is striked out.
733-- @function Strikeout
734-- @tparam {Inline,..} content inline content
735-- @treturn Inline strikeout element
736M.Strikeout = M.Inline:create_constructor(
738 function(content) return {c = ensureInlineList(content)} end,
742--- Creates a Strong element, whose text is usually displayed in a bold font.
744-- @tparam {Inline,..} content inline content
745-- @treturn Inline strong element
746M.Strong = M.Inline:create_constructor(
748 function(content) return {c = ensureInlineList(content)} end,
752--- Creates a Subscript inline element
753-- @function Subscript
754-- @tparam {Inline,..} content inline content
755-- @treturn Inline subscript element
756M.Subscript = M.Inline:create_constructor(
758 function(content) return {c = ensureInlineList(content)} end,
762--- Creates a Superscript inline element
763-- @function Superscript
764-- @tparam {Inline,..} content inline content
765-- @treturn Inline strong element
766M.Superscript = M.Inline:create_constructor(
768 function(content) return {c = ensureInlineList(content)} end,
773------------------------------------------------------------------------
775-- @section components
777--- Check if the first element of a pair matches the given value.
778-- @param x key value to be checked
779-- @return function returning true iff first element of its argument matches x
781local function assoc_key_equals (x)
782 return function (y) return y[1] == x end
785--- Lookup a value in an associative list
788-- @tparam {{key, value},...} alist associative list
789-- @param key key for which the associated value is to be looked up
790local function lookup(alist, key)
791 return (List.find_if(alist, assoc_key_equals(key)) or {})[2]
794--- Return an iterator which returns key-value pairs of an associative list.
797-- @tparam {{key, value},...} alist associative list
798local apairs = function (alist)
802 cur = rawget(alist, i)
805 return cur[1], cur[2]
812--- AttributeList, a metatable to allow table-like access to attribute lists
813-- represented by associative lists.
815local AttributeList = {
816 __index = function (t, k)
817 if type(k) == "number" then
824 __newindex = function (t, k, v)
825 local cur, idx = List.find_if(t, assoc_key_equals(k))
830 elseif type(k) == "number" then
833 rawset(t, #t + 1, {k, v})
840--- Convert a table to an associative list. The order of key-value pairs in the
841-- alist is undefined. The table should either contain no numeric keys or
842-- already be an associative list.
844-- @tparam table tbl associative list or table without numeric keys.
845-- @treturn table associative list
846local to_alist = function (tbl)
847 if #tbl ~= 0 or next(tbl) == nil then
848 -- probably already an alist
853 for k, v in pairs(tbl) do
862--- Create a new set of attributes (Attr).
864-- @tparam[opt] string identifier element identifier
865-- @tparam[opt] {string,...} classes element classes
866-- @tparam[opt] table attributes table containing string keys and values
867-- @return element attributes
868M.Attr = AstElement:make_subtype'Attr'
869function M.Attr:new (identifier, classes, attributes)
870 identifier = identifier or ''
871 classes = ensureList(classes or {})
872 attributes = setmetatable(to_alist(attributes or {}), AttributeList)
873 return {identifier, classes, attributes}
875M.Attr.behavior._field_names = {identifier = 1, classes = 2, attributes = 3}
876M.Attr.behavior.__index = function(t, k)
877 return rawget(t, getmetatable(t)._field_names[k]) or
880M.Attr.behavior.__newindex = function(t, k, v)
881 if getmetatable(t)._field_names[k] then
882 rawset(t, getmetatable(t)._field_names[k], v)
887M.Attr.behavior.__pairs = function(t)
888 local field_names = M.Attr.behavior._field_names
890 for name, i in pairs(field_names) do
893 return make_next_function(fields), t, nil
897M.Citation = AstElement:make_subtype'Citation'
899--- Creates a single citation.
901-- @tparam string id citation identifier (like a bibtex key)
902-- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
903-- @tparam[opt] {Inline,...} prefix citation prefix
904-- @tparam[opt] {Inline,...} suffix citation suffix
905-- @tparam[opt] int note_num note number
906-- @tparam[opt] int hash hash number
907function M.Citation:new (id, mode, prefix, suffix, note_num, hash)
911 prefix = ensureList(prefix or {}),
912 suffix = ensureList(suffix or {}),
913 note_num = note_num or 0,
919M.ListAttributes = AstElement:make_subtype 'ListAttributes'
921--- Creates a set of list attributes.
922-- @function ListAttributes
923-- @tparam[opt] integer start number of the first list item
924-- @tparam[opt] string style style used for list numbering
925-- @tparam[opt] DefaultDelim|Period|OneParen|TwoParens delimiter delimiter of list numbers
926-- @treturn table list attributes table
927function M.ListAttributes:new (start, style, delimiter)
929 style = style or 'DefaultStyle'
930 delimiter = delimiter or 'DefaultDelim'
931 return {start, style, delimiter}
933M.ListAttributes.behavior._field_names = {start = 1, style = 2, delimiter = 3}
934M.ListAttributes.behavior.__index = function (t, k)
935 return rawget(t, getmetatable(t)._field_names[k]) or
938M.ListAttributes.behavior.__newindex = function (t, k, v)
939 if getmetatable(t)._field_names[k] then
940 rawset(t, getmetatable(t)._field_names[k], v)
945M.ListAttributes.behavior.__pairs = function(t)
946 local field_names = M.ListAttributes.behavior._field_names
948 for name, i in pairs(field_names) do
951 return make_next_function(fields), t, nil
955------------------------------------------------------------------------
959--- Author name is mentioned in the text.
962M.AuthorInText = "AuthorInText"
964--- Author name is suppressed.
967M.SuppressAuthor = "SuppressAuthor"
969--- Default citation style is used.
972M.NormalCitation = "NormalCitation"
974--- Table cells aligned left.
976M.AlignLeft = "AlignLeft"
978--- Table cells right-aligned.
980M.AlignRight = "AlignRight"
982--- Table cell content is centered.
984M.AlignCenter = "AlignCenter"
986--- Table cells are alignment is unaltered.
988M.AlignDefault = "AlignDefault"
990--- Default list number delimiters are used.
992M.DefaultDelim = "DefaultDelim"
994--- List numbers are delimited by a period.
998--- List numbers are delimited by a single parenthesis.
1000M.OneParen = "OneParen"
1002--- List numbers are delimited by a double parentheses.
1004M.TwoParens = "TwoParens"
1006--- List are numbered in the default style
1008M.DefaultStyle = "DefaultStyle"
1010--- List items are numbered as examples.
1012M.Example = "Example"
1014--- List are numbered using decimal integers.
1016M.Decimal = "Decimal"
1018--- List are numbered using lower-case roman numerals.
1020M.LowerRoman = "LowerRoman"
1022--- List are numbered using upper-case roman numerals
1024M.UpperRoman = "UpperRoman"
1026--- List are numbered using lower-case alphabetic characters.
1028M.LowerAlpha = "LowerAlpha"
1030--- List are numbered using upper-case alphabetic characters.
1032M.UpperAlpha = "UpperAlpha"
1034------------------------------------------------------------------------
1035-- Functions which have moved to different modules
1036local utils = require 'pandoc.utils'
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list