macotron.files
Find files and folders by name in an index that Macotron keeps in memory. It answers in milliseconds, but knows only the folders you configure.
await macotron.files.configure({ roots: ["~", "/Applications"], ignore: ["node_modules", "Library"] });
const hits = await macotron.files.search("budget", { kind: "pdf", limit: 5 });
for (const h of hits) console.log(h.path);
The index runs in a helper process that ships inside Macotron. It starts on the first call. If the helper is missing or crashes twice, search rejects with "file indexer unavailable"; fall back to macotron.spotlight then.
Configuring
configure(opts: { roots?, ignore?, hidden?, ignoreFiles? }): Promise<void>
Sets the folders to index and the rules for skipping things. It replaces the whole previous configuration. A call with the same settings does nothing. Any change starts a rebuild in the background. While it runs, searches answer from the previous index, or return nothing on the first build.
| Option | Default | What it does |
|---|---|---|
roots | ["~", "/Applications"] | Folders to index. ~ expands to home. Roots can nest: a nested root is indexed with its own rules, so ~/Library/CloudStorage can be a root while Library is ignored. |
ignore | [] | Gitignore-style globs, matched against the path relative to its root and against the bare name. "node_modules" skips every folder with that name; "Library/Caches" skips that one path. |
hidden | false | Index names that start with a dot. |
ignoreFiles | true | Honor the .gitignore, .ignore and .macotronignore files found in the folders. |
The index never looks inside bundles such as .app, .framework or .photoslibrary; each bundle is one entry. Symbolic links are indexed but not followed.
When the helper is unavailable, configure resolves and does nothing.
reindex(): Promise<void>
Drops the index and walks the roots again.
Searching
search(query: string, opts?: { folder?, kind?, dirsOnly?, limit? }): Promise<Array<{ path, name, isDir, score, modified }>>
Returns matches, best first. Matching ignores case, and ranks matches in this order:
- The exact name.
- A prefix of the name.
- A prefix of a word in the name:
budgetfindsQ3 Budget.pdf. Words split on spaces,-,_,.and camelCase. - Text anywhere in the name.
- The letters in order in the name:
ctrctfindscontract. - The letters in order in the path below the root:
docdadfindsDocuments/Dad.
The last two apply only to words of three or more letters. Spaces separate words that must all match. Ties go to the less deeply nested path, then the shorter name. An empty query returns [].
| Option | What it does |
|---|---|
folder | Only return results inside this folder. ~ expands. |
kind | A file extension without the dot, such as "pdf". Case does not matter. |
dirsOnly | Only return folders. |
limit | The most results to return. Default 50, maximum 500. |
Each result has the absolute path, the name, isDir, the match score (higher is better), and modified in seconds since 1970.
status(): Promise<{ entries, indexing, watching, roots, lastIndexed, memoryBytes, available }>
Reports on the index: how many entries it holds, whether a build is running (indexing), whether it is watching the folders for changes, the roots of the live index, when the last build finished (lastIndexed, seconds since 1970), and its memory use in bytes. available is false when the helper cannot start, and then every other field is zero or empty.
const s = await macotron.files.status();
if (!s.available) macotron.checks([{ title: "File index", ok: false, message: "Using Spotlight instead" }]);
See also
- macotron.spotlight to search the whole disk, slower, with path completion.
- macotron.launcher to show results as the user types.
- The
file-search.jsplugin.