English | 繁體中文
Search Enhancement — ctags Symbol SearchFind any function, variable, or macro in million-line C/C++ codebases as fast as you can type. Multi-keyword search backed by a Universal Ctags index — no language server, no build system, no IntelliSense database. Tuned for FreeRTOS, kernel, embedded, and legacy projects; works with any language ctags can index.
Type
Why this over
|
| You type | Word match (default) | Partial match |
|---|---|---|
task create |
Names containing the whole words task and create: PSF_EVENT_TASK_CREATE, trcKERNEL_HOOKS_TASK_CREATE_FAILED |
Also names where the keyword is only part of a word: xTaskCreateStatic, vTaskCreate |
opt tcp ms |
Nothing — ms is not a whole word of any symbol |
TCP_OPT_MSS, TCP_OPT_MSS_LEN, TCP_BUILD_MSS_OPTION |
tcp_opt |
Joined with underscores, the words must be adjacent and in that order: TCP_OPT_MSS, LWIP_TCP_OPT_LENGTH. A name with the two words apart or reversed does not match |
Same rule, but each word may be a substring |
Switch modes from the panel's ... menu (Partial Match Mode). Partial match is the one to reach for on camelCase codebases and abbreviations; word match keeps big C trees noise-free.

opt tcp ms finds nothing in word match; Partial Match Mode finds the 13 *_MSS_* symbols.
Settings
All settings live under the searchEnhancement.* namespace. Open the Settings UI (Ctrl + ,) and search for Search Enhancement, or edit settings.json directly.
| Setting | Type | Default | Description |
|---|---|---|---|
tagsFilePaths |
string[] |
[] (falls back to ${workspaceFolder}/.tags) |
One or more ctags index files. Absolute paths or ${workspaceFolder}/... templates are both accepted. resource-scoped so each folder of a multi-root workspace can configure its own. |
debounceTime |
number |
600 |
Milliseconds to wait after the last keystroke before firing a search. Lower = more responsive but more CPU; higher = laggier but cheaper. |
defaultGroupBy |
"name" | "file" |
"name" |
Initial grouping of results when the panel opens. Can be switched live from the panel's ... menu without reloading. |
warmTagsCache |
"startup" | "viewOpen" | "off" |
"startup" |
When to pre-parse the configured .tags files in the background. startup warms as soon as VS Code finishes starting; viewOpen waits until the search view opens; off parses on the first search instead. Warming keeps the parsed symbols in memory: negligible for a typical project, ~500–750 MB for a 1.65 M-symbol index. |
precomputeSegments |
boolean |
true |
Precompute lowercased, underscore-split words at parse time so per-keystroke filtering can skip the work. Roughly 3–4× faster searches on large indexes; costs roughly 50–100 MB of memory per million symbols. |
profileSearch |
boolean |
false |
Log per-stage timings to the Search Enhancement output channel for each search. Use it when reporting a slow search; leave off in normal use. |
Advanced: index paths, memory trade-off, diagnosing slow searches
Tags file paths
- When
tagsFilePathsis empty:- If the legacy
searchEnhancement.tagsFilePath(deprecated) has a custom value, it is migrated intotagsFilePaths[0]and persisted to your settings. - Otherwise the default
${workspaceFolder}/.tagsis used at runtime without modifying any settings file.
- If the legacy
searchEnhancement.tagsFilePath(singular) is retained only for migration compatibility; new setups should usetagsFilePaths.searchEnhancement.warmTagsCacheOnViewOpen(boolean) is deprecated in favour ofwarmTagsCache. An explicitfalseis still honoured asoffwhilewarmTagsCacheis unset.
Memory / speed trade-off (precomputeSegments)
The default (true) is tuned for typical dev machines and large codebases — on a 1.65 M-symbol index it cuts the per-keystroke filter stage from ~0.4 s to ~0.1 s. (The rest of the 0.5.0 speed-up, ~3 s to ~100 ms, came from skipping the cross-file dedupe when only one .tags file is configured; this setting does not affect that.) If you index a smaller project or are on a memory-constrained machine, set it to false to save the per-symbol cache (~50–100 MB per million symbols). Toggling takes effect on the next search; the parsed-tags cache is cleared automatically.
Diagnosing slow searches (profileSearch)
Enable the setting, then open View → Output and pick Search Enhancement from the channel picker on the right. On a cache miss, parser phases and a heap snapshot are logged before the search block:
[00:55:05] Parse .tags "D:\project\.tags"
read file 737.8ms (290.6 MiB)
split lines 113.2ms (1652591 lines)
parse rows 1565.2ms (1652526 symbols)
precompute segments 545.0ms
---
parse total 2961.2ms
heap used snapshot 31.5 -> 777.9 MiB (+746.5 MiB)
Each search then appends a block like:
[14:32:05] Search "port" partial=false groupBy=name
resolve paths 0.2ms
tags cache 45.3ms (1 files, 1 miss)
dedupe 0.0ms (47288 symbols)
filter 18.7ms (47288 → 137 matches)
build results 0.4ms
post message 0.1ms
---
extension total 64.7ms
webview render 12.5ms (137 results)
---
end-to-end total 77.2ms
To compare a cold first search against background warm-up, enable profileSearch, set warmTagsCache to off, reload the window, and run one search. Then set it back to startup, reload again, wait for the Tags warm-up profile block, and run the same search. Reloading between runs prevents one mode's parsed cache from affecting the other.
If background warm-up is off or has not finished yet, the first search pays the one-time tags cache parse cost proportional to the index size; later searches reuse the parsed result.
Contributing
Contributions, bug reports and feature requests are welcome. See CONTRIBUTING.md for details.
Developing
npm install
npm run compile
Press F5 in VS Code to launch a development host with the extension loaded.
Tests:
npm test # unit + integration
npm run test:unit # unit only — runs in plain Node, no VS Code needed
npm run test:integration # e2e against a real VS Code instance
License
This project is licensed under the MIT license.
Acknowledgements
Icon adapted from SVG Repo.


