diff --git a/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts b/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts index 309a599489428b440005c135685be54de07cbdf5..c565ecdcb4d8f7ab7cc60b17049a11df9123bbe7 100644 --- a/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts +++ b/src/vs/workbench/services/dialogs/browser/remoteFileDialog.ts @@ -135,7 +135,7 @@ export class RemoteFileDialog { private remoteUriFrom(path: string): URI { path = path.replace(/\\/g, '/'); - return URI.from({ scheme: this.scheme, authority: this.remoteAuthority, path }); + return resources.toLocalResource(URI.from({ scheme: this.scheme, path }), this.remoteAuthority); } private getScheme(defaultUri: URI | undefined, available: string[] | undefined): string { @@ -188,6 +188,8 @@ export class RemoteFileDialog { let isResolving = false; let isAcceptHandled = false; this.currentFolder = homedir; + this.userEnteredPathSegment = ''; + this.autoCompletePathSegment = ''; this.filePickBox.buttons = [this.acceptButton]; this.filePickBox.onDidTriggerButton(_ => { // accept button @@ -362,12 +364,12 @@ export class RemoteFileDialog { } catch (e) { // do nothing } - if (stat && stat.isDirectory && (resources.basename(valueUri) !== '.')) { + if (stat && stat.isDirectory && (resources.basename(valueUri) !== '.') && this.endsWithSlash(value)) { await this.updateItems(valueUri); return true; } else { const inputUriDirname = resources.dirname(valueUri); - if (!resources.isEqual(this.currentFolder, inputUriDirname, true)) { + if (!resources.isEqual(this.remoteUriFrom(this.trimTrailingSlash(this.pathFromUri(this.currentFolder))), inputUriDirname, true)) { let statWithoutTrailing: IFileStat | undefined; try { statWithoutTrailing = await this.fileService.resolve(inputUriDirname); @@ -386,8 +388,9 @@ export class RemoteFileDialog { private setActiveItems(value: string) { const inputBasename = resources.basename(this.remoteUriFrom(value)); - if ((value !== this.constructFullUserPath().substring(0, value.length)) - && resources.isEqual(resources.dirname(this.remoteUriFrom(this.filePickBox.value)), this.currentFolder, true)) { + // Make sure that the folder whose children we are currently viewing matches the path in the input + const userPath = this.constructFullUserPath(); + if (userPath === value.substring(0, userPath.length)) { let hasMatch = false; for (let i = 0; i < this.filePickBox.items.length; i++) { const item = this.filePickBox.items[i]; @@ -402,40 +405,42 @@ export class RemoteFileDialog { this.filePickBox.activeItems = []; } } else { - this.userEnteredPathSegment = inputBasename; + if (inputBasename !== resources.basename(this.currentFolder)) { + this.userEnteredPathSegment = inputBasename; + } else { + this.userEnteredPathSegment = ''; + } this.autoCompletePathSegment = ''; } } private setAutoComplete(startingValue: string, startingBasename: string, quickPickItem: FileQuickPickItem, force: boolean = false): boolean { const itemBasename = (quickPickItem.label === '..') ? quickPickItem.label : resources.basename(quickPickItem.uri); - const itemPathLabel = (itemBasename === '..') ? this.pathAppend(this.currentFolder, itemBasename) : this.pathFromUri(quickPickItem.uri); - if (!equalsIgnoreCase(this.trimTrailingSlash(this.filePickBox.value), itemPathLabel)) { - // Either force the autocomplete, or the old value should be one smaller than the new value and match the new value. - if (!force && (itemBasename.length >= startingBasename.length + 1) && equalsIgnoreCase(itemBasename.substr(0, startingBasename.length), startingBasename)) { - this.userEnteredPathSegment = startingBasename; - this.activeItem = quickPickItem; - // Changing the active items will trigger the onDidActiveItemsChanged. Clear the autocomplete first, then set it after. - this.autoCompletePathSegment = ''; - this.filePickBox.activeItems = [quickPickItem]; - this.autoCompletePathSegment = itemBasename.substr(startingBasename.length); - this.insertText(startingValue + this.autoCompletePathSegment, this.autoCompletePathSegment); - this.filePickBox.valueSelection = [startingValue.length, this.filePickBox.value.length]; - return true; - } else if (force && (quickPickItem.label !== (this.userEnteredPathSegment + this.autoCompletePathSegment))) { - this.userEnteredPathSegment = ''; - this.autoCompletePathSegment = itemBasename; - this.activeItem = quickPickItem; - this.filePickBox.valueSelection = [this.pathFromUri(this.currentFolder, true).length, this.filePickBox.value.length]; - // use insert text to preserve undo buffer - this.insertText(this.pathAppend(this.currentFolder, itemBasename), itemBasename); - this.filePickBox.valueSelection = [this.filePickBox.value.length - itemBasename.length, this.filePickBox.value.length]; - return true; - } + // Either force the autocomplete, or the old value should be one smaller than the new value and match the new value. + if (!force && (itemBasename.length >= startingBasename.length) && equalsIgnoreCase(itemBasename.substr(0, startingBasename.length), startingBasename)) { + this.userEnteredPathSegment = startingBasename; + this.activeItem = quickPickItem; + // Changing the active items will trigger the onDidActiveItemsChanged. Clear the autocomplete first, then set it after. + this.autoCompletePathSegment = ''; + this.filePickBox.activeItems = [quickPickItem]; + this.autoCompletePathSegment = itemBasename.substr(startingBasename.length); + this.insertText(startingValue + this.autoCompletePathSegment, this.autoCompletePathSegment); + this.filePickBox.valueSelection = [startingValue.length, this.filePickBox.value.length]; + return true; + } else if (force && (quickPickItem.label !== (this.userEnteredPathSegment + this.autoCompletePathSegment))) { + this.userEnteredPathSegment = ''; + this.autoCompletePathSegment = itemBasename; + this.activeItem = quickPickItem; + this.filePickBox.valueSelection = [this.pathFromUri(this.currentFolder, true).length, this.filePickBox.value.length]; + // use insert text to preserve undo buffer + this.insertText(this.pathAppend(this.currentFolder, itemBasename), itemBasename); + this.filePickBox.valueSelection = [this.filePickBox.value.length - itemBasename.length, this.filePickBox.value.length]; + return true; + } else { + this.userEnteredPathSegment = startingBasename; + this.autoCompletePathSegment = ''; + return false; } - this.userEnteredPathSegment = startingBasename; - this.autoCompletePathSegment = ''; - return false; } private insertText(wholeValue: string, insertText: string) { @@ -554,11 +559,11 @@ export class RemoteFileDialog { } private async updateItems(newFolder: URI, trailing?: string) { - this.currentFolder = newFolder; this.userEnteredPathSegment = trailing ? trailing : ''; this.autoCompletePathSegment = ''; this.filePickBox.valueSelection = [0, this.filePickBox.value.length]; const newValue = trailing ? this.pathFromUri(resources.joinPath(newFolder, trailing)) : this.pathFromUri(newFolder, true); + this.currentFolder = this.remoteUriFrom(this.pathFromUri(newFolder, true)); this.insertText(newValue, newValue); this.filePickBox.busy = true; return this.createItems(this.currentFolder).then(items => { @@ -586,7 +591,8 @@ export class RemoteFileDialog { private pathAppend(uri: URI, additional: string): string { if ((additional === '..') || (additional === '.')) { - return this.pathFromUri(uri) + this.labelService.getSeparator(uri.scheme, uri.authority) + additional; + const basePath = this.pathFromUri(uri); + return basePath + (this.endsWithSlash(basePath) ? '' : this.labelService.getSeparator(uri.scheme, uri.authority)) + additional; } else { return this.pathFromUri(resources.joinPath(uri, additional)); }