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