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)