From a5bbf034b6264780bd5144c48fdd9be61ec9030a Mon Sep 17 00:00:00 2001
From: Philipp Gesang <pgesang@ix.urz.uni-heidelberg.de>
Date: Fri, 3 Sep 2010 04:25:36 +0200
Subject: enumerations (most types, incl. conversions)

---
 rst_context.lua | 72 ++++++++++++++++++++++++++++++++++++++++++++++++---
 rst_parser.lua  | 80 ++++++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 124 insertions(+), 28 deletions(-)

diff --git a/rst_context.lua b/rst_context.lua
index 8b4c8d6..8131505 100644
--- a/rst_context.lua
+++ b/rst_context.lua
@@ -195,12 +195,76 @@ function rst_context.transition (str)
     return "\n\\hrule\n"
 end
 
-function rst_context.bullet_list (str)
-    return [[
+function rst_context.bullet_marker(str)
+    return "marker"
+end
+
+do
+    local space    = lpeg.S(" \t\v\n")
+    local nospace  = 1 - space
+    local stripper = space^0 * lpeg.C((space^0 * nospace^1)^0)
+    function string.strip(str)
+        return match(stripper,str) or ""
+    end 
+end
+
+local enumeration_types = {
+    ["*"] = "*", -- unordered bulleted
+    ["+"] = "*",
+    ["-"] = "*",
+    ["•"] = "*",
+    ["‣"] = "*",
+    ["⁃"] = "*",
+
+    ["#"] = "1", -- numbered lists and conversion
+    ["A"] = "A",
+    ["a"] = "a",
+    ["I"] = "R",
+    ["i"] = "r",
+}
+
+-- \setupitemize[left=(, right=), margin=4em, stopper=]
+
+local stripme   = S"()."
+local dontstrip = 1 - stripme
+local itemstripper = stripme^0 * C(dontstrip) * stripme^0
+local function parse_itemstring(str)
+    local setup = [[\setupitemize[]]
+    -- string.match is slightly faster than string.find
+    if str:match("^%(") then
+        setup = setup .. [[left=(,]]
+    end
+    if str:match("%)$") then
+        setup = setup .. [[right=)]]
+    end
+    if str:match("%.$") then
+        setup = setup .. [[stopper=.]]
+    end
+    setup = setup .. "]\n"
+
+    str = itemstripper:match(str)
+    return {setup = setup, str=str}
+end
 
-\\startitemize
-]] .. str .. [[
+function rst_context.startitemize(str)
+    local setup = ""
+    str = string.strip(str)
+
+    local listtype = enumeration_types[str] or parse_itemstring(str)
+
+    if type(listtype) == "table" then
+        print(type(listtype), listtype[2])
+        setup = listtype.setup
+        listtype = listtype.str
+    end
+
+    return setup .. [[
+\\startitemize[]] .. listtype .. [[]
+]] 
+end
 
+function rst_context.stopitemize(str)
+    return str .. [[
 \\stopitemize
 ]]
 end
diff --git a/rst_parser.lua b/rst_parser.lua
index 826d79c..eb5e6b8 100644
--- a/rst_parser.lua
+++ b/rst_parser.lua
@@ -78,17 +78,14 @@ local parser = P{
     list = V"bullet_list",
 
 --------------------------------------------------------------------------------
--- Bullet lists
+-- Bullet lists and enumerations
 --------------------------------------------------------------------------------
 
-    --bullet_list = Cs(V"bullet_init"
-                --* (V"bullet_continue"
-                 --+ V"bullet_list")^0)
-                --/ rst.bullet_list,
-
-    bullet_list = Cs(V"bullet_init"
+    -- the next rule handles enumerations as well
+    bullet_list = V"bullet_init"
                 * (V"bullet_list"
-                 + V"bullet_continue")^0) / rst.bullet_list
+                 + V"bullet_continue")^0
+                * V"bullet_stop"
                 * Cmt(Cc(nil), function (s, i)
                     local t = tracklists
                     print("[close]>", t.depth)
@@ -96,11 +93,22 @@ local parser = P{
                     return true
                 end),
 
-    bullet_first = Cmt(C(V"space"^0 * V"bullet_char" * V"space"^1), function (s, i, bullet)
+    bullet_stop = Cs(Cc("")) / rst.stopitemize,
+
+    bullet_init = V"eol"^0
+                * V"bullet_first"
+                * V"bullet_itemrest",
+
+    bullet_indent = V"space"^0 * V"bullet_expr" * V"space"^1,
+
+    bullet_first = #Cmt(V"bullet_indent", function (s, i, bullet)
                         local t = tracklists
                         local oldbullet = t.bullets[t.depth]
                         local n_spaces = match(P" "^0, bullet)
-                        print("[first]>", t.depth, n_spaces, bullet, oldbullet)
+                        print("[first]>", 
+                            t.depth, 
+                            (t.depth == 0 and n_spaces == 1) or
+                            (t.depth >  0 and n_spaces >  1), bullet, oldbullet)
 
                         if t.depth == 0 and n_spaces == 1 then -- first level
                             t.depth = 1
@@ -116,39 +124,58 @@ local parser = P{
                             end
                         end
                         return false
-                    end),
+                    end)
+                    --* V"bullet_indent" / rst.startitemize,
+                    * Cs(V"bullet_indent") / rst.startitemize,
 
-    bullet_cont  = Cmt(C(V"space"^0 * V"bullet_char" * V"space"^1), function (s, i, bullet)
+    bullet_cont  = Cmt(V"bullet_indent", function (s, i, bullet)
                         local t = tracklists
-                        print("[contin]>>", t.depth, bullet, t.bullets[t.depth], bullet == t.bullets[t.depth])
+                        print("[contin]>>", 
+                                t.depth, 
+                                bullet == t.bullets[t.depth],
+                                bullet, 
+                                t.bullets[t.depth])
                         return t.bullets[t.depth] == bullet
-                    end),
-
-    bullet_init = V"eol"^0
-                * V"bullet_first"
-                * Cs(V"bullet_itemrest")
-                / rst.bullet_item,
+                    end) / "",
+                    --   ^^^^^
+                    --   otherwise returns the value of V"bullet_indent", not sure why …
 
     bullet_continue = V"eol"^0
                     * V"bullet_cont"
-                    * Cs(V"bullet_itemrest")
-                    / rst.bullet_item,
+                    * V"bullet_itemrest",
 
     bullet_itemrest = Cs(V"bullet_rest"                               -- first line
                        * ((V"bullet_match" * V"bullet_rest")^0        -- any successive lines
                         * (V"eol"
-                         * (V"bullet_match" * (V"bullet_rest" - V"bullet_char"))^1)^0)),
+                         * (V"bullet_match" * (V"bullet_rest" - V"bullet_expr"))^1)^0))
+                    / rst.bullet_item,
                          --                                     ^^^^^^^^^^^^^
                          --                                     otherwise matches bullet_first
  
+    bullet_expr = V"bullet_char"
+                + (V"number_char" * V"dot")
+                + (P"(" * V"number_char" * P")")
+                +        V"number_char" * P")"
+                + V"number_char" * #V"space",
+
     bullet_char = S"*+-" + P"•" + P"‣" + P"⁃",
 
+    number_char = V"roman_numeral"
+                + V"Roman_numeral"
+                + P"#"
+                + V"digit"^1 
+                + R"AZ"
+                + R"az",
+
     bullet_rest = Cs((1 - V"eol")^1 * V"eol"),  -- rest of one line
 
     bullet_next  = C(V"space"^1),
     bullet_match = Cmt(V"bullet_next", function (s, i, this)
                          local t = tracklists
-                         print("[match]>>>", t.depth, utf.len(t.bullets[t.depth]), string.len(this) )
+                         print("[match]>>>", 
+                                t.depth, 
+                                string.len(this) == utf.len(t.bullets[t.depth]),
+                                utf.len(t.bullets[t.depth]), string.len(this) )
                          return string.len(this) == utf.len(t.bullets[t.depth])
                      end),
 
@@ -232,7 +259,7 @@ local parser = P{
 -- Paragraphs * Inline Markup
 --------------------------------------------------------------------------------
 
-    paragraph = -(V"doubledot" + V"double_underscore" + V"bullet_char") 
+    paragraph = -(V"doubledot" + V"double_underscore" + V"bullet_indent") 
               * Cs((V"enclosed_inline"
                   + V"inline_elements" 
                   + V"word" 
@@ -381,8 +408,13 @@ local parser = P{
     endpar = V"eol" * (V"eol"^1 + V"eof"),
 
     delimiters = P"‐" + P"‑" + P"‒" + P"–" + P"—" + V"space",
+    
     adornment_char = S[[!"#$%&'()*+,-./:;<=>?@[]^_`{|}~]] + P[[\\]],
 
+    digit = R"09",
+    roman_numeral = S"ivxlcdm"^1,
+    Roman_numeral = S"IVXLCDM"^1,
+
     inline_delimiter = P"**" + P"``" + S"*`",
     enclosed_open    = S[['"([{<]],
     enclosed_close   = S[['")]}>]],
-- 
cgit v1.2.3