diff --git a/schema/drives-file-browser.json b/schema/drives-file-browser.json index aa008ad..ff24fdf 100644 --- a/schema/drives-file-browser.json +++ b/schema/drives-file-browser.json @@ -82,6 +82,17 @@ "command": "drives:rename", "selector": ".jp-DirListing-item[data-isdir]", "rank": 5 + }, + { + "command": "filebrowser:copy-path", + "selector": ".jp-DirListing-item[data-isdir]", + "rank": 14, + "disabled": true + }, + { + "command": "drives:copy-path", + "selector": ".jp-DirListing-item[data-isdir]", + "rank": 14 } ] }, diff --git a/src/plugins/driveBrowserPlugin.ts b/src/plugins/driveBrowserPlugin.ts index 5105879..de44ac2 100644 --- a/src/plugins/driveBrowserPlugin.ts +++ b/src/plugins/driveBrowserPlugin.ts @@ -13,6 +13,7 @@ import { import { ITranslator } from '@jupyterlab/translation'; import { createToolbarFactory, + Clipboard, IToolbarWidgetRegistry, setToolbar, showDialog, @@ -28,6 +29,7 @@ import { notebookIcon, editIcon } from '@jupyterlab/ui-components'; +import { PageConfig, PathExt } from '@jupyterlab/coreutils'; import { CommandRegistry } from '@lumino/commands'; import { Widget } from '@lumino/widgets'; @@ -151,7 +153,7 @@ export const driveFileBrowser: JupyterFrontEndPlugin = { ); // Add commands - Private.addCommands(app, drive, driveBrowser); + Private.addCommands(app, drive, driveBrowser, fileBrowserFactory); const updateVisibility = () => { // Visibility of context menu and toolbar commands changed. @@ -334,8 +336,11 @@ namespace Private { export function addCommands( app: JupyterFrontEnd, drive: Drive, - browser: FileBrowser + browser: FileBrowser, + factory: IFileBrowserFactory ): void { + const { tracker } = factory; + app.commands.addCommand(CommandIDs.createNewDrive, { isEnabled: () => { return browser.model.path === 's3:'; @@ -425,5 +430,36 @@ namespace Private { icon: editIcon.bindprops({ stylesheet: 'menuItem' }), label: 'Rename' }); + + app.commands.addCommand(CommandIDs.copyPath, { + execute: () => { + const widget = tracker.currentWidget; + if (!widget) { + return; + } + const item = widget.selectedItems().next(); + if (item.done) { + return; + } + + let path: string = item.value.path; + if (PageConfig.getOption('copyAbsolutePath') === 'true') { + path = PathExt.joinWithLeadingSlash( + PageConfig.getOption('serverRoot') ?? '', + item.value.path + ); + } + const parts = path.split(':'); + path = parts[0] + '://' + parts[1]; + Clipboard.copyToSystem(path); + }, + isVisible: () => + // So long as this command only handles one file at time, don't show it + // if multiple files are selected. + !!tracker.currentWidget && + Array.from(tracker.currentWidget.selectedItems()).length === 1, + icon: fileIcon.bindprops({ stylesheet: 'menuItem' }), + label: 'Copy Path' + }); } } diff --git a/src/token.ts b/src/token.ts index 195a47b..311e4ac 100644 --- a/src/token.ts +++ b/src/token.ts @@ -14,6 +14,7 @@ export namespace CommandIDs { export const createNewFile = 'drives:create-new-file'; export const createNewNotebook = 'drives:create-new-notebook'; export const rename = 'drives:rename'; + export const copyPath = 'drives:copy-path'; } /**