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'
28local utils = require 'pandoc.utils'
30------------------------------------------------------------------------
33-- Create metatables which allow to access numerical indices via accessor
38--- Create a new indexing function.
39-- @param template function template
40-- @param indices list of indices, starting with the most deeply nested
41-- @return newly created function
43function make_indexing_function(template, indices)
44 local loadstring = loadstring or load
46 for i = 1, #indices do
47 bracketed[i] = string.format('[%d]', indices[#indices - i + 1])
49 local fnstr = string.format('return ' .. template, table.concat(bracketed))
50 return assert(loadstring(fnstr))()
53--- Create accessor functions using a function template.
54-- @param fn_template function template in which '%s' is replacd with indices
55-- @param accessors list of accessors
56-- @return mapping from accessor names to accessor functions
58local function create_accessor_functions (fn_template, accessors)
60 function add_accessors(acc, ...)
61 if type(acc) == 'string' then
62 res[acc] = make_indexing_function(fn_template, {...})
63 elseif type(acc) == 'table' and #acc == 0 and next(acc) then
64 local name, substructure = next(acc)
65 res[name] = make_indexing_function(fn_template, {...})
66 add_accessors(substructure, ...)
68 for i = 1, #(acc or {}) do
69 add_accessors(acc[i], i, ...)
73 add_accessors(accessors)
77--- Get list of top-level fields from field descriptor table.
78-- E.g.: `top_level_fields{'foo', {bar='baz'}, {'qux', 'quux'}}`
79-- gives {'foo, 'bar', 'qux', 'quux'}
81local function top_level_fields (fields)
82 local result = List:new{}
83 for _, v in ipairs(fields) do
84 if type(v) == 'string' then
85 table.insert(result, v)
86 elseif type(v) == 'table' and #v == 0 and next(v) then
87 table.insert(result, (next(v)))
89 result:extend(top_level_fields(v))
95--- Creates a function which behaves like next, but respects field names.
97local function make_next_function (fields)
98 local field_indices = {}
99 for i, f in ipairs(fields) do
103 return function (t, field)
104 local raw_idx = field == nil and 0 or field_indices[field]
105 local next_field = fields[raw_idx + 1]
106 return next_field, t[next_field]
110--- Create a new table which allows to access numerical indices via accessor
113local function create_accessor_behavior (tag, accessors)
114 local behavior = {tag = tag}
115 behavior.getters = create_accessor_functions(
116 'function (x) return x.c%s end',
119 behavior.setters = create_accessor_functions(
120 'function (x, v) x.c%s = v end',
123 behavior.__eq = utils.equals
124 behavior.__index = function(t, k)
125 if getmetatable(t).getters[k] then
126 return getmetatable(t).getters[k](t)
128 return getmetatable(t)["tag"]
130 return getmetatable(t)[k]
133 behavior.__newindex = function(t, k, v)
134 if getmetatable(t).setters[k] then
135 getmetatable(t).setters[k](t, v)
140 behavior.__pairs = function (t)
141 if accessors == nil then
144 local iterable_fields = type(accessors) == 'string'
146 or top_level_fields(accessors)
147 return make_next_function(iterable_fields), t
153------------------------------------------------------------------------
154-- The base class for types
164 setmetatable(obj, self)
168Type.behavior.__index = Type.behavior
170--- Set a new behavior for the type, inheriting that of the parent type if none
171--- is specified explicitly
172-- @param behavior the behavior object for this type.
174function Type:set_behavior (behavior)
175 behavior = behavior or {}
176 behavior.__index = rawget(behavior, '__index') or behavior
177 behavior.__type = self
178 if not getmetatable(behavior) and getmetatable(self) then
179 setmetatable(behavior, getmetatable(self).behavior)
181 self.behavior = behavior
184--- Create a new subtype, using the given table as base.
185-- @param name name of the new type
186-- @param[opt] behavior behavioral object for the new type.
189function Type:make_subtype(name, behavior)
190 local newtype = setmetatable({}, self)
192 newtype.__index = newtype
193 newtype:set_behavior(behavior)
198------------------------------------------------------------------------
199-- The base class for pandoc's AST elements.
202local AstElement = Type:make_subtype 'AstElement'
203AstElement.__call = function(t, ...)
204 local success, ret = pcall(t.new, t, ...)
206 return setmetatable(ret, t.behavior)
208 error(string.format('Constructor for %s failed: %s\n', t.name, ret))
212--- Make a new subtype which constructs a new value when called.
214function AstElement:make_subtype(...)
215 local newtype = Type.make_subtype(self, ...)
216 newtype.__call = self.__call
220--- Create a new constructor
222-- @param tag Tag used to identify the constructor
223-- @param fn Function to be called when constructing a new element
224-- @param accessors names to use as accessors for numerical fields
225-- @return function that constructs a new element
226function AstElement:create_constructor(tag, fn, accessors)
227 local constr = self:make_subtype(tag, create_accessor_behavior(tag, accessors))
228 function constr:new(...)
229 return setmetatable(fn(...), self.behavior)
231 self.constructor = self.constructor or {}
232 self.constructor[tag] = constr
236--- Convert AstElement input into a list if necessary.
238local function ensureList (x)
240 -- Lists are not tagged, but all elements are
247--- Ensure a given object is an Inline element, or convert it into one.
249local function ensureInlineList (x)
250 if type(x) == 'string' then
251 return List:new{M.Str(x)}
257------------------------------------------------------------------------
261--- A complete pandoc document
263-- @tparam {Block,...} blocks document content
264-- @tparam[opt] Meta meta document meta data
265M.Pandoc = AstElement:make_subtype'Pandoc'
266function M.Pandoc:new (blocks, meta)
268 blocks = ensureList(blocks),
273-- DEPRECATED synonym:
276------------------------------------------------------------------------
280--- Create a new Meta object. It sets the metatable of the given table to
283-- @tparam meta table table containing document meta information
284M.Meta = AstElement:make_subtype'Meta'
285function M.Meta:new (meta) return meta end
288------------------------------------------------------------------------
291M.MetaValue = AstElement:make_subtype('MetaValue')
294-- @function MetaBlocks
295-- @tparam {Block,...} blocks blocks
296M.MetaBlocks = M.MetaValue:create_constructor(
298 function (content) return ensureList(content) end
302-- @function MetaInlines
303-- @tparam {Inline,...} inlines inlines
304M.MetaInlines = M.MetaValue:create_constructor(
306 function (content) return ensureInlineList(content) end
311-- @tparam {MetaValue,...} meta_values list of meta values
312M.MetaList = M.MetaValue:create_constructor(
315 if content.tag == 'MetaList' then
318 return ensureList(content)
321for k, v in pairs(List) do
322 M.MetaList.behavior[k] = v
327-- @tparam table key_value_map a string-indexed map of meta values
328M.MetaMap = M.MetaValue:create_constructor(
330 function (mm) return mm end
333--- Creates string to be used in meta data.
334-- Does nothing, lua strings are meta strings.
335-- @function MetaString
336-- @tparam string str string value
337function M.MetaString(str)
341--- Creates boolean to be used in meta data.
342-- Does nothing, lua booleans are meta booleans.
344-- @tparam boolean bool boolean value
345function M.MetaBool(bool)
349------------------------------------------------------------------------
354M.Block = AstElement:make_subtype'Block'
356--- Creates a block quote element
357-- @function BlockQuote
358-- @tparam {Block,...} content block content
359-- @treturn Block block quote element
360M.BlockQuote = M.Block:create_constructor(
362 function(content) return {c = ensureList(content)} end,
366--- Creates a bullet (i.e. unordered) list.
367-- @function BulletList
368-- @tparam {{Block,...},...} content list of items
369-- @treturn Block bullet list element
370M.BulletList = M.Block:create_constructor(
372 function(content) return {c = ensureList(content)} end,
376--- Creates a code block element
377-- @function CodeBlock
378-- @tparam string text code string
379-- @tparam[opt] Attr attr element attributes
380-- @treturn Block code block element
381M.CodeBlock = M.Block:create_constructor(
383 function(text, attr) return {c = {attr or M.Attr(), text}} end,
384 {{attr = {"identifier", "classes", "attributes"}}, "text"}
387--- Creates a definition list, containing terms and their explanation.
388-- @function DefinitionList
389-- @tparam {{{Inline,...},{Block,...}},...} content list of items
390-- @treturn Block definition list element
391M.DefinitionList = M.Block:create_constructor(
393 function(content) return {c = ensureList(content)} end,
397--- Creates a div element
399-- @tparam {Block,...} content block content
400-- @tparam[opt] Attr attr element attributes
401-- @treturn Block div element
402M.Div = M.Block:create_constructor(
404 function(content, attr)
405 return {c = {attr or M.Attr(), ensureList(content)}}
407 {{attr = {"identifier", "classes", "attributes"}}, "content"}
410--- Creates a header element.
412-- @tparam int level header level
413-- @tparam {Inline,...} content inline content
414-- @tparam[opt] Attr attr element attributes
415-- @treturn Block header element
416M.Header = M.Block:create_constructor(
418 function(level, content, attr)
419 return {c = {level, attr or M.Attr(), ensureInlineList(content)}}
421 {"level", {attr = {"identifier", "classes", "attributes"}}, "content"}
424--- Creates a horizontal rule.
425-- @function HorizontalRule
426-- @treturn Block horizontal rule
427M.HorizontalRule = M.Block:create_constructor(
429 function() return {} end
432--- Creates a line block element.
433-- @function LineBlock
434-- @tparam {{Inline,...},...} content inline content
435-- @treturn Block line block element
436M.LineBlock = M.Block:create_constructor(
438 function(content) return {c = ensureList(content)} end,
442--- Creates a null element.
444-- @treturn Block null element
445M.Null = M.Block:create_constructor(
447 function() return {} end
450--- Creates an ordered list.
451-- @function OrderedList
452-- @tparam {{Block,...},...} items list items
453-- @param[opt] listAttributes list parameters
454-- @treturn Block ordered list element
455M.OrderedList = M.Block:create_constructor(
457 function(items, listAttributes)
458 listAttributes = listAttributes or M.ListAttributes()
459 return {c = {listAttributes, ensureList(items)}}
461 {{listAttributes = {"start", "style", "delimiter"}}, "content"}
464--- Creates a para element.
466-- @tparam {Inline,...} content inline content
467-- @treturn Block paragraph element
468M.Para = M.Block:create_constructor(
470 function(content) return {c = ensureInlineList(content)} end,
474--- Creates a plain element.
476-- @tparam {Inline,...} content inline content
477-- @treturn Block plain element
478M.Plain = M.Block:create_constructor(
480 function(content) return {c = ensureInlineList(content)} end,
484--- Creates a raw content block of the specified format.
486-- @tparam string format format of content
487-- @tparam string text string content
488-- @treturn Block raw block element
489M.RawBlock = M.Block:create_constructor(
491 function(format, text) return {c = {format, text}} end,
495--- Creates a table element.
497-- @tparam {Inline,...} caption table caption
498-- @tparam {AlignDefault|AlignLeft|AlignRight|AlignCenter,...} aligns alignments
499-- @tparam {int,...} widths column widths
500-- @tparam {Block,...} headers header row
501-- @tparam {{Block,...}} rows table rows
502-- @treturn Block table element
503M.Table = M.Block:create_constructor(
505 function(caption, aligns, widths, headers, rows)
508 ensureInlineList(caption),
516 {"caption", "aligns", "widths", "headers", "rows"}
520------------------------------------------------------------------------
524--- Inline element class
525M.Inline = AstElement:make_subtype'Inline'
527--- Creates a Cite inline element
529-- @tparam {Inline,...} content List of inlines
530-- @tparam {Citation,...} citations List of citations
531-- @treturn Inline citations element
532M.Cite = M.Inline:create_constructor(
534 function(content, citations)
535 return {c = {ensureList(citations), ensureInlineList(content)}}
537 {"citations", "content"}
540--- Creates a Code inline element
542-- @tparam string text code string
543-- @tparam[opt] Attr attr additional attributes
544-- @treturn Inline code element
545M.Code = M.Inline:create_constructor(
547 function(text, attr) return {c = {attr or M.Attr(), text}} end,
548 {{attr = {"identifier", "classes", "attributes"}}, "text"}
551--- Creates an inline element representing emphasised text.
553-- @tparam {Inline,..} content inline content
554-- @treturn Inline emphasis element
555M.Emph = M.Inline:create_constructor(
557 function(content) return {c = ensureInlineList(content)} end,
561--- Creates a Image inline element
563-- @tparam {Inline,..} caption text used to describe the image
564-- @tparam string src path to the image file
565-- @tparam[opt] string title brief image description
566-- @tparam[opt] Attr attr additional attributes
567-- @treturn Inline image element
568M.Image = M.Inline:create_constructor(
570 function(caption, src, title, attr)
572 attr = attr or M.Attr()
573 return {c = {attr, ensureInlineList(caption), {src, title}}}
575 {{attr = {"identifier", "classes", "attributes"}}, "caption", {"src", "title"}}
578--- Create a LineBreak inline element
579-- @function LineBreak
580-- @treturn Inline linebreak element
581M.LineBreak = M.Inline:create_constructor(
583 function() return {} end
586--- Creates a link inline element, usually a hyperlink.
588-- @tparam {Inline,..} content text for this link
589-- @tparam string target the link target
590-- @tparam[opt] string title brief link description
591-- @tparam[opt] Attr attr additional attributes
592-- @treturn Inline image element
593M.Link = M.Inline:create_constructor(
595 function(content, target, title, attr)
597 attr = attr or M.Attr()
598 return {c = {attr, ensureInlineList(content), {target, title}}}
600 {{attr = {"identifier", "classes", "attributes"}}, "content", {"target", "title"}}
603--- Creates a Math element, either inline or displayed.
605-- @tparam "InlineMath"|"DisplayMath" mathtype rendering specifier
606-- @tparam string text Math content
607-- @treturn Inline Math element
608M.Math = M.Inline:create_constructor(
610 function(mathtype, text)
611 return {c = {mathtype, text}}
615--- Creates a DisplayMath element (DEPRECATED).
616-- @function DisplayMath
617-- @tparam string text Math content
618-- @treturn Inline Math element
619M.DisplayMath = M.Inline:create_constructor(
621 function(text) return M.Math("DisplayMath", text) end,
624--- Creates an InlineMath inline element (DEPRECATED).
625-- @function InlineMath
626-- @tparam string text Math content
627-- @treturn Inline Math element
628M.InlineMath = M.Inline:create_constructor(
630 function(text) return M.Math("InlineMath", text) end,
634--- Creates a Note inline element
636-- @tparam {Block,...} content footnote block content
637M.Note = M.Inline:create_constructor(
639 function(content) return {c = ensureList(content)} end,
643--- Creates a Quoted inline element given the quote type and quoted content.
645-- @tparam "DoubleQuote"|"SingleQuote" quotetype type of quotes to be used
646-- @tparam {Inline,..} content inline content
647-- @treturn Inline quoted element
648M.Quoted = M.Inline:create_constructor(
650 function(quotetype, content) return {c = {quotetype, ensureInlineList(content)}} end,
651 {"quotetype", "content"}
653--- Creates a single-quoted inline element (DEPRECATED).
654-- @function SingleQuoted
655-- @tparam {Inline,..} content inline content
656-- @treturn Inline quoted element
658M.SingleQuoted = M.Inline:create_constructor(
660 function(content) return M.Quoted(M.SingleQuote, content) end,
661 {"quotetype", "content"}
663--- Creates a single-quoted inline element (DEPRECATED).
664-- @function DoubleQuoted
665-- @tparam {Inline,..} content inline content
666-- @treturn Inline quoted element
668M.DoubleQuoted = M.Inline:create_constructor(
670 function(content) return M.Quoted("DoubleQuote", content) end,
671 {"quotetype", "content"}
674--- Creates a RawInline inline element
675-- @function RawInline
676-- @tparam string format format of the contents
677-- @tparam string text string content
678-- @treturn Inline raw inline element
679M.RawInline = M.Inline:create_constructor(
681 function(format, text) return {c = {format, text}} end,
685--- Creates text rendered in small caps
686-- @function SmallCaps
687-- @tparam {Inline,..} content inline content
688-- @treturn Inline smallcaps element
689M.SmallCaps = M.Inline:create_constructor(
691 function(content) return {c = ensureInlineList(content)} end,
695--- Creates a SoftBreak inline element.
696-- @function SoftBreak
697-- @treturn Inline softbreak element
698M.SoftBreak = M.Inline:create_constructor(
700 function() return {} end
703--- Create a Space inline element
705-- @treturn Inline space element
706M.Space = M.Inline:create_constructor(
708 function() return {} end
711--- Creates a Span inline element
713-- @tparam {Inline,..} content inline content
714-- @tparam[opt] Attr attr additional attributes
715-- @treturn Inline span element
716M.Span = M.Inline:create_constructor(
718 function(content, attr)
719 return {c = {attr or M.Attr(), ensureInlineList(content)}}
721 {{attr = {"identifier", "classes", "attributes"}}, "content"}
724--- Creates a Str inline element
726-- @tparam string text content
727-- @treturn Inline string element
728M.Str = M.Inline:create_constructor(
730 function(text) return {c = text} end,
734--- Creates text which is striked out.
735-- @function Strikeout
736-- @tparam {Inline,..} content inline content
737-- @treturn Inline strikeout element
738M.Strikeout = M.Inline:create_constructor(
740 function(content) return {c = ensureInlineList(content)} end,
744--- Creates a Strong element, whose text is usually displayed in a bold font.
746-- @tparam {Inline,..} content inline content
747-- @treturn Inline strong element
748M.Strong = M.Inline:create_constructor(
750 function(content) return {c = ensureInlineList(content)} end,
754--- Creates a Subscript inline element
755-- @function Subscript
756-- @tparam {Inline,..} content inline content
757-- @treturn Inline subscript element
758M.Subscript = M.Inline:create_constructor(
760 function(content) return {c = ensureInlineList(content)} end,
764--- Creates a Superscript inline element
765-- @function Superscript
766-- @tparam {Inline,..} content inline content
767-- @treturn Inline strong element
768M.Superscript = M.Inline:create_constructor(
770 function(content) return {c = ensureInlineList(content)} end,
775------------------------------------------------------------------------
777-- @section components
779--- Check if the first element of a pair matches the given value.
780-- @param x key value to be checked
781-- @return function returning true iff first element of its argument matches x
783local function assoc_key_equals (x)
784 return function (y) return y[1] == x end
787--- Lookup a value in an associative list
790-- @tparam {{key, value},...} alist associative list
791-- @param key key for which the associated value is to be looked up
792local function lookup(alist, key)
793 return (List.find_if(alist, assoc_key_equals(key)) or {})[2]
796--- Return an iterator which returns key-value pairs of an associative list.
799-- @tparam {{key, value},...} alist associative list
800local apairs = function (alist)
804 cur = rawget(alist, i)
807 return cur[1], cur[2]
814--- AttributeList, a metatable to allow table-like access to attribute lists
815-- represented by associative lists.
817local AttributeList = {
818 __index = function (t, k)
819 if type(k) == "number" then
826 __newindex = function (t, k, v)
827 local cur, idx = List.find_if(t, assoc_key_equals(k))
832 elseif type(k) == "number" then
835 rawset(t, #t + 1, {k, v})
842--- Convert a table to an associative list. The order of key-value pairs in the
843-- alist is undefined. The table should either contain no numeric keys or
844-- already be an associative list.
846-- @tparam table tbl associative list or table without numeric keys.
847-- @treturn table associative list
848local to_alist = function (tbl)
849 if #tbl ~= 0 or next(tbl) == nil then
850 -- probably already an alist
855 for k, v in pairs(tbl) do
864--- Create a new set of attributes (Attr).
866-- @tparam[opt] string identifier element identifier
867-- @tparam[opt] {string,...} classes element classes
868-- @tparam[opt] table attributes table containing string keys and values
869-- @return element attributes
870M.Attr = AstElement:make_subtype'Attr'
871function M.Attr:new (identifier, classes, attributes)
872 identifier = identifier or ''
873 classes = ensureList(classes or {})
874 attributes = setmetatable(to_alist(attributes or {}), AttributeList)
875 return {identifier, classes, attributes}
877M.Attr.behavior._field_names = {identifier = 1, classes = 2, attributes = 3}
878M.Attr.behavior.__eq = utils.equals
879M.Attr.behavior.__index = function(t, k)
880 return rawget(t, getmetatable(t)._field_names[k]) or
883M.Attr.behavior.__newindex = function(t, k, v)
884 if getmetatable(t)._field_names[k] then
885 rawset(t, getmetatable(t)._field_names[k], v)
890M.Attr.behavior.__pairs = function(t)
891 local field_names = M.Attr.behavior._field_names
893 for name, i in pairs(field_names) do
896 return make_next_function(fields), t, nil
900M.Citation = AstElement:make_subtype'Citation'
902--- Creates a single citation.
904-- @tparam string id citation identifier (like a bibtex key)
905-- @tparam AuthorInText|SuppressAuthor|NormalCitation mode citation mode
906-- @tparam[opt] {Inline,...} prefix citation prefix
907-- @tparam[opt] {Inline,...} suffix citation suffix
908-- @tparam[opt] int note_num note number
909-- @tparam[opt] int hash hash number
910function M.Citation:new (id, mode, prefix, suffix, note_num, hash)
914 prefix = ensureList(prefix or {}),
915 suffix = ensureList(suffix or {}),
916 note_num = note_num or 0,
922M.ListAttributes = AstElement:make_subtype 'ListAttributes'
924--- Creates a set of list attributes.
925-- @function ListAttributes
926-- @tparam[opt] integer start number of the first list item
927-- @tparam[opt] string style style used for list numbering
928-- @tparam[opt] DefaultDelim|Period|OneParen|TwoParens delimiter delimiter of list numbers
929-- @treturn table list attributes table
930function M.ListAttributes:new (start, style, delimiter)
932 style = style or 'DefaultStyle'
933 delimiter = delimiter or 'DefaultDelim'
934 return {start, style, delimiter}
936M.ListAttributes.behavior._field_names = {start = 1, style = 2, delimiter = 3}
937M.ListAttributes.behavior.__eq = utils.equals
938M.ListAttributes.behavior.__index = function (t, k)
939 return rawget(t, getmetatable(t)._field_names[k]) or
942M.ListAttributes.behavior.__newindex = function (t, k, v)
943 if getmetatable(t)._field_names[k] then
944 rawset(t, getmetatable(t)._field_names[k], v)
949M.ListAttributes.behavior.__pairs = function(t)
950 local field_names = M.ListAttributes.behavior._field_names
952 for name, i in pairs(field_names) do
955 return make_next_function(fields), t, nil
959------------------------------------------------------------------------
963--- Author name is mentioned in the text.
966M.AuthorInText = "AuthorInText"
968--- Author name is suppressed.
971M.SuppressAuthor = "SuppressAuthor"
973--- Default citation style is used.
976M.NormalCitation = "NormalCitation"
978--- Table cells aligned left.
980M.AlignLeft = "AlignLeft"
982--- Table cells right-aligned.
984M.AlignRight = "AlignRight"
986--- Table cell content is centered.
988M.AlignCenter = "AlignCenter"
990--- Table cells are alignment is unaltered.
992M.AlignDefault = "AlignDefault"
994--- Default list number delimiters are used.
996M.DefaultDelim = "DefaultDelim"
998--- List numbers are delimited by a period.
1002--- List numbers are delimited by a single parenthesis.
1004M.OneParen = "OneParen"
1006--- List numbers are delimited by a double parentheses.
1008M.TwoParens = "TwoParens"
1010--- List are numbered in the default style
1012M.DefaultStyle = "DefaultStyle"
1014--- List items are numbered as examples.
1016M.Example = "Example"
1018--- List are numbered using decimal integers.
1020M.Decimal = "Decimal"
1022--- List are numbered using lower-case roman numerals.
1024M.LowerRoman = "LowerRoman"
1026--- List are numbered using upper-case roman numerals
1028M.UpperRoman = "UpperRoman"
1030--- List are numbered using lower-case alphabetic characters.
1032M.LowerAlpha = "LowerAlpha"
1034--- List are numbered using upper-case alphabetic characters.
1036M.UpperAlpha = "UpperAlpha"
1038------------------------------------------------------------------------
1039-- Functions which have moved to different modules
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