Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 1 | vim9script noclear |
Bram Moolenaar | e344bea | 2005-09-01 20:46:49 +0000 | [diff] [blame] | 2 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 3 | # Vim completion script |
| 4 | # Language: C |
| 5 | # Maintainer: Bram Moolenaar <Bram@vim.org> |
| 6 | # Rewritten in Vim9 script by github user lacygoill |
| 7 | # Last Change: 2021 Dec 27 |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 8 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 9 | var prepended: string |
| 10 | var grepCache: dict<list<dict<any>>> |
| 11 | |
| 12 | # This function is used for the 'omnifunc' option. |
| 13 | def ccomplete#Complete(findstart: bool, abase: string): any # {{{1 |
| 14 | if findstart |
| 15 | # Locate the start of the item, including ".", "->" and "[...]". |
| 16 | var line: string = getline('.') |
| 17 | var start: number = charcol('.') - 1 |
| 18 | var lastword: number = -1 |
Bram Moolenaar | e344bea | 2005-09-01 20:46:49 +0000 | [diff] [blame] | 19 | while start > 0 |
Bram Moolenaar | d5cdbeb | 2005-10-10 20:59:28 +0000 | [diff] [blame] | 20 | if line[start - 1] =~ '\w' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 21 | --start |
Bram Moolenaar | d5cdbeb | 2005-10-10 20:59:28 +0000 | [diff] [blame] | 22 | elseif line[start - 1] =~ '\.' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 23 | if lastword == -1 |
| 24 | lastword = start |
| 25 | endif |
| 26 | --start |
| 27 | elseif start > 1 && line[start - 2] == '-' |
| 28 | && line[start - 1] == '>' |
| 29 | if lastword == -1 |
| 30 | lastword = start |
| 31 | endif |
| 32 | start -= 2 |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 33 | elseif line[start - 1] == ']' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 34 | # Skip over [...]. |
| 35 | var n: number = 0 |
| 36 | --start |
| 37 | while start > 0 |
| 38 | --start |
| 39 | if line[start] == '[' |
| 40 | if n == 0 |
| 41 | break |
| 42 | endif |
| 43 | --n |
| 44 | elseif line[start] == ']' # nested [] |
| 45 | ++n |
| 46 | endif |
| 47 | endwhile |
Bram Moolenaar | e344bea | 2005-09-01 20:46:49 +0000 | [diff] [blame] | 48 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 49 | break |
Bram Moolenaar | e344bea | 2005-09-01 20:46:49 +0000 | [diff] [blame] | 50 | endif |
| 51 | endwhile |
Bram Moolenaar | d5cdbeb | 2005-10-10 20:59:28 +0000 | [diff] [blame] | 52 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 53 | # Return the column of the last word, which is going to be changed. |
| 54 | # Remember the text that comes before it in prepended. |
Bram Moolenaar | d5cdbeb | 2005-10-10 20:59:28 +0000 | [diff] [blame] | 55 | if lastword == -1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 56 | prepended = '' |
| 57 | return byteidx(line, start) |
Bram Moolenaar | d5cdbeb | 2005-10-10 20:59:28 +0000 | [diff] [blame] | 58 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 59 | prepended = line[start : lastword - 1] |
| 60 | return byteidx(line, lastword) |
Bram Moolenaar | e344bea | 2005-09-01 20:46:49 +0000 | [diff] [blame] | 61 | endif |
| 62 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 63 | # Return list of matches. |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 64 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 65 | var base: string = prepended .. abase |
Bram Moolenaar | d5cdbeb | 2005-10-10 20:59:28 +0000 | [diff] [blame] | 66 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 67 | # Don't do anything for an empty base, would result in all the tags in the |
| 68 | # tags file. |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 69 | if base == '' |
| 70 | return [] |
| 71 | endif |
| 72 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 73 | # init cache for vimgrep to empty |
| 74 | grepCache = {} |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 75 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 76 | # Split item in words, keep empty word after "." or "->". |
| 77 | # "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> ['aa', 'bb'], etc. |
| 78 | # We can't use split, because we need to skip nested [...]. |
| 79 | # "aa[...]" -> ['aa', '[...]'], "aa.bb[...]" -> ['aa', 'bb', '[...]'], etc. |
| 80 | var items: list<string> |
| 81 | var s: number = 0 |
| 82 | var arrays: number = 0 |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 83 | while 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 84 | var e: number = base->charidx(match(base, '\.\|->\|\[', s)) |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 85 | if e < 0 |
| 86 | if s == 0 || base[s - 1] != ']' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 87 | items->add(base[s :]) |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 88 | endif |
| 89 | break |
Bram Moolenaar | d5cdbeb | 2005-10-10 20:59:28 +0000 | [diff] [blame] | 90 | endif |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 91 | if s == 0 || base[s - 1] != ']' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 92 | items->add(base[s : e - 1]) |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 93 | endif |
| 94 | if base[e] == '.' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 95 | # skip over '.' |
| 96 | s = e + 1 |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 97 | elseif base[e] == '-' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 98 | # skip over '->' |
| 99 | s = e + 2 |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 100 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 101 | # Skip over [...]. |
| 102 | var n: number = 0 |
| 103 | s = e |
| 104 | ++e |
| 105 | while e < strcharlen(base) |
| 106 | if base[e] == ']' |
| 107 | if n == 0 |
| 108 | break |
| 109 | endif |
| 110 | --n |
| 111 | elseif base[e] == '[' # nested [...] |
| 112 | ++n |
| 113 | endif |
| 114 | ++e |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 115 | endwhile |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 116 | ++e |
| 117 | items->add(base[s : e - 1]) |
| 118 | ++arrays |
| 119 | s = e |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 120 | endif |
| 121 | endwhile |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 122 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 123 | # Find the variable items[0]. |
| 124 | # 1. in current function (like with "gd") |
| 125 | # 2. in tags file(s) (like with ":tag") |
| 126 | # 3. in current file (like with "gD") |
| 127 | var res: list<dict<any>> |
| 128 | if items[0]->searchdecl(false, true) == 0 |
| 129 | # Found, now figure out the type. |
| 130 | # TODO: join previous line if it makes sense |
| 131 | var line: string = getline('.') |
| 132 | var col: number = charcol('.') |
| 133 | if line[: col - 1]->stridx(';') >= 0 |
| 134 | # Handle multiple declarations on the same line. |
| 135 | var col2: number = col - 1 |
Bram Moolenaar | 8c8de83 | 2008-06-24 22:58:06 +0000 | [diff] [blame] | 136 | while line[col2] != ';' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 137 | --col2 |
Bram Moolenaar | 8c8de83 | 2008-06-24 22:58:06 +0000 | [diff] [blame] | 138 | endwhile |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 139 | line = line[col2 + 1 :] |
| 140 | col -= col2 |
Bram Moolenaar | 8c8de83 | 2008-06-24 22:58:06 +0000 | [diff] [blame] | 141 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 142 | if line[: col - 1]->stridx(',') >= 0 |
| 143 | # Handle multiple declarations on the same line in a function |
| 144 | # declaration. |
| 145 | var col2: number = col - 1 |
Bram Moolenaar | 8c8de83 | 2008-06-24 22:58:06 +0000 | [diff] [blame] | 146 | while line[col2] != ',' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 147 | --col2 |
Bram Moolenaar | 8c8de83 | 2008-06-24 22:58:06 +0000 | [diff] [blame] | 148 | endwhile |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 149 | if line[col2 + 1 : col - 1] =~ ' *[^ ][^ ]* *[^ ]' |
| 150 | line = line[col2 + 1 :] |
| 151 | col -= col2 |
Bram Moolenaar | 8c8de83 | 2008-06-24 22:58:06 +0000 | [diff] [blame] | 152 | endif |
| 153 | endif |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 154 | if len(items) == 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 155 | # Completing one word and it's a local variable: May add '[', '.' or |
| 156 | # '->'. |
| 157 | var match: string = items[0] |
| 158 | var kind: string = 'v' |
| 159 | if match(line, '\<' .. match .. '\s*\[') > 0 |
| 160 | match ..= '[' |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 161 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 162 | res = line[: col - 1]->Nextitem([''], 0, true) |
| 163 | if len(res) > 0 |
| 164 | # There are members, thus add "." or "->". |
| 165 | if match(line, '\*[ \t(]*' .. match .. '\>') > 0 |
| 166 | match ..= '->' |
| 167 | else |
| 168 | match ..= '.' |
| 169 | endif |
| 170 | endif |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 171 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 172 | res = [{match: match, tagline: '', kind: kind, info: line}] |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 173 | elseif len(items) == arrays + 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 174 | # Completing one word and it's a local array variable: build tagline |
| 175 | # from declaration line |
| 176 | var match: string = items[0] |
| 177 | var kind: string = 'v' |
| 178 | var tagline: string = "\t/^" .. line .. '$/' |
| 179 | res = [{match: match, tagline: tagline, kind: kind, info: line}] |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 180 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 181 | # Completing "var.", "var.something", etc. |
| 182 | res = line[: col - 1]->Nextitem(items[1 :], 0, true) |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 183 | endif |
| 184 | endif |
| 185 | |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 186 | if len(items) == 1 || len(items) == arrays + 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 187 | # Only one part, no "." or "->": complete from tags file. |
| 188 | var tags: list<dict<any>> |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 189 | if len(items) == 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 190 | tags = taglist('^' .. base) |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 191 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 192 | tags = taglist('^' .. items[0] .. '$') |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 193 | endif |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 194 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 195 | tags |
| 196 | # Remove members, these can't appear without something in front. |
| 197 | ->filter((_, v: dict<any>): bool => |
| 198 | v->has_key('kind') ? v.kind != 'm' : true) |
| 199 | # Remove static matches in other files. |
| 200 | ->filter((_, v: dict<any>): bool => |
| 201 | !v->has_key('static') |
| 202 | || !v['static'] |
| 203 | || bufnr('%') == bufnr(v['filename'])) |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 204 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 205 | res = extendnew(res, tags->map((_, v: dict<any>) => Tag2item(v))) |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 206 | endif |
| 207 | |
| 208 | if len(res) == 0 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 209 | # Find the variable in the tags file(s) |
| 210 | var diclist: list<dict<any>> = taglist('^' .. items[0] .. '$') |
| 211 | # Remove members, these can't appear without something in front. |
| 212 | ->filter((_, v: dict<string>): bool => |
| 213 | v->has_key('kind') ? v.kind != 'm' : true) |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 214 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 215 | res = [] |
| 216 | for i: number in len(diclist)->range() |
| 217 | # New ctags has the "typeref" field. Patched version has "typename". |
| 218 | if diclist[i]->has_key('typename') |
| 219 | res = extendnew(res, diclist[i]['typename']->StructMembers(items[1 :], true)) |
| 220 | elseif diclist[i]->has_key('typeref') |
| 221 | res = extendnew(res, diclist[i]['typeref']->StructMembers(items[1 :], true)) |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 222 | endif |
| 223 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 224 | # For a variable use the command, which must be a search pattern that |
| 225 | # shows the declaration of the variable. |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 226 | if diclist[i]['kind'] == 'v' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 227 | var line: string = diclist[i]['cmd'] |
| 228 | if line[: 1] == '/^' |
| 229 | var col: number = line->charidx(match(line, '\<' .. items[0] .. '\>')) |
| 230 | res = extendnew(res, line[2 : col - 1]->Nextitem(items[1 :], 0, true)) |
| 231 | endif |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 232 | endif |
| 233 | endfor |
| 234 | endif |
| 235 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 236 | if len(res) == 0 && items[0]->searchdecl(true) == 0 |
| 237 | # Found, now figure out the type. |
| 238 | # TODO: join previous line if it makes sense |
| 239 | var line: string = getline('.') |
| 240 | var col: number = charcol('.') |
| 241 | res = line[: col - 1]->Nextitem(items[1 :], 0, true) |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 242 | endif |
| 243 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 244 | # If the last item(s) are [...] they need to be added to the matches. |
| 245 | var last: number = len(items) - 1 |
| 246 | var brackets: string = '' |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 247 | while last >= 0 |
| 248 | if items[last][0] != '[' |
| 249 | break |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 250 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 251 | brackets = items[last] .. brackets |
| 252 | --last |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 253 | endwhile |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 254 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 255 | return res->map((_, v: dict<any>): dict<string> => Tagline2item(v, brackets)) |
| 256 | enddef |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 257 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 258 | def GetAddition( # {{{1 |
| 259 | line: string, |
| 260 | match: string, |
| 261 | memarg: list<dict<any>>, |
| 262 | bracket: bool |
| 263 | ): string |
| 264 | # Guess if the item is an array. |
| 265 | if bracket && match(line, match .. '\s*\[') > 0 |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 266 | return '[' |
| 267 | endif |
| 268 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 269 | # Check if the item has members. |
| 270 | if SearchMembers(memarg, [''], false)->len() > 0 |
| 271 | # If there is a '*' before the name use "->". |
| 272 | if match(line, '\*[ \t(]*' .. match .. '\>') > 0 |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 273 | return '->' |
| 274 | else |
| 275 | return '.' |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 276 | endif |
| 277 | endif |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 278 | return '' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 279 | enddef |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 280 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 281 | def Tag2item(val: dict<any>): dict<any> # {{{1 |
| 282 | # Turn the tag info "val" into an item for completion. |
| 283 | # "val" is is an item in the list returned by taglist(). |
| 284 | # If it is a variable we may add "." or "->". Don't do it for other types, |
| 285 | # such as a typedef, by not including the info that GetAddition() uses. |
| 286 | var res: dict<any> = {match: val['name']} |
Bram Moolenaar | f52c725 | 2006-02-10 23:23:57 +0000 | [diff] [blame] | 287 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 288 | res['extra'] = Tagcmd2extra(val['cmd'], val['name'], val['filename']) |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 289 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 290 | var s: string = Dict2info(val) |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 291 | if s != '' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 292 | res['info'] = s |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 293 | endif |
| 294 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 295 | res['tagline'] = '' |
| 296 | if val->has_key('kind') |
| 297 | var kind: string = val['kind'] |
| 298 | res['kind'] = kind |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 299 | if kind == 'v' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 300 | res['tagline'] = "\t" .. val['cmd'] |
| 301 | res['dict'] = val |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 302 | elseif kind == 'f' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 303 | res['match'] = val['name'] .. '(' |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 304 | endif |
| 305 | endif |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 306 | |
| 307 | return res |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 308 | enddef |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 309 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 310 | def Dict2info(dict: dict<any>): string # {{{1 |
| 311 | # Use all the items in dictionary for the "info" entry. |
| 312 | var info: string = '' |
| 313 | for k: string in dict->keys()->sort() |
| 314 | info ..= k .. repeat(' ', 10 - strlen(k)) |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 315 | if k == 'cmd' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 316 | info ..= dict['cmd'] |
| 317 | ->matchstr('/^\s*\zs.*\ze$/') |
| 318 | ->substitute('\\\(.\)', '\1', 'g') |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 319 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 320 | var dictk: any = dict[k] |
| 321 | if typename(dictk) != 'string' |
| 322 | info ..= dictk->string() |
| 323 | else |
| 324 | info ..= dictk |
| 325 | endif |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 326 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 327 | info ..= "\n" |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 328 | endfor |
| 329 | return info |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 330 | enddef |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 331 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 332 | def ParseTagline(line: string): dict<any> # {{{1 |
| 333 | # Parse a tag line and return a dictionary with items like taglist() |
| 334 | var l: list<string> = split(line, "\t") |
| 335 | var d: dict<any> |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 336 | if len(l) >= 3 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 337 | d['name'] = l[0] |
| 338 | d['filename'] = l[1] |
| 339 | d['cmd'] = l[2] |
| 340 | var n: number = 2 |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 341 | if l[2] =~ '^/' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 342 | # Find end of cmd, it may contain Tabs. |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 343 | while n < len(l) && l[n] !~ '/;"$' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 344 | ++n |
| 345 | d['cmd'] ..= ' ' .. l[n] |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 346 | endwhile |
| 347 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 348 | for i: number in range(n + 1, len(l) - 1) |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 349 | if l[i] == 'file:' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 350 | d['static'] = 1 |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 351 | elseif l[i] !~ ':' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 352 | d['kind'] = l[i] |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 353 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 354 | d[l[i]->matchstr('[^:]*')] = l[i]->matchstr(':\zs.*') |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 355 | endif |
| 356 | endfor |
| 357 | endif |
| 358 | |
| 359 | return d |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 360 | enddef |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 361 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 362 | def Tagline2item(val: dict<any>, brackets: string): dict<string> # {{{1 |
| 363 | # Turn a match item "val" into an item for completion. |
| 364 | # "val['match']" is the matching item. |
| 365 | # "val['tagline']" is the tagline in which the last part was found. |
| 366 | var line: string = val['tagline'] |
| 367 | var add: string = GetAddition(line, val['match'], [val], brackets == '') |
| 368 | var res: dict<string> = {word: val['match'] .. brackets .. add} |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 369 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 370 | if val->has_key('info') |
| 371 | # Use info from Tag2item(). |
| 372 | res['info'] = val['info'] |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 373 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 374 | # Parse the tag line and add each part to the "info" entry. |
| 375 | var s: string = ParseTagline(line)->Dict2info() |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 376 | if s != '' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 377 | res['info'] = s |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 378 | endif |
| 379 | endif |
| 380 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 381 | if val->has_key('kind') |
| 382 | res['kind'] = val['kind'] |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 383 | elseif add == '(' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 384 | res['kind'] = 'f' |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 385 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 386 | var s: string = line->matchstr('\t\(kind:\)\=\zs\S\ze\(\t\|$\)') |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 387 | if s != '' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 388 | res['kind'] = s |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 389 | endif |
| 390 | endif |
| 391 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 392 | if val->has_key('extra') |
| 393 | res['menu'] = val['extra'] |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 394 | return res |
Bram Moolenaar | 8b6144b | 2006-02-08 09:20:24 +0000 | [diff] [blame] | 395 | endif |
Bram Moolenaar | f52c725 | 2006-02-10 23:23:57 +0000 | [diff] [blame] | 396 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 397 | # Isolate the command after the tag and filename. |
| 398 | var s: string = line->matchstr('[^\t]*\t[^\t]*\t\zs\(/^.*$/\|[^\t]*\)\ze\(;"\t\|\t\|$\)') |
Bram Moolenaar | f52c725 | 2006-02-10 23:23:57 +0000 | [diff] [blame] | 399 | if s != '' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 400 | res['menu'] = s->Tagcmd2extra(val['match'], line->matchstr('[^\t]*\t\zs[^\t]*\ze\t')) |
Bram Moolenaar | f52c725 | 2006-02-10 23:23:57 +0000 | [diff] [blame] | 401 | endif |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 402 | return res |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 403 | enddef |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 404 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 405 | def Tagcmd2extra( # {{{1 |
| 406 | cmd: string, |
| 407 | name: string, |
| 408 | fname: string |
| 409 | ): string |
| 410 | # Turn a command from a tag line to something that is useful in the menu |
| 411 | var x: string |
| 412 | if cmd =~ '^/^' |
| 413 | # The command is a search command, useful to see what it is. |
| 414 | x = cmd |
| 415 | ->matchstr('^/^\s*\zs.*\ze$/') |
| 416 | ->substitute('\<' .. name .. '\>', '@@', '') |
| 417 | ->substitute('\\\(.\)', '\1', 'g') |
| 418 | .. ' - ' .. fname |
| 419 | elseif cmd =~ '^\d*$' |
| 420 | # The command is a line number, the file name is more useful. |
| 421 | x = fname .. ' - ' .. cmd |
Bram Moolenaar | f52c725 | 2006-02-10 23:23:57 +0000 | [diff] [blame] | 422 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 423 | # Not recognized, use command and file name. |
| 424 | x = cmd .. ' - ' .. fname |
Bram Moolenaar | f52c725 | 2006-02-10 23:23:57 +0000 | [diff] [blame] | 425 | endif |
| 426 | return x |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 427 | enddef |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 428 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 429 | def Nextitem( # {{{1 |
| 430 | lead: string, |
| 431 | items: list<string>, |
| 432 | depth: number, |
| 433 | all: bool |
| 434 | ): list<dict<string>> |
| 435 | # Find composing type in "lead" and match items[0] with it. |
| 436 | # Repeat this recursively for items[1], if it's there. |
| 437 | # When resolving typedefs "depth" is used to avoid infinite recursion. |
| 438 | # Return the list of matches. |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 439 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 440 | # Use the text up to the variable name and split it in tokens. |
| 441 | var tokens: list<string> = split(lead, '\s\+\|\<') |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 442 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 443 | # Try to recognize the type of the variable. This is rough guessing... |
| 444 | var res: list<dict<string>> |
| 445 | for tidx: number in len(tokens)->range() |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 446 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 447 | # Skip tokens starting with a non-ID character. |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 448 | if tokens[tidx] !~ '^\h' |
| 449 | continue |
| 450 | endif |
| 451 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 452 | # Recognize "struct foobar" and "union foobar". |
| 453 | # Also do "class foobar" when it's C++ after all (doesn't work very well |
| 454 | # though). |
| 455 | if (tokens[tidx] == 'struct' |
| 456 | || tokens[tidx] == 'union' |
| 457 | || tokens[tidx] == 'class') |
| 458 | && tidx + 1 < len(tokens) |
| 459 | res = StructMembers(tokens[tidx] .. ':' .. tokens[tidx + 1], items, all) |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 460 | break |
| 461 | endif |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 462 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 463 | # TODO: add more reserved words |
| 464 | if ['int', 'short', 'char', 'float', |
| 465 | 'double', 'static', 'unsigned', 'extern']->index(tokens[tidx]) >= 0 |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 466 | continue |
| 467 | endif |
| 468 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 469 | # Use the tags file to find out if this is a typedef. |
| 470 | var diclist: list<dict<any>> = taglist('^' .. tokens[tidx] .. '$') |
| 471 | for tagidx: number in len(diclist)->range() |
| 472 | var item: dict<any> = diclist[tagidx] |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 473 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 474 | # New ctags has the "typeref" field. Patched version has "typename". |
| 475 | if item->has_key('typeref') |
| 476 | res = extendnew(res, item['typeref']->StructMembers(items, all)) |
| 477 | continue |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 478 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 479 | if item->has_key('typename') |
| 480 | res = extendnew(res, item['typename']->StructMembers(items, all)) |
| 481 | continue |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 482 | endif |
| 483 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 484 | # Only handle typedefs here. |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 485 | if item['kind'] != 't' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 486 | continue |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 487 | endif |
| 488 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 489 | # Skip matches local to another file. |
| 490 | if item->has_key('static') && item['static'] |
| 491 | && bufnr('%') != bufnr(item['filename']) |
| 492 | continue |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 493 | endif |
| 494 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 495 | # For old ctags we recognize "typedef struct aaa" and |
| 496 | # "typedef union bbb" in the tags file command. |
| 497 | var cmd: string = item['cmd'] |
| 498 | var ei: number = cmd->charidx(matchend(cmd, 'typedef\s\+')) |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 499 | if ei > 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 500 | var cmdtokens: list<string> = cmd[ei :]->split('\s\+\|\<') |
| 501 | if len(cmdtokens) > 1 |
| 502 | if cmdtokens[0] == 'struct' |
| 503 | || cmdtokens[0] == 'union' |
| 504 | || cmdtokens[0] == 'class' |
| 505 | var name: string = '' |
| 506 | # Use the first identifier after the "struct" or "union" |
| 507 | for ti: number in (len(cmdtokens) - 1)->range() |
| 508 | if cmdtokens[ti] =~ '^\w' |
| 509 | name = cmdtokens[ti] |
| 510 | break |
| 511 | endif |
| 512 | endfor |
| 513 | if name != '' |
| 514 | res = extendnew(res, StructMembers(cmdtokens[0] .. ':' .. name, items, all)) |
| 515 | endif |
| 516 | elseif depth < 10 |
| 517 | # Could be "typedef other_T some_T". |
| 518 | res = extendnew(res, cmdtokens[0]->Nextitem(items, depth + 1, all)) |
| 519 | endif |
| 520 | endif |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 521 | endif |
| 522 | endfor |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 523 | if len(res) > 0 |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 524 | break |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 525 | endif |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 526 | endfor |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 527 | |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 528 | return res |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 529 | enddef |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 530 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 531 | def StructMembers( # {{{1 |
| 532 | atypename: string, |
| 533 | items: list<string>, |
| 534 | all: bool |
| 535 | ): list<dict<string>> |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 536 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 537 | # Search for members of structure "typename" in tags files. |
| 538 | # Return a list with resulting matches. |
| 539 | # Each match is a dictionary with "match" and "tagline" entries. |
| 540 | # When "all" is true find all, otherwise just return 1 if there is any member. |
| 541 | |
| 542 | # Todo: What about local structures? |
| 543 | var fnames: string = tagfiles() |
| 544 | ->map((_, v: string) => escape(v, ' \#%')) |
| 545 | ->join() |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 546 | if fnames == '' |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 547 | return [] |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 548 | endif |
| 549 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 550 | var typename: string = atypename |
| 551 | var qflist: list<dict<any>> |
| 552 | var cached: number = 0 |
| 553 | var n: string |
| 554 | if !all |
| 555 | n = '1' # stop at first found match |
| 556 | if grepCache->has_key(typename) |
| 557 | qflist = grepCache[typename] |
| 558 | cached = 1 |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 559 | endif |
Bram Moolenaar | 1f35bf9 | 2006-03-07 22:38:47 +0000 | [diff] [blame] | 560 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 561 | n = '' |
Bram Moolenaar | 1f35bf9 | 2006-03-07 22:38:47 +0000 | [diff] [blame] | 562 | endif |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 563 | if !cached |
| 564 | while 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 565 | execute 'silent! keepjumps noautocmd ' |
| 566 | .. n .. 'vimgrep ' .. '/\t' .. typename .. '\(\t\|$\)/j ' |
| 567 | .. fnames |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 568 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 569 | qflist = getqflist() |
| 570 | if len(qflist) > 0 || match(typename, '::') < 0 |
| 571 | break |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 572 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 573 | # No match for "struct:context::name", remove "context::" and try again. |
| 574 | typename = typename->substitute(':[^:]*::', ':', '') |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 575 | endwhile |
| 576 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 577 | if !all |
| 578 | # Store the result to be able to use it again later. |
| 579 | grepCache[typename] = qflist |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 580 | endif |
Bram Moolenaar | 1056d98 | 2006-03-09 22:37:52 +0000 | [diff] [blame] | 581 | endif |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 582 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 583 | # Skip over [...] items |
| 584 | var idx: number = 0 |
| 585 | var target: string |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 586 | while 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 587 | if idx >= len(items) |
| 588 | target = '' # No further items, matching all members |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 589 | break |
| 590 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 591 | if items[idx][0] != '[' |
| 592 | target = items[idx] |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 593 | break |
| 594 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 595 | ++idx |
Bram Moolenaar | 20aac6c | 2018-09-02 21:07:30 +0200 | [diff] [blame] | 596 | endwhile |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 597 | # Put matching members in matches[]. |
| 598 | var matches: list<dict<string>> |
| 599 | for l: dict<any> in qflist |
| 600 | var memb: string = l['text']->matchstr('[^\t]*') |
| 601 | if memb =~ '^' .. target |
| 602 | # Skip matches local to another file. |
| 603 | if match(l['text'], "\tfile:") < 0 |
| 604 | || bufnr('%') == l['text']->matchstr('\t\zs[^\t]*')->bufnr() |
| 605 | var item: dict<string> = {match: memb, tagline: l['text']} |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 606 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 607 | # Add the kind of item. |
| 608 | var s: string = l['text']->matchstr('\t\(kind:\)\=\zs\S\ze\(\t\|$\)') |
| 609 | if s != '' |
| 610 | item['kind'] = s |
| 611 | if s == 'f' |
| 612 | item['match'] = memb .. '(' |
| 613 | endif |
| 614 | endif |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 615 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 616 | matches->add(item) |
Bram Moolenaar | eb94e55 | 2006-03-11 21:35:11 +0000 | [diff] [blame] | 617 | endif |
Bram Moolenaar | a4a0838 | 2005-09-09 19:52:02 +0000 | [diff] [blame] | 618 | endif |
Bram Moolenaar | dd2436f | 2005-09-05 22:14:46 +0000 | [diff] [blame] | 619 | endfor |
| 620 | |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 621 | if len(matches) > 0 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 622 | # Skip over next [...] items |
| 623 | ++idx |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 624 | while 1 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 625 | if idx >= len(items) |
| 626 | return matches # No further items, return the result. |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 627 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 628 | if items[idx][0] != '[' |
| 629 | break |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 630 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 631 | ++idx |
Bram Moolenaar | 0e5bd96 | 2006-02-04 00:59:56 +0000 | [diff] [blame] | 632 | endwhile |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 633 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 634 | # More items following. For each of the possible members find the |
| 635 | # matching following members. |
| 636 | return SearchMembers(matches, items[idx :], all) |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 637 | endif |
| 638 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 639 | # Failed to find anything. |
Bram Moolenaar | caa0fcf | 2005-09-07 21:21:14 +0000 | [diff] [blame] | 640 | return [] |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 641 | enddef |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 642 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 643 | def SearchMembers( # {{{1 |
| 644 | matches: list<dict<any>>, |
| 645 | items: list<string>, |
| 646 | all: bool |
| 647 | ): list<dict<string>> |
| 648 | |
| 649 | # For matching members, find matches for following items. |
| 650 | # When "all" is true find all, otherwise just return 1 if there is any member. |
| 651 | var res: list<dict<string>> |
| 652 | for i: number in len(matches)->range() |
| 653 | var typename: string = '' |
| 654 | var line: string |
| 655 | if matches[i]->has_key('dict') |
| 656 | if matches[i]['dict']->has_key('typename') |
| 657 | typename = matches[i]['dict']['typename'] |
| 658 | elseif matches[i]['dict']->has_key('typeref') |
| 659 | typename = matches[i]['dict']['typeref'] |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 660 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 661 | line = "\t" .. matches[i]['dict']['cmd'] |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 662 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 663 | line = matches[i]['tagline'] |
| 664 | var eb: number = matchend(line, '\ttypename:') |
| 665 | var e: number = charidx(line, eb) |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 666 | if e < 0 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 667 | eb = matchend(line, '\ttyperef:') |
| 668 | e = charidx(line, eb) |
Bram Moolenaar | 76b92b2 | 2006-03-24 22:46:53 +0000 | [diff] [blame] | 669 | endif |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 670 | if e > 0 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 671 | # Use typename field |
| 672 | typename = line->matchstr('[^\t]*', eb) |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 673 | endif |
| 674 | endif |
Bram Moolenaar | 1f35bf9 | 2006-03-07 22:38:47 +0000 | [diff] [blame] | 675 | |
Bram Moolenaar | 280f126 | 2006-01-30 00:14:18 +0000 | [diff] [blame] | 676 | if typename != '' |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 677 | res = extendnew(res, StructMembers(typename, items, all)) |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 678 | else |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 679 | # Use the search command (the declaration itself). |
| 680 | var sb: number = line->match('\t\zs/^') |
| 681 | var s: number = charidx(line, sb) |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 682 | if s > 0 |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 683 | var e: number = line |
| 684 | ->charidx(match(line, '\<' .. matches[i]['match'] .. '\>', sb)) |
| 685 | if e > 0 |
| 686 | res = extendnew(res, line[s : e - 1]->Nextitem(items, 0, all)) |
| 687 | endif |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 688 | endif |
| 689 | endif |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 690 | if !all && len(res) > 0 |
Bram Moolenaar | 1f35bf9 | 2006-03-07 22:38:47 +0000 | [diff] [blame] | 691 | break |
| 692 | endif |
Bram Moolenaar | f75a963 | 2005-09-13 21:20:47 +0000 | [diff] [blame] | 693 | endfor |
| 694 | return res |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 695 | enddef |
| 696 | #}}}1 |
Bram Moolenaar | b6b046b | 2011-12-30 13:11:27 +0100 | [diff] [blame] | 697 | |
Bram Moolenaar | a4d131d | 2021-12-27 21:33:07 +0000 | [diff] [blame] | 698 | # vim: noet sw=2 sts=2 |