Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export class SettingsDocument {
return this.provideFilesAssociationsCompletionItems(location, position);
}

// files.exclude, search.exclude
if (location.path[0] === 'files.exclude' || location.path[0] === 'search.exclude') {
// files.exclude, search.exclude, explorer.autoRevealExclude
if (location.path[0] === 'files.exclude' || location.path[0] === 'search.exclude' || location.path[0] === 'explorer.autoRevealExclude') {
return this.provideExcludeCompletionItems(location, position);
}

Expand Down
7 changes: 5 additions & 2 deletions src/vs/workbench/common/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ export class ResourceGlobMatcher extends Disposable {
}
}

matches(resource: URI): boolean {
matches(
resource: URI,
hasSibling?: (name: string) => boolean
): boolean {
const folder = this.contextService.getWorkspaceFolder(resource);

let expressionForRoot: ParsedExpression | undefined;
Expand All @@ -108,6 +111,6 @@ export class ResourceGlobMatcher extends Disposable {
resourcePathToMatch = resource.fsPath; // TODO@isidor: support non-file URIs
}

return !!expressionForRoot && typeof resourcePathToMatch === 'string' && !!expressionForRoot(resourcePathToMatch);
return !!expressionForRoot && typeof resourcePathToMatch === 'string' && !!expressionForRoot(resourcePathToMatch, undefined, hasSibling);
}
}
51 changes: 50 additions & 1 deletion src/vs/workbench/contrib/files/browser/explorerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ import { IProgressService, ProgressLocation, IProgressNotificationOptions, IProg
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { RunOnceScheduler } from 'vs/base/common/async';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IExpression } from 'vs/base/common/glob';
import { ResourceGlobMatcher } from 'vs/workbench/common/resources';

export const UNDO_REDO_SOURCE = new UndoRedoSource();

Expand All @@ -39,6 +41,7 @@ export class ExplorerService implements IExplorerService {
private model: ExplorerModel;
private onFileChangesScheduler: RunOnceScheduler;
private fileChangeEvents: FileChangesEvent[] = [];
private revealExcludeMatcher: ResourceGlobMatcher;

constructor(
@IFileService private fileService: IFileService,
Expand Down Expand Up @@ -130,6 +133,11 @@ export class ExplorerService implements IExplorerService {
this.refresh(false);
}
}));
this.revealExcludeMatcher = new ResourceGlobMatcher(
(uri) => getRevealExcludes(configurationService.getValue<IFilesConfiguration>({ resource: uri })),
(event) => event.affectsConfiguration('explorer.autoRevealExclude'),
contextService, configurationService);
this.disposables.add(this.revealExcludeMatcher);
}

get roots(): ExplorerItem[] {
Expand Down Expand Up @@ -254,8 +262,14 @@ export class ExplorerService implements IExplorerService {
return;
}

// If file or parent matches exclude patterns, do not reveal unless reveal argument is 'force'
const ignoreRevealExcludes = reveal === 'force';

const fileStat = this.findClosest(resource);
if (fileStat) {
if (!this.shouldAutoRevealItem(fileStat, ignoreRevealExcludes)) {
return;
}
await this.view.selectResource(fileStat.resource, reveal);
return Promise.resolve(undefined);
}
Expand All @@ -277,7 +291,10 @@ export class ExplorerService implements IExplorerService {
const item = root.find(resource);
await this.view.refresh(true, root);

// Select and Reveal
// Once item is resolved, check again if folder should be expanded
if (item && !this.shouldAutoRevealItem(item, ignoreRevealExcludes)) {
return;
}
await this.view.selectResource(item ? item.resource : undefined, reveal);
} catch (error) {
root.isError = true;
Expand Down Expand Up @@ -395,6 +412,28 @@ export class ExplorerService implements IExplorerService {
}
}

// Check if an item matches a explorer.autoRevealExclude pattern
private shouldAutoRevealItem(item: ExplorerItem | undefined, ignore: boolean): boolean {
if (item === undefined || ignore) {
return true;
}
if (this.revealExcludeMatcher.matches(item.resource, name => !!(item.parent && item.parent.getChild(name)))) {
return false;
}
const root = item.root;
let currentItem = item.parent;
while (currentItem !== root) {
if (currentItem === undefined) {
return true;
}
if (this.revealExcludeMatcher.matches(currentItem.resource)) {
return false;
}
currentItem = currentItem.parent;
}
return true;
}

private async onConfigurationUpdated(configuration: IFilesConfiguration, event?: IConfigurationChangeEvent): Promise<void> {
let shouldRefresh = false;

Expand Down Expand Up @@ -440,3 +479,13 @@ function doesFileEventAffect(item: ExplorerItem, view: IExplorerView, events: Fi

return false;
}

function getRevealExcludes(configuration: IFilesConfiguration): IExpression {
const revealExcludes = configuration && configuration.explorer && configuration.explorer.autoRevealExclude;

if (!revealExcludes) {
return {};
}

return revealExcludes;
}
2 changes: 1 addition & 1 deletion src/vs/workbench/contrib/files/browser/fileCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ CommandsRegistry.registerCommand({
const explorerView = viewlet.getExplorerView();
if (explorerView) {
explorerView.setExpanded(true);
await explorerService.select(uri, true);
await explorerService.select(uri, 'force');
explorerView.focus();
}
} else {
Expand Down
24 changes: 24 additions & 0 deletions src/vs/workbench/contrib/files/browser/files.contribution.ts
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,30 @@ configurationRegistry.registerConfiguration({
],
'description': nls.localize('autoReveal', "Controls whether the explorer should automatically reveal and select files when opening them.")
},
'explorer.autoRevealExclude': {
'type': 'object',
'markdownDescription': nls.localize('autoRevealExclude', "Configure glob patterns for excluding files and folders from being revealed and selected in the explorer when they are opened. Read more about glob patterns [here](https://code.visualstudio.com/docs/editor/codebasics#_advanced-search-options)."),
'default': { '**/node_modules': true, '**/bower_components': true },
'additionalProperties': {
'anyOf': [
{
'type': 'boolean',
'description': nls.localize('explorer.autoRevealExclude.boolean', "The glob pattern to match file paths against. Set to true or false to enable or disable the pattern."),
},
{
type: 'object',
properties: {
when: {
type: 'string', // expression ({ "**/*.js": { "when": "$(basename).js" } })
pattern: '\\w*\\$\\(basename\\)\\w*',
default: '$(basename).ext',
description: nls.localize('explorer.autoRevealExclude.when', 'Additional check on the siblings of a matching file. Use $(basename) as variable for the matching file name.')
}
}
}
]
}
},
'explorer.enableDragAndDrop': {
'type': 'boolean',
'description': nls.localize('enableDragAndDrop', "Controls whether the explorer should allow to move files and folders via drag and drop. This setting only effects drag and drop from inside the explorer."),
Expand Down
6 changes: 3 additions & 3 deletions src/vs/workbench/contrib/files/browser/views/explorerView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ export class ExplorerView extends ViewPane implements IExplorerView {
private horizontalScrolling: boolean | undefined;

private dragHandler!: DelayedDragHandler;
private autoReveal: boolean | 'focusNoScroll' = false;
private autoReveal: boolean | 'force' | 'focusNoScroll' = false;
private decorationsProvider: ExplorerDecorationsProvider | undefined;

constructor(
Expand Down Expand Up @@ -725,7 +725,7 @@ export class ExplorerView extends ViewPane implements IExplorerView {
}

public async selectResource(resource: URI | undefined, reveal = this.autoReveal, retry = 0): Promise<void> {
// do no retry more than once to prevent inifinite loops in cases of inconsistent model
// do no retry more than once to prevent infinite loops in cases of inconsistent model
if (retry === 2) {
return;
}
Expand Down Expand Up @@ -766,7 +766,7 @@ export class ExplorerView extends ViewPane implements IExplorerView {
await this.tree.expand(item.nestedParent);
}

if (reveal === true && this.tree.getRelativeTop(item) === null) {
if ((reveal === true || reveal === 'force') && this.tree.getRelativeTop(item) === null) {
// Don't scroll to the item if it's already visible, or if set not to.
this.tree.reveal(item, 0.5);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ interface CachedParsedExpression {
}

/**
* Respectes files.exclude setting in filtering out content from the explorer.
* Respects files.exclude setting in filtering out content from the explorer.
* Makes sure that visible editors are always shown in the explorer even if they are filtered out by settings.
*/
export class FilesFilter implements ITreeFilter<ExplorerItem, FuzzyScore> {
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/contrib/files/common/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { once } from 'vs/base/common/functional';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { localize } from 'vs/nls';
import { IExpression } from 'vs/base/common/glob';

/**
* Explorer viewlet id.
Expand Down Expand Up @@ -88,6 +89,7 @@ export interface IFilesConfiguration extends PlatformIFilesConfiguration, IWorkb
sortOrder: 'editorOrder' | 'alphabetical' | 'fullPath';
};
autoReveal: boolean | 'focusNoScroll';
autoRevealExclude: IExpression;
enableDragAndDrop: boolean;
confirmDelete: boolean;
enableUndo: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,7 @@ export function isExcludeSetting(setting: ISetting): boolean {
return setting.key === 'files.exclude' ||
setting.key === 'search.exclude' ||
setting.key === 'workbench.localHistory.exclude' ||
setting.key === 'explorer.autoRevealExclude' ||
setting.key === 'files.watcherExclude';
}

Expand Down