neovim

Personal neovim configuration files
git clone git://gtms.dev/neovim
Log | Files | Refs

trun.lua (6060B)


      1 -- Add this to your nvim folder to `plugin/trun.lua`.
      2 --
      3 -- use `:Trun <name>` to fill quickfix list with lines after last
      4 -- success status. It has autocompletion for running truns, press <tab> to list
      5 -- those.
      6 --
      7 -- !important
      8 -- Handler needs to store the output inside file and path to that file must be
      9 -- added as second line to status file. viz->examples/handler_tmp_output_file.lua
     10 --
     11 -- returns list of running truns
     12 local function trun_list()
     13   local status_dir_def = os.getenv('XDG_CACHE_HOME') .. '/trun'
     14   local status_dir = os.getenv('TRUN_STATUS_DIR') or status_dir_def
     15   local ls = io.popen('ls ' .. status_dir)
     16   local truns = {}
     17   if not ls then
     18     return truns
     19   end
     20   for trun in ls:lines() do
     21     local name = trun:match('(.*)%..*')
     22     table.insert(truns, name)
     23   end
     24   return truns
     25 end
     26 
     27 local diag_ns = vim.api.nvim_create_namespace('trun_diag')
     28 
     29 -- return lines that can be added to quickfix list
     30 -- it needs to have its tempfile for output
     31 local function trun_to_qf_list(name)
     32   if not name then
     33     return
     34   end
     35   -- Depends on `trun-status`  viz->tools/trun-status.lua
     36   local handle = io.popen('trun-status ' .. name)
     37   local o = {}
     38   if not handle then
     39     return o
     40   end
     41   for line in handle:lines() do
     42     table.insert(o, line)
     43   end
     44   if #o == 0 then
     45     vim.notify('No running trun for "' .. name .. '"', vim.log.levels.INFO)
     46     return
     47   end
     48   -- edit this if path to tmpfile(errorfile) is on another line
     49   local errorfile = o[2]
     50   if errorfile then
     51     local package_name = require('tms.ft.dart.package').package_name()
     52     if not package_name then
     53       return
     54     end
     55     local packages_paths = require('tms.ft.dart.package').packages()
     56     if not packages_paths then
     57       return
     58     end
     59     local errfile = io.open(errorfile, 'r')
     60     local lines = {}
     61     if not errfile then
     62       return
     63     end
     64     for line in errfile:lines() do
     65       if string.find(line, 'Starting Build') then
     66         lines = {}
     67       end
     68       -- translate
     69       if package_name and packages_paths then
     70         -- local package_root = packages_paths[package_name].root
     71         line = string.gsub(line, 'org%-dartlang%-app:.+', '')
     72         line = string.gsub(line, '^packages/(.-)/(.-:%d+:%d+:)', function(package, path)
     73           -- return package_root .. '/' .. '.dart_tool/build/generated/' .. package .. '/lib/' .. path
     74           local root = packages_paths[package].lib
     75           return root .. '/' .. path
     76         end)
     77         line = string.gsub(line, 'asset:(.-)/(.-):', function(package, path)
     78           local root = packages_paths[package].root
     79           return root .. '/' .. path
     80         end)
     81         line = string.gsub(line, '\'package:(.-)/(.-)\'', function(package, path)
     82           local root = packages_paths[package].lib
     83           return root .. '/' .. path
     84         end)
     85         line = string.gsub(line, 'package:(.-)/(.-):', function(package, path)
     86           local root = packages_paths[package].lib
     87           return root .. '/' .. path
     88         end)
     89       end
     90 
     91       table.insert(lines, line)
     92     end
     93 
     94     local efm = {
     95       [[%EErrors in %.%#,%Zline %l\, column %c of %f %m]],
     96       [[%f:%l:%c: %t%*[^:]: %m.]],
     97       [[%EOne or more fatal errors occured during compilation:,%Zline %l\, column %c of asset:%f: %m]],
     98       [[%EError: %m,%Z - %.%# is from %f %.%#]],
     99       [[%-G%.%#]],
    100     }
    101 
    102     local qf_items = vim.fn.getqflist({ lines = lines, efm = table.concat(efm, ',') })
    103 
    104     -- normalize template location
    105     for _, item in pairs(qf_items.items) do
    106       local lines = vim.api.nvim_buf_get_lines(item.bufnr, 0, -1, false)
    107       for line_num, line in ipairs(lines) do
    108         -- template inside annotation
    109         if string.find(line, [[template:]]) then
    110           item.lnum = item.lnum + line_num
    111         end
    112       end
    113     end
    114 
    115     return qf_items
    116   else
    117     vim.notify('Trun for "' .. name .. '" does not have tmp file', vim.log.levels.INFO)
    118     return
    119   end
    120 end
    121 
    122 local function open_diag(qf_items)
    123   local per_buf = {}
    124   for _, item in pairs(qf_items.items) do
    125     per_buf[item.bufnr] = per_buf[item.bufnr] or {}
    126     table.insert(per_buf[item.bufnr], item)
    127   end
    128 
    129   for bufnr, items in pairs(per_buf) do
    130     vim.diagnostic.reset(diag_ns, bufnr)
    131     local diag_items = vim.diagnostic.fromqflist(items)
    132 
    133     -- allow diag only for html template
    134     local ft = vim.api.nvim_get_option_value('ft', { buf = bufnr })
    135     if ft ~= 'html' then
    136       return
    137     end
    138 
    139     vim.diagnostic.set(diag_ns, bufnr, diag_items, {})
    140   end
    141 end
    142 
    143 local function open_qf(qf_items)
    144   vim.fn.setqflist({}, ' ', { items = qf_items.items })
    145   if #vim.fn.getqflist() > 0 then
    146     vim.cmd.copen()
    147   else
    148     vim.notify('no errors found', vim.log.levels.INFO)
    149   end
    150 end
    151 
    152 local function select()
    153   local list = trun_list()
    154   if #list == 0 then
    155     vim.notify('no truns', vim.log.levels.INFO)
    156   end
    157   vim.ui.select(list, { prompt = 'Select trun:' }, function(trun)
    158     local lines = trun_to_qf_list(trun)
    159     open_qf(lines)
    160   end)
    161 end
    162 
    163 local autocomplete = {
    164   nargs = '?',
    165   complete = function(ArgLead, CmdLine, CursorPos)
    166     return trun_list()
    167   end,
    168 }
    169 
    170 vim.api.nvim_create_user_command('TrunDiagClear', function(opts)
    171   vim.diagnostic.reset(diag_ns, nil)
    172 end, autocomplete)
    173 
    174 vim.api.nvim_create_user_command('TrunDiag', function(opts)
    175   local function open(name)
    176     local qf_items = trun_to_qf_list(name)
    177     if not qf_items then
    178       return
    179     end
    180     open_diag(qf_items)
    181   end
    182 
    183   if #opts.fargs == 0 then
    184     local package_name = require('tms.ft.dart.package').package_name()
    185     if not package_name then
    186       select()
    187     end
    188     open(package_name)
    189   else
    190     open(opts.fargs[1])
    191   end
    192 end, autocomplete)
    193 
    194 vim.api.nvim_create_user_command('Trun', function(opts)
    195   local function open(name)
    196     local qf_items = trun_to_qf_list(name)
    197     if not qf_items then
    198       return
    199     end
    200     open_qf(qf_items)
    201   end
    202 
    203   if #opts.fargs == 0 then
    204     local package_name = require('tms.ft.dart.package').package_name()
    205     if not package_name then
    206       select()
    207     end
    208     open(package_name)
    209   else
    210     open(opts.fargs[1])
    211   end
    212 end, autocomplete)