vis-config

lua scripts to configure vis editor

git clone https://9o.is/git/vis-config.git

ctags.lua

(3397B)


      1 local M = {
      2 	file = '.tags',
      3 	path = '.',
      4 	flags = '-R',
      5 }
      6 
      7 local function generate_tags(win, file)
      8 	local tags = win.tags[file]
      9 
     10 	if not tags then
     11 		return
     12 	end
     13 
     14 	local fd = io.popen(string.format('ctags %s -n -f %s %s', tags.flags, file, tags.path))
     15 	local success, msg = fd:close()
     16 
     17 	if not success then
     18 		vis:info(string.format('Error: %s', msg))
     19 	end
     20 end
     21 
     22 local tagstack = {}
     23 
     24 vis:option_register('ctags', 'bool', function(value, toggle)
     25 	local win = vis.win
     26 	if not win then return false end
     27 
     28 	win.ctags = toggle and not win.ctags or value
     29 
     30 	if win.ctags then
     31 		if not win.tags then
     32 			win.tags = {}
     33 			M.add(win, M.file)
     34 		end
     35 
     36 		win:map(vis.modes.NORMAL, '<C-t>', function()
     37 			vis:command('tag-back')
     38 		end)
     39 
     40 		win:map(vis.modes.NORMAL, '<C-]>', function()
     41 			local tag = win.file:content(win.file:text_object_word(win.selection.pos))
     42 			vis:command('tag ' .. tag)
     43 		end)
     44 
     45 		win:map(vis.modes.VISUAL, '<C-]>', function()
     46 			local tag = win.file:content(win.selection.range)
     47 			vis:command('tag ' .. tag)
     48 		end)
     49 	end
     50 
     51 	return true
     52 end, 'Enables ctags')
     53 
     54 vis:command_register('tag-generate', function(argv, _, win)
     55 	local file = argv[1]
     56 
     57 	if not win.ctags then
     58 		vis:info('tag: disabled')
     59 		return
     60 	end
     61 
     62 	if not win.tags then
     63 		vis:info('tag-generate: tags not configured')
     64 		return
     65 	end
     66 
     67 	if file and not win.tags[file] then
     68 		vis:info('tag-generate: tags file not configured')
     69 		return
     70 	end
     71 
     72 	for f in pairs(win.tags) do
     73 		if not file or (file and file == f) then
     74 			generate_tags(win, f)
     75 		end
     76 	end
     77 end, 'Generate ctags file')
     78 
     79 vis:command_register('tag', function(argv, _, win)
     80 	local tag = argv[1]
     81 
     82 	if not win.ctags then
     83 		vis:info('tag: disabled')
     84 		return
     85 	end
     86 
     87 	if not win.tags then
     88 		vis:info('tag: tags not configured')
     89 		return
     90 	end
     91 
     92 	if not tag or tag == '' then
     93 		vis:info('tag: missing argument')
     94 		return false
     95 	end
     96 
     97 	local files = ''
     98 	for file in pairs(win.tags) do
     99 		files = files .. ' ' .. file
    100 	end
    101 
    102 	local fd = io.popen(string.format(
    103 		"sh -c 'cat %s 2>/dev/null | grep -v \'^!_\' | readtags -t - - %s'", files, tag))
    104 	local line = fd:read()
    105 	fd:close()
    106 
    107 	if not line or line == '' then
    108 		vis:info('tag: nothing found')
    109 		return false
    110 	end
    111 
    112 	local prev = {
    113 		path = win.file.name,
    114 		line = win.selection.line,
    115 		col = win.selection.col,
    116 	}
    117 
    118 	local file, lineno = line:match('^[^%s]+%s+([^%s]+)%s+(%d+)') 
    119 
    120 	if not vis:command(string.format('e %s', file)) then
    121 		vis:info(string.format('tag failed: %s cannot be opened', file))
    122 		return false
    123 	end
    124 
    125 	vis.win.selection:to(lineno, 0)
    126 	table.insert(tagstack, prev)
    127 
    128 	return true
    129 end, 'Jump to tag')
    130 
    131 vis:command_register('tag-back', function()
    132 	local item = table.remove(tagstack)
    133 
    134 	if not item then
    135 		return
    136 	end
    137 
    138 	if not vis:command(string.format('e %s', item.path)) then
    139 		vis:info(string.format('tag-back failed: %s cannot be opened', item.path))
    140 		return
    141 	end
    142 	
    143 	vis.win.selection:to(item.line, item.col)
    144 end, 'Go back in tag stack')
    145 
    146 vis.events.subscribe(vis.events.FILE_SAVE_POST, function()
    147 	if not vis.win.ctags then
    148 		return
    149 	end
    150 
    151 	for file, prefs in pairs(vis.win.tags) do
    152 		if prefs.autosave then
    153 			generate_tags(vis.win, file)
    154 		end
    155 	end
    156 end)
    157 
    158 M.add = function(win, file, prefs)
    159 	if not prefs       then prefs = {} end
    160 	if not prefs.path  then prefs.path  = M.path end
    161 	if not prefs.file  then prefs.file  = M.file end
    162 	if not prefs.flags then prefs.flags = M.flags end
    163 	win.tags[file] = prefs
    164 end
    165 
    166 return M