require("vis")
local M = {}
M.par_prg = "par"
M.par_tw = 72
M.ex_args = function () return "RET4bhgqw" .. M.par_tw end
M.debug = false
-- ex_args = "RET4bhgqB=.,?_A_aQ=_s>|w" .. par_tw
-- export PARINIT='Tbp2hgqR B=.,?_A_a Q=_s>|'
function print(...)
if M.debug then
_print_ = _print_ or io.open("/tmp/visprint", "w")
_print_:write(..., "\n")
end
end
--- Dump value of a variable in a formatted string
--
--- @param o table Dumpable object
--- @param tbs string|nil Tabulation string, ' ' by default
--- @param tb number|nil Initial tabulation level, 0 by default
--- @return string
local function dump(o, tbs, tb)
tb = tb or 0
tbs = tbs or " "
if type(o) == "table" then
local s = "{"
if (next(o)) then
s = s .. "\n"
else
return s .. "}"
end
tb = tb + 1
for k, v in pairs(o) do
if type(k) ~= "number" then
k = '"' .. k .. '"'
end
s = s .. tbs:rep(tb) .. "[" .. k .. "] = " .. dump(v, tbs, tb)
s = s .. ",\n"
end
tb = tb - 1
return s .. tbs:rep(tb) .. "}"
else
return tostring(o)
end
end
local supress_stdout = " >/dev/null"
local supress_stderr = " 2>/dev/null"
local supress_output = supress_stdout .. supress_stderr
-- Return nil or a string of formatted text from a specific file range or text
-- by calling the formatter command.
-- If given a range we will use vis:pipe to get the output from the formatter.
-- If a string was passed we call the formatter ourself and redirect its stdout
-- to a temporary file. See http://lua-users.org/lists/lua-l/2007-10/msg00189.html.
local function run_shell_cmd(cmd, params, inp)
local out
print("cmd = " .. cmd .. ", params = " .. params .. ", inp = " .. inp .. ", (" .. type(inp) .. ")")
if type(inp) == "string" then
local full_cmd = cmd .. " '" .. params .. "'"
local tmp_name = os.tmpname()
print("tmp_name = " .. tmp_name)
full_cmd = full_cmd .. " > " .. tmp_name
print("full_cmd = " .. full_cmd)
local proc = assert(io.popen(full_cmd, "w"))
print("proc = " .. type(proc))
proc:write(inp)
-- this error detection may need lua5.2
proc:flush()
local exit_code = proc:close()
print("exit_code = " .. tostring(exit_code))
local tmp_file = assert(io.open(tmp_name, "r"))
out = tmp_file:read("*a")
tmp_file:close()
-- print("out = " .. out)
os.remove(tmp_name)
if not exit_code then
print("calling " .. full_cmd .. " failed (" .. out .. ")")
return nil
end
else
local range = inp
local ret, so, _ = vis:pipe(vis.win.file, range, cmd)
if ret ~= 0 then
print("calling " .. cmd .. " failed (" .. ret .. ")")
return nil
end
out = so
end
return out
end
function lines(str)
local t = {}
local function helper(line)
table.insert(t, line)
return ""
end
helper((str:gsub("(.-)\r?\n", helper)))
return t
end
getmetatable(_VERSION).__index.lines = lines
function hanging_symbol(line, nspc)
local beg, fin = 0, 0
-- itemized list
beg, fin = line:find("^[-+*] ", nspc)
if beg then
print("item beg = " .. beg .. ", fin = " .. fin)
return fin
end
local beg, fin = line:find("^%d+%. ", nspc)
if beg then
print("enum beg = " .. beg .. ", fin = " .. fin)
return fin
end
return nspc -- no hanging idennt
end
function new_segment(segment, p_arg)
if next(segment) then
print("M.par_prg = " .. M.par_prg .. ", M.ex_args = " .. M.ex_args() .. ", p_arg = " .. p_arg)
local new_text = run_shell_cmd(M.par_prg, M.ex_args() .. "p" .. p_arg,
table.concat(segment, "\n"))
print("new_text = " .. new_text)
return new_text, {}, 0 -- add-to-out, segment, p_arg
else
return "", {}, 0 -- add-to-out, segment, p_arg
end
end
vis:operator_new(
"gq",
function(file, range, pos)
local out = ""
local hang_sym = ""
local segment = {}
local p_arg = 0
local range_lines = file:content(range):lines()
for _, line in ipairs(range_lines) do
local beg, beg_spc_len = line:find("^%s*")
assert(beg == 1, "There is no way this would not be 1.")
local non_spc_idx = line:len() >= beg_spc_len + 1 and beg_spc_len + 1 or 0
print("non_spc_idx = " .. non_spc_idx)
hang_sym = hanging_symbol(line, non_spc_idx)
print("hang_sym = " .. hang_sym .. ", non_spc_idx = " .. non_spc_idx)
if non_spc_idx ~= 0 then -- non-empty line
-- item: start new segment
if hang_sym ~= non_spc_idx then
seg_pared, segment, p_arg = new_segment(segment, p_arg)
if seg_pared then
out = out .. seg_pared
p_arg = hang_sym
end
table.insert(segment, line)
else
-- continuous line in a segment, just collect it
table.insert(segment, line)
end
else -- this is an empty line
seg_pared, segment, p_arg = new_segment(segment, p_arg)
if seg_pared then
out = out .. seg_pared
end
end
end
if out:len() == 0 then
print("Cannot process paragraph.")
else
file:delete(range)
file:insert(range.start, out)
end
return range.start -- new cursor location
end,
"Formating operator, filter range through formatting filter"
)
vis:option_register(
"autoformat",
"bool",
function(value, toogle)
if not vis.win then
return false
end
vis.win.autoformat = toogle and not vis.win.autoformat or value
print("Option autoformat = " .. tostring(vis.win.autoformat))
return true
end,
"Automatically format current paragraph."
)
return M