Module:Add-punc

From Pittsburgh Streets

Documentation for this module may be created at Module:Add-punc/doc

local p = {};

function p.add_punc(frame)
  local text = frame.args[1];
  if not text then
    return '';
  end

  local punc = frame.args[2] or '';
  local ital = frame.args['ital'];

  local result = '';
  if ital == 'on' then
    result = "''";
  end

  -- Everything other than period and comma is easy.
  if punc ~= '.' and punc ~= ',' then
    result = result .. text .. punc;
    if ital == 'on' then
      result = result .. "''";
    end
    return result;
  end

  -- Position of last non-quote character.
  local last_non_quote_pos = text:len();
  while last_non_quote_pos > 0 do
    local c = text:sub(last_non_quote_pos, last_non_quote_pos);
    if c == '"' or c == "'" then
      last_non_quote_pos = last_non_quote_pos - 1;
    else
      break;
    end
  end

  -- Last interesting character. Parentheses are not interesting.
  local last_interesting_pos = last_non_quote_pos;
  while last_interesting_pos > 0 do
    local c = text:sub(last_interesting_pos, last_interesting_pos);
    if c == ')' then
      last_interesting_pos = last_interesting_pos - 1;
    else
      break;
    end
  end
  local last_interesting_char = nil;
  if last_interesting_pos > 0 then
    last_interesting_char = text:sub(last_interesting_pos, last_interesting_pos);
  end

  -- Text before trailing quote characters.
  result = result .. text:sub(1, last_non_quote_pos);

  -- Close italics if there are no trailing quote characters.
  if ital == 'on' and last_non_quote_pos == text:len() then
    result = result .. "''";
  end

  -- Insert punctuation.
  if punc == '.' then
    -- Period, unless it collides.
    if last_interesting_char ~= '.' and last_interesting_char ~= '?' and last_interesting_char ~= '!' then
      result = result .. '.';
    end
  else
    result = result .. punc;
  end

  -- Trailing quote characters.
  result = result .. text:sub(last_non_quote_pos + 1, text:len());

  -- Close italics if there are trailing quote characters.
  if ital == 'on' and last_non_quote_pos ~= text:len() then
    result = result .. "''";
  end

  return result;
end

return p;