Skip to content

Instantly share code, notes, and snippets.

/secthdr.lua
Created Jul 5, 2016

Embed
What would you like to do?
local string = string
local stringformat = string.format
local stringrep = string.rep
local table = table
local tableappend = table.append
local tableconcat = table.concat
local unpack = unpack or table.unpack
local vim = vim or { }
local vimeval = vim.eval
local vimline = vim.line
local vimwindow = vim.window
local lpeg = require "lpeg"
local lpegmatch = lpeg.match
local math = math
local mathfloor = math.floor
local println = function (fmt, ...) print (stringformat (fmt, ...)) end
local p_comment do
local set = function (acc, flags, str)
if not flags then
acc [#acc + 1] = str
else
acc [#acc + 1] = { str = str, flags = flags }
end
return acc
end
local C = lpeg.C
local Cc = lpeg.Cc
local Cf = lpeg.Cf
local Cg = lpeg.Cg
local Ct = lpeg.Ct
local P = lpeg.P
local R = lpeg.R
local S = lpeg.S
local comma = P","
local colon = P":"
local minus = P"-"
local digit = R"09"
local floff = (digit^1 + minus * digit^1) / tonumber
local flnum = Cg (C (S"se") * (floff + Cc (0)))
local fljunk = Cg (C ((P (1) - colon)) * Cc (false))
local flsim = Cg (C (S"nbfmlrOx") * Cc (true))
local flags = flnum + flsim + fljunk
local cstr = (P(1) - comma)^1
local lhs = Cf (Ct"" * flags^1, rawset)
local rhs = C (cstr)
local itemflg = lhs * colon * rhs
local iteml = colon * Cc (false) * rhs
local item = Cg (itemflg) + Cg (iteml)
p_comment = Cf (Ct"" * item * (comma * item)^0, set)
end
local comments_parse = function (c)
if c == "" then return { } end
return lpegmatch (p_comment, c)
end
local comments_format_flag = function (flag)
local tflag = type (flag)
local ret = "<junk>"
if tflag == "string" then
ret = stringformat ("‘%s’", flag)
elseif tflag == "table" then
ret = stringformat ("‘%s’[%d]", unpack (flag))
else
ret = stringformat ("invalid flag type %s for ‘%s’", tflag, flag)
end
return ret
end
local comments_print = function (c)
for i = 1, #c do
local ci = c [i]
local tci = type (ci)
if tci == "string" then
println ("[%d] “%s”", i, ci)
elseif tci == "table" then
local lst = { }
for fl, val in next, ci.flags do
local s = ""
if val == true then s = "+" .. fl
elseif val == false then s = "-" .. fl
elseif tonumber (val) then s = stringformat ("%s=%d", fl, val) end
lst [#lst + 1] = s
end
local str = ci.str
local nci = #ci
println ("[%d] “%s”; flags: %s", i, str, tableconcat (lst, ", "))
end
end
end
if not vimeval then --- testing
local comdflt = [[s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-]]
local comrs = [[s0:/*!,m: ,ex:*/,s1:/*,mb:*,ex:*/,:///,://!,://]]
local comc = [[sO:* -,mO:* ,exO:*/,s1:/*,mb:*,ex:*/,://]]
local comocaml = [[sr:(*,mb:*,ex:*)]]
----- comsh = [[s1:/*,mb:*,ex:*/,://,b:#,:%,:XCOMM,n:>,fb:-]] -- same as default
local comlua = [[:--]]
local comconf = [[:#,:; ]] --- e. g. gitconfig
local comviml = [[sO:" -,mO:" ,eO:"",:"]]
local sep = function () println ("\n%s", string.rep ("*", 80)) end
local test = function (c)
sep ()
println ("input:%q", c)
comments_print (comments_parse (c))
end
test (comdflt)
test (comrs)
test (comc)
test (comocaml)
--test (comsh)
test (comlua)
test ""
test (comconf)
test (comviml)
end
--- query first start (“s”) comment
local comments_triple = function (c)
local s = false s_fallback = false
local m = false m_fallback = false
local e = false
for i = 1, #c do
local ci = c [i]
if type (ci) == "string" then
--- Lua comments are “:--”
m_fallback = ci
elseif type (ci) == "table" then
local cifl = ci.flags
local cistr = ci.str
local cifls = cifl.s
local ciflm = cifl.m
local cifle = cifl.e
if cifls and not s then
--- the C comments have both “sO:* -” and “s1:/*” but only the latter
--- is useful for us
if cifls == 1 then s = cistr else s_fallback = cistr end
end
if ciflm and not m then
--- e. g. the C comments have both “mO:* ” and “mb:*” where the
--- former messes things up lest we make below distinction
if cifl.b then m = cistr else m_fallback = cistr end
end
if cifle and not e then
e = cistr
end
end
if s and m and e then return s, m, e end
end
return s or s_fallback, m or m_fallback, e --> maybe partial
end
local comments_block_delim = function (s, m, e, tw)
local nm = #m
local ns = #s
local nidt = ns - nm
local nreps = mathfloor (tw / nm) - ns
local nrepe = mathfloor (tw / nm) - #e - nidt
local idt = stringrep (" ", nidt)
local seps = s .. stringrep (m, nreps)
local sepe = idt .. stringrep (m, nrepe) .. e
return { seps, idt .. m .. " ", sepe }
end
local comments_block_eol = function (m, tw)
local nm = #m
local nrep = mathfloor (tw / nm)
local sep = stringrep (m, nrep)
return { sep, m .. " ", sep }
end
local comments_block = function (s, m, e, tw)
if s and m and e then
return comments_block_delim (s, m, e, tw)
elseif m then
return comments_block_eol (m, tw)
end
return false
end
local comments_header = function ()
local tw = tonumber (vimeval "&textwidth")
local cm = comments_parse (vimeval "&comments")
if not cm then return false end
local s, m, e = comments_triple (cm)
return comments_block (s, m, e, tw)
end
local comments_insert = function ()
local hdr = comments_header ()
if not hdr then return end
local w = vimwindow ()
local n = w.line - 1
local thdr = type (hdr)
--- add lines from block builder
if thdr == "string" then
w.buffer:insert(hdr, n)
elseif thdr == "table" then
for i = #hdr, 1, -1 do
w.buffer:insert(hdr [i], n)
end
else
return stringformat ("<received junk %q from header builder>", tostring (hdr))
end
--- reposition cursor
w.line = n + 2
w.col = #w.buffer [w.line]
end
return function ()
return {
insert = comments_insert,
}
end
lua << ENOUGH
local string = string
local filevim = vim.eval [[expand("<sfile>")]]
local filelua = string.gsub(filevim, "%.vim$", ".lua")
local loadmodule = function (mod)
local ok, data = pcall (dofile, mod)
if ok then return data end
return false
end
local init = loadmodule (filelua)
if init and type (init) == "function" then
_G.secthdr = init ()
else
print (string.format ("secthdr: failed to load module from “%s”", filelua))
end
ENOUGH
function! Secthdr ()
lua secthdr.insert ()
endfunction
nnoremap <Leader>h :call Secthdr()<CR>a
inoremap <Leader>h <ESC>:call Secthdr()<CR>a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.