Skip to content

Commit

Permalink
Improve FileSearchProvider (exclude grob support + no command)
Browse files Browse the repository at this point in the history
  • Loading branch information
SchoofsKelvin committed Apr 13, 2019
1 parent 119f2bd commit 543c95c
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 36 deletions.
14 changes: 8 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,7 @@
"postinstall": "node ./node_modules/vscode/bin/install"
},
"devDependencies": {
"@types/minimatch": "^3.0.3",
"@types/node": "^8.10.43",
"@types/request": "^2.48.1",
"@types/ssh2": "^0.5.35",
Expand All @@ -452,6 +453,7 @@
"dependencies": {
"event-stream": "^3.3.4",
"jsonc-parser": "^2.0.0",
"minimatch": "^3.0.4",
"socks": "^2.2.0",
"ssh2": "^0.8.2",
"winreg": "^1.2.4"
Expand Down
59 changes: 29 additions & 30 deletions src/searchProvider.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,56 @@

import * as minimatch from 'minimatch';
import { posix as path } from 'path';
import { createInterface } from 'readline';
import { ClientChannel } from 'ssh2';
import * as vscode from 'vscode';
import { Manager } from './manager';
import { toPromise } from './toPromise';

export class SearchProvider implements vscode.FileSearchProvider {
protected cache: [vscode.CancellationToken, Promise<string[]>][] = [];
protected cache: [vscode.CancellationToken, Promise<vscode.Uri[]>][] = [];
constructor(protected manager: Manager) { }
public async provideFileSearchResults(query: vscode.FileSearchQuery, options: vscode.FileSearchOptions, token: vscode.CancellationToken): Promise<vscode.Uri[]> {
const { folder, session = token } = options;
const { folder, session } = options;
let cached = this.cache.find(([t]) => session === t);
if (!cached) {
if (!cached && session) {
cached = [session, this.buildTree(options, session)] as SearchProvider['cache'][0];
this.cache.push(cached);
session.onCancellationRequested(() => {
this.cache.splice(this.cache.indexOf(cached!));
});
} else if (!cached) {
cached = [token, this.buildTree(options, token)] as SearchProvider['cache'][0];
}
const paths = await cached[1];
console.log('Found', paths.length);
if (token.isCancellationRequested) return [];
const pattern = query.pattern.toLowerCase();
return paths.map<vscode.Uri | null>((relative) => {
if (!relative.toLowerCase().includes(pattern)) return null;
return folder.with({ path: path.join(folder.path, relative) });
if (!relative.path.toLowerCase().includes(pattern)) return null;
return folder.with({ path: path.join(folder.path, relative.path) });
}).filter(s => !!s) as vscode.Uri[];
}
protected async buildTree(options: vscode.FileSearchOptions, token: vscode.CancellationToken): Promise<string[]> {
protected async buildTree(options: vscode.FileSearchOptions, token: vscode.CancellationToken): Promise<vscode.Uri[]> {
const { folder } = options;
const fs = await this.manager.getFs(folder);
if (!fs || token.isCancellationRequested) return [];
const cmd = `ls -AQ1R "${fs.absoluteFromRelative(folder.path)}"`;
console.log('Creating tree with command:', cmd);
const exec = await toPromise<ClientChannel>(cb => fs.client.exec(cmd, cb)).catch(() => null);
if (!exec || token.isCancellationRequested) return [];
const res: string[] = [];
const rl = createInterface(exec);
let root = '';
rl.on('line', (line: string) => {
if (!line) return;
if (line.endsWith(':')) {
root = JSON.parse(line.substr(0, line.length - 1));
} else {
let relative = JSON.parse(line);
relative = path.join(root, relative);
relative = fs.relativeFromAbsolute(relative);
res.push(relative);
}
});
token.onCancellationRequested(rl.close, rl);
await toPromise(cb => rl.on('close', cb));
const excludes = options.excludes.map(e => minimatch.makeRe(e, { nocase: true }));
const exclude = (p: string) => excludes.some(reg => reg.test(p));
const res: vscode.Uri[] = [];
async function readDirectory(uri: vscode.Uri) {
if (token.isCancellationRequested) return;
const entries = await fs!.readDirectory(uri).catch(() => [] as never);
if (token.isCancellationRequested) return;
return Promise.all(entries.map(([name, type]) => {
if (token.isCancellationRequested) return;
const joined = path.join(uri.path, name);
if (exclude(joined)) return;
// tslint:disable-next-line:no-bitwise
if (type & vscode.FileType.Directory) {
return readDirectory(uri.with({ path: joined }));
} else {
res.push(uri.with({ path: joined }));
}
}));
}
await readDirectory(folder);
return res;
}
}

0 comments on commit 543c95c

Please sign in to comment.