Skip to content

Commit

Permalink
Copy/paste not working within same folder in Explorer
Browse files Browse the repository at this point in the history
* treat paste on parent directory same as paste on copied file
* use spaces instead of underscores as separators inside file names for
newly created files/folders
* fix unique name generation for dotfiles

Signed-off-by: Johannes Faltermeier <[email protected]>
Signed-off-by: Alexandra Buzila <[email protected]>
  • Loading branch information
jfaltermeier authored and AlexandraBuzila committed Feb 21, 2022
1 parent 363e521 commit 8f5bedd
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 17 deletions.
3 changes: 1 addition & 2 deletions packages/filesystem/src/browser/file-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1120,8 +1120,7 @@ export class FileService {
// if target exists get valid target
if (exists && !overwrite) {
const parent = await this.resolve(target.parent);
const name = isSameResourceWithDifferentPathCase ? target.path.name : target.path.name + '_copy';
target = FileSystemUtils.generateUniqueResourceURI(target.parent, parent, name, target.path.ext);
target = FileSystemUtils.generateUniqueResourceURI(target.parent, parent, target, isSameResourceWithDifferentPathCase ? 'copy' : undefined);
}

// delete as needed (unless target is same resource with different path case)
Expand Down
11 changes: 7 additions & 4 deletions packages/filesystem/src/browser/file-tree/file-tree-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,15 @@ export class FileTreeModel extends CompressedTreeModel implements LocationServic
}

async copy(source: URI, target: Readonly<FileStatNode>): Promise<URI> {
let targetUri = target.uri.resolve(source.path.base);
const dirNode = target.fileStat.isFile ? target.parent : target;
if (!FileStatNode.is(dirNode)) {
throw new Error('Parent of file has to be a FileStatNode');
}
let targetUri = target.fileStat.isFile ? dirNode.uri.resolve(source.path.base) : dirNode.uri;
try {
if (source.path.toString() === target.uri.path.toString()) {
if (source.path.toString() === targetUri.path.toString()) {
const parent = await this.fileService.resolve(source.parent);
const name = source.path.name + '_copy';
targetUri = FileSystemUtils.generateUniqueResourceURI(source.parent, parent, name, source.path.ext);
targetUri = FileSystemUtils.generateUniqueResourceURI(source.parent, parent, targetUri, 'copy');
}
await this.fileService.copy(source, targetUri);
} catch (e) {
Expand Down
23 changes: 17 additions & 6 deletions packages/filesystem/src/common/filesystem-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,34 @@ import { FileStat } from '../common/files';
import URI from '@theia/core/lib/common/uri';

export namespace FileSystemUtils {
export const FILE_NAME_SEPARATOR = ' ';

/**
* Generate unique URI for a given parent which does not collide
*
* @param parentUri the `URI` of the parent
* @param parent the `FileStat` of the parent
* @param name the resource name
* @param ext the resource extension
* @param targetUri the initial URI
* @param suffix an optional string to append to the file name, in case of collision (e.g. `copy`)
*/
export function generateUniqueResourceURI(parentUri: URI, parent: FileStat, name: string, ext: string = ''): URI {
export function generateUniqueResourceURI(parentUri: URI, parent: FileStat, targetUri: URI, suffix?: string): URI {
const children = !parent.children ? [] : parent.children!.map(child => child.resource);

let name = targetUri.path.name;
let extension = targetUri.path.ext;
if (!name) {
// special case for dotfiles (e.g. '.foobar'): use the extension as the name
name = targetUri.path.ext;
extension = '';
}
let base = name + extension;
if (suffix && children.some(child => child.path.base === base)) {
name = name + FILE_NAME_SEPARATOR + suffix;
base = name + extension;
}
let index = 1;
let base = name + ext;
while (children.some(child => child.path.base === base)) {
index = index + 1;
base = name + '_' + index + ext;
base = name + FILE_NAME_SEPARATOR + index + extension;
}
return parentUri.resolve(base);
}
Expand Down
6 changes: 4 additions & 2 deletions packages/workspace/src/browser/workspace-commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ export class WorkspaceCommandContribution implements CommandContribution {
if (parent) {
const parentUri = parent.resource;
const { fileName, fileExtension } = this.getDefaultFileConfig();
const vacantChildUri = FileSystemUtils.generateUniqueResourceURI(parentUri, parent, fileName, fileExtension);
const targetUri = parentUri.resolve(fileName + fileExtension);
const vacantChildUri = FileSystemUtils.generateUniqueResourceURI(parentUri, parent, targetUri);

const dialog = new WorkspaceInputDialog({
title: nls.localizeByDefault('New File'),
Expand All @@ -270,7 +271,8 @@ export class WorkspaceCommandContribution implements CommandContribution {
execute: uri => this.getDirectory(uri).then(parent => {
if (parent) {
const parentUri = parent.resource;
const vacantChildUri = FileSystemUtils.generateUniqueResourceURI(parentUri, parent, 'Untitled');
const targetUri = parentUri.resolve('Untitled');
const vacantChildUri = FileSystemUtils.generateUniqueResourceURI(parentUri, parent, targetUri);
const dialog = new WorkspaceInputDialog({
title: nls.localizeByDefault('New Folder'),
parentUri: parentUri,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,7 @@ export class WorkspaceDuplicateHandler implements UriCommandHandler<URI[]> {
try {
const parent = await this.fileService.resolve(uri.parent);
const parentUri = parent.resource;
const name = uri.path.name + '_copy';
const ext = uri.path.ext;
const target = FileSystemUtils.generateUniqueResourceURI(parentUri, parent, name, ext);
const target = FileSystemUtils.generateUniqueResourceURI(parentUri, parent, uri, 'copy');
await this.fileService.copy(uri, target);
} catch (e) {
console.error(e);
Expand Down

0 comments on commit 8f5bedd

Please sign in to comment.