From a47844a42cfabc9eb893eef80dd375d75bdd436f Mon Sep 17 00:00:00 2001 From: Philipp Gesang Date: Fri, 17 Sep 2010 17:11:35 +0200 Subject: revised bullet list enumeration, accepting irregular numbering. --- rst_context.lua | 39 +++++++++++++++++++++++++++----- rst_helpers.lua | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++------- rst_parser.lua | 30 ++++++++++++++++--------- 3 files changed, 113 insertions(+), 25 deletions(-) diff --git a/rst_context.lua b/rst_context.lua index 19a5167..39d375b 100644 --- a/rst_context.lua +++ b/rst_context.lua @@ -49,6 +49,7 @@ rst_context.anonymous_targets = 0 rst_context.anonymous_links = 0 rst_context.context_references = {} rst_context.substitutions = {} +rst_context.lastitemnumber = 0 -- enumerations in RST allow arbitrary skips rst_context.current_footnote_number = 0 rst_context.current_symbolnote_number = 0 @@ -589,12 +590,12 @@ local function parse_itemstring(str) if str:match("%.$") then setup = setup .. [[stopper={.\\space}]] end - if str:match("^%d") then + local num = str:match("^%d") + if num then -- http://thread.gmane.org/gmane.comp.tex.context/61728/focus=61729 - setup = setup .. ",start=" .. tonumber(str:match("^%d+")) - 1 + setup = setup .. ",start=" .. num str = "n" end - setup = setup str = itemstripper:match(str) str = enumeration_types[str] or str @@ -619,16 +620,42 @@ function rst_context.startitemize(str) return result end +local last_item = {} -- stack +local current_itemdepth = 0 function rst_context.stopitemize(str) + last_item[current_itemdepth] = nil + current_itemdepth = current_itemdepth - 1 return str .. [[ \\stopitemize ]] end -function rst_context.bullet_item (str) - return [[ +function rst_context.bullet_item (tab) + local li = last_item + -- The capture of the first item has the \startitemize as + -- *second* element in the array. + local content = #tab == 2 and tab[2] or tab[3] + local startstr = #tab == 3 and tab[2] or nil + local itemtype = tab[1] + local result = startstr or "" + if startstr then + current_itemdepth = current_itemdepth + 1 + li[current_itemdepth] = itemtype + elseif li[current_itemdepth] then + if helpers.list.successor(itemtype, li[current_itemdepth]) then + -- just leave it alone + elseif helpers.list.greater(itemtype, li[current_itemdepth]) then + local itemnum = tonumber(string.strip(itemtype)) or helpers.list.get_decimal(itemtype) + result = result .. string.format([[ +\\setnumber[itemgroup:itemize]{%s} +]], itemnum) + end + li[current_itemdepth] = itemtype + end + + return result .. [[ -\\item ]] .. inline_parser:match(str) .. [[ +\\item ]] .. inline_parser:match(content) .. [[ ]] end diff --git a/rst_helpers.lua b/rst_helpers.lua index 0f6e10c..b8902ca 100644 --- a/rst_helpers.lua +++ b/rst_helpers.lua @@ -354,11 +354,9 @@ function helpers.table.simple(raw) --ignore = false } cell.content = string.strip(row:sub(start, stop)) - print(">>".. row:sub(start, stop) .."<<", ">>"..cell.content.."<<") if check_span then local start_at, stop_at for colnr, slice in ipairs(bounds.slices) do - print(start, slice.start, stop, slice.stop) if slice.start == start then start_at = colnr end @@ -373,7 +371,6 @@ function helpers.table.simple(raw) end end cell.span.x = 1 + stop_at - start_at - print(start_at, stop_at, cell.span.x) end newrow[nc] = cell end @@ -412,8 +409,8 @@ do local c = {} c.roman = S"ivxlcdm"^1 c.Roman = S"IVXLCDM"^1 - c.alpha = R"az" - P"i" - c.Alpha = R"AZ" - P"I" + c.alpha = R"az" - P"i" - P"v" - P"x" - P"l" + c.Alpha = R"AZ" - P"I" - P"V" - P"X" - P"L" c.digit = R"09"^1 c.auto = P"#" @@ -422,7 +419,6 @@ do local itemstripper = stripme^0 * C(dontstrip^1) * stripme^0 local con = function (str) - --print("This is it: >"..str.."<") str = itemstripper:match(str) for conv, pat in next, c do if pat:match(str) then @@ -498,7 +494,6 @@ do return false end - local trc = state.roman_cache n_str = trc[str] or nil n_old = trc[old] or nil @@ -510,11 +505,69 @@ do n_old = roman_to_arab(old:lower()) trc[old] = n_old end - --print(n_str, n_old, n_str == n_old + 1 ) return n_str == n_old + 1 end end helpers.list.successor = suc + + local greater = function (str, old) + str, old = itemstripper:match(str), itemstripper:match(old) + local n_str, n_old = tonumber(str), tonumber(old) + if n_str and n_old then -- arabic numeral + return n_str > n_old + end + + local con_str, con_old = con(str), con(old) + if con_str == "alpha" or + con_str == "Alpha" then + return str:byte() > old:byte() + else + if not (str:lower() == str or + str:upper() == str) then -- uneven cased --> fail + return false + end + + + local trc = state.roman_cache + n_str = trc[str] or nil + n_old = trc[old] or nil + if not n_str then + n_str = roman_to_arab(str:lower()) + trc[str] = n_str + end + if not n_old then + n_old = roman_to_arab(old:lower()) + trc[old] = n_old + end + return n_str > n_old + end + end + helpers.list.greater = greater + + local gd = function(str) + str = itemstripper:match(str) + local value + local con_str = con(str) + if con_str == "alpha" or + con_str == "Alpha" then + return str:byte() + else + if not (str:lower() == str or + str:upper() == str) then + return false + end + + local trc = state.roman_cache + n_str = trc[str] or nil + if not n_str then + n_str = roman_to_arab(str:lower()) + trc[str] = n_str + end + return n_str + end + end + + helpers.list.get_decimal = gd end helpers.string = {} diff --git a/rst_parser.lua b/rst_parser.lua index 01cd42d..cd44f51 100644 --- a/rst_parser.lua +++ b/rst_parser.lua @@ -826,7 +826,9 @@ local parser = P{ --bullet_stop = V"blank_line" * Cs(Cc("")) / rst.stopitemize, bullet_stop = V"end_block" / rst.stopitemize, - bullet_init = V"bullet_first" * V"bullet_itemrest", + bullet_init = Ct(C(V"bullet_first") * V"bullet_itemrest") + / rst.bullet_item + , bullet_first = #Cmt(V"bullet_indent", function (s, i, bullet) local t = state @@ -858,7 +860,9 @@ local parser = P{ end return false end) - * Cs(V"bullet_indent") / rst.startitemize, + * V"bullet_indent" + / rst.startitemize + , bullet_indent = V"space"^0 * V"bullet_expr" * V"space"^1, @@ -881,28 +885,32 @@ local parser = P{ return true elseif conversion(t.lastbullet) == conversion(bullet) then -- same type local autoconv = conversion(bullet) == "auto" - local successor = helpers.list.successor(bullet, t.lastbullet) + --local successor = helpers.list.successor(bullet, t.lastbullet) + local greater = helpers.list.greater (bullet, t.lastbullet) t.lastbullet = bullet - return autoconv or successor + --return autoconv or successor or greater + return autoconv or successor or greater end --return t.bullets[t.depth] == bullet - end) / "", + end), -- ^^^^^ -- otherwise returns the value of V"bullet_indent", not sure why … - bullet_continue = V"bullet_cont" - * V"bullet_itemrest", + bullet_continue = Ct(C(V"bullet_cont") * V"bullet_itemrest") + /rst.bullet_item + , - bullet_itemrest = Cs(V"bullet_rest" -- first line + bullet_itemrest = C(V"bullet_rest" -- first line * ((V"bullet_match" * V"bullet_rest")^0 -- any successive lines --* (V"eol" * (V"blank_line" * (V"bullet_match" * (V"bullet_rest" - V"bullet_indent"))^1)^0)) - / rst.bullet_item, + --/ rst.bullet_item, + , -- ^^^^^^^^^^^^^ -- otherwise matches bullet_first - bullet_rest = Cs((1 - V"eol")^1 * V"eol"), -- rest of one line + bullet_rest = (1 - V"eol")^1 * V"eol", -- rest of one line bullet_next = V"space"^1 , @@ -952,7 +960,7 @@ local parser = P{ section = V"section_before"^-1 * V"section_text" * V"section_after" - * (V"eol" + V"end_block") + * (V"end_block" + V"blank_line") / rst.section , -- cgit v1.2.3