aboutsummaryrefslogblamecommitdiffstats
path: root/init.lua
blob: 4411c375750155e912d27fdd0027f6b3afc814fb (plain) (tree)
1
2
3
4
5
6
7
8
              





                                                          
               


                                                 
                   



                                                          





















                                                                  
               









                                                                          



                                                       



                                                                               
                                                                                   
                                              



                                                                                                       
                                                     














                                                       

                                 

                             





























                                                                      
                         
                    



                                                        



                                               

                                                        




                                    

                                    

                                                                                                      







                                                                   



                              
                           


                                                       






                                                                                      








                                                                                 
                                        





                                                                    
                                         


                                                                       




















                                                                
           





                                                                       

        
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