|
|
|
|
@ -6,7 +6,6 @@
|
|
|
|
|
// Distributed under the terms of the Modified BSD License.
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
ILabShell,
|
|
|
|
|
ILayoutRestorer,
|
|
|
|
|
ITreePathUpdater,
|
|
|
|
|
IRouter,
|
|
|
|
|
@ -16,8 +15,6 @@ import {
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
Clipboard,
|
|
|
|
|
MainAreaWidget,
|
|
|
|
|
ToolbarButton,
|
|
|
|
|
WidgetTracker,
|
|
|
|
|
ICommandPalette,
|
|
|
|
|
InputDialog,
|
|
|
|
|
@ -25,7 +22,7 @@ import {
|
|
|
|
|
DOMUtils
|
|
|
|
|
} from '@jupyterlab/apputils';
|
|
|
|
|
|
|
|
|
|
import { PageConfig, PathExt } from '@jupyterlab/coreutils';
|
|
|
|
|
import { PathExt } from '@jupyterlab/coreutils';
|
|
|
|
|
|
|
|
|
|
import { IDocumentManager } from '@jupyterlab/docmanager';
|
|
|
|
|
|
|
|
|
|
@ -35,10 +32,10 @@ import {
|
|
|
|
|
IFileBrowserFactory
|
|
|
|
|
} from '@jupyterlab/filebrowser';
|
|
|
|
|
|
|
|
|
|
import { Launcher } from '@jupyterlab/launcher';
|
|
|
|
|
|
|
|
|
|
import { IMainMenu } from '@jupyterlab/mainmenu';
|
|
|
|
|
|
|
|
|
|
import { IRunningSessionManagers, RunningSessions } from '@jupyterlab/running';
|
|
|
|
|
|
|
|
|
|
import { Contents } from '@jupyterlab/services';
|
|
|
|
|
|
|
|
|
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
|
|
|
@ -59,17 +56,16 @@ import {
|
|
|
|
|
markdownIcon,
|
|
|
|
|
newFolderIcon,
|
|
|
|
|
pasteIcon,
|
|
|
|
|
runningIcon,
|
|
|
|
|
stopIcon,
|
|
|
|
|
textEditorIcon
|
|
|
|
|
} from '@jupyterlab/ui-components';
|
|
|
|
|
|
|
|
|
|
import { IIterator, map, reduce, toArray, find } from '@lumino/algorithm';
|
|
|
|
|
import { map, toArray } from '@lumino/algorithm';
|
|
|
|
|
|
|
|
|
|
import { CommandRegistry } from '@lumino/commands';
|
|
|
|
|
|
|
|
|
|
import { Message } from '@lumino/messaging';
|
|
|
|
|
|
|
|
|
|
import { Menu } from '@lumino/widgets';
|
|
|
|
|
import { TabPanel } from '@lumino/widgets';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The command IDs used by the file browser plugin.
|
|
|
|
|
@ -79,9 +75,6 @@ namespace CommandIDs {
|
|
|
|
|
|
|
|
|
|
export const copyDownloadLink = 'filebrowser:copy-download-link';
|
|
|
|
|
|
|
|
|
|
// For main browser only.
|
|
|
|
|
export const createLauncher = 'filebrowser:create-main-launcher';
|
|
|
|
|
|
|
|
|
|
export const cut = 'filebrowser:cut';
|
|
|
|
|
|
|
|
|
|
export const del = 'filebrowser:delete';
|
|
|
|
|
@ -90,9 +83,6 @@ namespace CommandIDs {
|
|
|
|
|
|
|
|
|
|
export const duplicate = 'filebrowser:duplicate';
|
|
|
|
|
|
|
|
|
|
// For main browser only.
|
|
|
|
|
export const hideBrowser = 'filebrowser:hide-main';
|
|
|
|
|
|
|
|
|
|
export const goToPath = 'filebrowser:go-to-path';
|
|
|
|
|
|
|
|
|
|
export const openPath = 'filebrowser:open-path';
|
|
|
|
|
@ -117,13 +107,8 @@ namespace CommandIDs {
|
|
|
|
|
// For main browser only.
|
|
|
|
|
export const copyPath = 'filebrowser:copy-path';
|
|
|
|
|
|
|
|
|
|
export const showBrowser = 'filebrowser:activate';
|
|
|
|
|
|
|
|
|
|
export const shutdown = 'filebrowser:shutdown';
|
|
|
|
|
|
|
|
|
|
// For main browser only.
|
|
|
|
|
export const toggleBrowser = 'filebrowser:toggle-main';
|
|
|
|
|
|
|
|
|
|
export const toggleNavigateToCurrentDirectory =
|
|
|
|
|
'filebrowser:toggle-navigate-to-current-directory';
|
|
|
|
|
|
|
|
|
|
@ -137,7 +122,7 @@ namespace CommandIDs {
|
|
|
|
|
*/
|
|
|
|
|
const browser: JupyterFrontEndPlugin<void> = {
|
|
|
|
|
activate: activateBrowser,
|
|
|
|
|
id: '@jupyterlab-classic/filebrowser-extension:browser',
|
|
|
|
|
id: '@jupyterlab-classic/tree-extension:browser',
|
|
|
|
|
requires: [
|
|
|
|
|
IFileBrowserFactory,
|
|
|
|
|
IDocumentManager,
|
|
|
|
|
@ -145,24 +130,26 @@ const browser: JupyterFrontEndPlugin<void> = {
|
|
|
|
|
ITranslator
|
|
|
|
|
],
|
|
|
|
|
optional: [
|
|
|
|
|
ILabShell,
|
|
|
|
|
ICommandPalette,
|
|
|
|
|
IMainMenu,
|
|
|
|
|
ILayoutRestorer,
|
|
|
|
|
ITreePathUpdater
|
|
|
|
|
ITreePathUpdater,
|
|
|
|
|
IRunningSessionManagers
|
|
|
|
|
],
|
|
|
|
|
autoStart: true
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* The default file browser factory provider.
|
|
|
|
|
*
|
|
|
|
|
* TODO: remove and use upstream plugin
|
|
|
|
|
*/
|
|
|
|
|
const factory: JupyterFrontEndPlugin<IFileBrowserFactory> = {
|
|
|
|
|
activate: activateFactory,
|
|
|
|
|
id: '@jupyterlab-classic/filebrowser-extension:factory',
|
|
|
|
|
id: '@jupyterlab-classic/tree-extension:factory',
|
|
|
|
|
provides: IFileBrowserFactory,
|
|
|
|
|
requires: [IDocumentManager, ITranslator],
|
|
|
|
|
optional: [ILabShell, IStateDB, IRouter, JupyterFrontEnd.ITreeResolver]
|
|
|
|
|
optional: [IStateDB, IRouter, JupyterFrontEnd.ITreeResolver]
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -183,12 +170,10 @@ async function activateFactory(
|
|
|
|
|
app: JupyterFrontEnd,
|
|
|
|
|
docManager: IDocumentManager,
|
|
|
|
|
translator: ITranslator,
|
|
|
|
|
labShell: ILabShell | null,
|
|
|
|
|
state: IStateDB | null,
|
|
|
|
|
router: IRouter | null,
|
|
|
|
|
tree: JupyterFrontEnd.ITreeResolver | null
|
|
|
|
|
): Promise<IFileBrowserFactory> {
|
|
|
|
|
const trans = translator.load('jupyterlab');
|
|
|
|
|
const { commands } = app;
|
|
|
|
|
const tracker = new WidgetTracker<FileBrowser>({ namespace });
|
|
|
|
|
const createFileBrowser = (
|
|
|
|
|
@ -207,31 +192,6 @@ async function activateFactory(
|
|
|
|
|
const restore = options.restore;
|
|
|
|
|
const widget = new FileBrowser({ id, model, restore, translator });
|
|
|
|
|
|
|
|
|
|
// Add a launcher toolbar item.
|
|
|
|
|
if (labShell) {
|
|
|
|
|
const launcher = new ToolbarButton({
|
|
|
|
|
icon: addIcon,
|
|
|
|
|
onClick: () => {
|
|
|
|
|
if (
|
|
|
|
|
labShell.mode === 'multiple-document' &&
|
|
|
|
|
commands.hasCommand('launcher:create')
|
|
|
|
|
) {
|
|
|
|
|
return Private.createLauncher(commands, widget);
|
|
|
|
|
} else {
|
|
|
|
|
const newUrl = PageConfig.getUrl({
|
|
|
|
|
mode: labShell.mode,
|
|
|
|
|
workspace: PageConfig.defaultWorkspace,
|
|
|
|
|
treePath: model.path
|
|
|
|
|
});
|
|
|
|
|
window.open(newUrl, '_blank');
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
tooltip: trans.__('New Launcher'),
|
|
|
|
|
actualOnClick: true
|
|
|
|
|
});
|
|
|
|
|
widget.toolbar.insertItem(0, 'launch', launcher);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Track the newly created file browser.
|
|
|
|
|
void tracker.add(widget);
|
|
|
|
|
|
|
|
|
|
@ -257,15 +217,13 @@ function activateBrowser(
|
|
|
|
|
docManager: IDocumentManager,
|
|
|
|
|
settingRegistry: ISettingRegistry,
|
|
|
|
|
translator: ITranslator,
|
|
|
|
|
labShell: ILabShell | null,
|
|
|
|
|
commandPalette: ICommandPalette | null,
|
|
|
|
|
mainMenu: IMainMenu | null,
|
|
|
|
|
restorer: ILayoutRestorer | null,
|
|
|
|
|
treePathUpdater: ITreePathUpdater | null
|
|
|
|
|
treePathUpdater: ITreePathUpdater | null,
|
|
|
|
|
manager: IRunningSessionManagers | null
|
|
|
|
|
): void {
|
|
|
|
|
const trans = translator.load('jupyterlab');
|
|
|
|
|
const browser = factory.defaultBrowser;
|
|
|
|
|
const { commands } = app;
|
|
|
|
|
|
|
|
|
|
// Let the application restorer track the primary file browser (that is
|
|
|
|
|
// automatically created) for restoration of application state (e.g. setting
|
|
|
|
|
@ -282,60 +240,31 @@ function activateBrowser(
|
|
|
|
|
factory,
|
|
|
|
|
settingRegistry,
|
|
|
|
|
translator,
|
|
|
|
|
labShell,
|
|
|
|
|
commandPalette,
|
|
|
|
|
mainMenu
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
browser.title.icon = folderIcon;
|
|
|
|
|
// Show the current file browser shortcut in its title.
|
|
|
|
|
const updateBrowserTitle = () => {
|
|
|
|
|
const binding = find(
|
|
|
|
|
app.commands.keyBindings,
|
|
|
|
|
b => b.command === CommandIDs.toggleBrowser
|
|
|
|
|
);
|
|
|
|
|
if (binding) {
|
|
|
|
|
const ks = CommandRegistry.formatKeystroke(binding.keys.join(' '));
|
|
|
|
|
browser.title.caption = trans.__('File Browser (%1)', ks);
|
|
|
|
|
} else {
|
|
|
|
|
browser.title.caption = trans.__('File Browser');
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
updateBrowserTitle();
|
|
|
|
|
app.commands.keyBindingChanged.connect(() => {
|
|
|
|
|
updateBrowserTitle();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.shell.add(browser, 'main', { rank: 100 });
|
|
|
|
|
const tabPanel = new TabPanel({ tabPlacement: 'top', tabsMovable: true });
|
|
|
|
|
tabPanel.addClass('jp-TreePanel');
|
|
|
|
|
|
|
|
|
|
// If the layout is a fresh session without saved data and not in single document
|
|
|
|
|
// mode, open file browser.
|
|
|
|
|
if (labShell) {
|
|
|
|
|
void labShell.restored.then(layout => {
|
|
|
|
|
if (layout.fresh && labShell.mode !== 'single-document') {
|
|
|
|
|
void commands.execute(CommandIDs.showBrowser, void 0);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
browser.title.label = 'File Browser';
|
|
|
|
|
tabPanel.addWidget(browser);
|
|
|
|
|
tabPanel.tabBar.addTab(browser.title);
|
|
|
|
|
|
|
|
|
|
void Promise.all([app.restored, browser.model.restored]).then(() => {
|
|
|
|
|
function maybeCreate() {
|
|
|
|
|
// Create a launcher if there are no open items.
|
|
|
|
|
if (
|
|
|
|
|
toArray(app.shell.widgets('main')).length === 0 &&
|
|
|
|
|
commands.hasCommand('launcher:create')
|
|
|
|
|
) {
|
|
|
|
|
void Private.createLauncher(commands, browser);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (manager) {
|
|
|
|
|
const running = new RunningSessions(manager, translator);
|
|
|
|
|
running.id = 'jp-running-sessions';
|
|
|
|
|
running.title.label = 'Running Sessions';
|
|
|
|
|
running.title.icon = runningIcon;
|
|
|
|
|
tabPanel.addWidget(running);
|
|
|
|
|
tabPanel.tabBar.addTab(running.title);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// When layout is modified, create a launcher if there are no open items.
|
|
|
|
|
if (labShell) {
|
|
|
|
|
labShell.layoutModified.connect(() => {
|
|
|
|
|
maybeCreate();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
app.shell.add(tabPanel, 'main', { rank: 100 });
|
|
|
|
|
|
|
|
|
|
void Promise.all([app.restored, browser.model.restored]).then(() => {
|
|
|
|
|
let navigateToCurrentDirectory = false;
|
|
|
|
|
let useFuzzyFilter = true;
|
|
|
|
|
|
|
|
|
|
@ -359,35 +288,11 @@ function activateBrowser(
|
|
|
|
|
browser.useFuzzyFilter = useFuzzyFilter;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Whether to automatically navigate to a document's current directory
|
|
|
|
|
if (labShell) {
|
|
|
|
|
labShell.currentChanged.connect(async (_, change) => {
|
|
|
|
|
if (navigateToCurrentDirectory && change.newValue) {
|
|
|
|
|
const { newValue } = change;
|
|
|
|
|
const context = docManager.contextForWidget(newValue);
|
|
|
|
|
if (context) {
|
|
|
|
|
const { path } = context;
|
|
|
|
|
try {
|
|
|
|
|
await Private.navigateToPath(path, factory, translator);
|
|
|
|
|
labShell.currentWidget?.activate();
|
|
|
|
|
} catch (reason) {
|
|
|
|
|
console.warn(
|
|
|
|
|
`${CommandIDs.goToPath} failed to open: ${path}`,
|
|
|
|
|
reason
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (treePathUpdater) {
|
|
|
|
|
browser.model.pathChanged.connect((sender, args) => {
|
|
|
|
|
treePathUpdater(args.newValue);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
maybeCreate();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -399,7 +304,6 @@ function addCommands(
|
|
|
|
|
factory: IFileBrowserFactory,
|
|
|
|
|
settingRegistry: ISettingRegistry,
|
|
|
|
|
translator: ITranslator,
|
|
|
|
|
labShell: ILabShell | null,
|
|
|
|
|
commandPalette: ICommandPalette | null,
|
|
|
|
|
mainMenu: IMainMenu | null
|
|
|
|
|
): void {
|
|
|
|
|
@ -469,24 +373,12 @@ function addCommands(
|
|
|
|
|
label: trans.__('Duplicate')
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (labShell) {
|
|
|
|
|
commands.addCommand(CommandIDs.hideBrowser, {
|
|
|
|
|
execute: () => {
|
|
|
|
|
const widget = tracker.currentWidget;
|
|
|
|
|
if (widget && !widget.isHidden) {
|
|
|
|
|
labShell.collapseLeft();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
commands.addCommand(CommandIDs.goToPath, {
|
|
|
|
|
execute: async args => {
|
|
|
|
|
const path = (args.path as string) || '';
|
|
|
|
|
const showBrowser = !(args?.dontShowBrowser ?? false);
|
|
|
|
|
try {
|
|
|
|
|
const item = await Private.navigateToPath(path, factory, translator);
|
|
|
|
|
if (item.type !== 'directory' && showBrowser) {
|
|
|
|
|
if (item.type !== 'directory') {
|
|
|
|
|
const browserForPath = Private.getBrowserForPath(path, factory);
|
|
|
|
|
if (browserForPath) {
|
|
|
|
|
browserForPath.clearSelectedItems();
|
|
|
|
|
@ -500,9 +392,6 @@ function addCommands(
|
|
|
|
|
} catch (reason) {
|
|
|
|
|
console.warn(`${CommandIDs.goToPath} failed to go to: ${path}`, reason);
|
|
|
|
|
}
|
|
|
|
|
if (showBrowser) {
|
|
|
|
|
return commands.execute(CommandIDs.showBrowser, { path });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
@ -740,36 +629,6 @@ function addCommands(
|
|
|
|
|
label: trans.__('Copy Path')
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
commands.addCommand(CommandIDs.showBrowser, {
|
|
|
|
|
execute: args => {
|
|
|
|
|
const path = (args.path as string) || '';
|
|
|
|
|
const browserForPath = Private.getBrowserForPath(path, factory);
|
|
|
|
|
|
|
|
|
|
// Check for browser not found
|
|
|
|
|
if (!browserForPath) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// Shortcut if we are using the main file browser
|
|
|
|
|
if (browser === browserForPath) {
|
|
|
|
|
app.shell.activateById(browser.id);
|
|
|
|
|
return;
|
|
|
|
|
} else {
|
|
|
|
|
const areas: ILabShell.Area[] = ['left', 'right'];
|
|
|
|
|
for (const area of areas) {
|
|
|
|
|
const it = app.shell.widgets(area);
|
|
|
|
|
let widget = it.next();
|
|
|
|
|
while (widget) {
|
|
|
|
|
if (widget.contains(browserForPath)) {
|
|
|
|
|
app.shell.activateById(widget.id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
widget = it.next();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
commands.addCommand(CommandIDs.shutdown, {
|
|
|
|
|
execute: () => {
|
|
|
|
|
const widget = tracker.currentWidget;
|
|
|
|
|
@ -782,21 +641,6 @@ function addCommands(
|
|
|
|
|
label: trans.__('Shut Down Kernel')
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
commands.addCommand(CommandIDs.toggleBrowser, {
|
|
|
|
|
execute: () => {
|
|
|
|
|
if (browser.isHidden) {
|
|
|
|
|
return commands.execute(CommandIDs.showBrowser, void 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return commands.execute(CommandIDs.hideBrowser, void 0);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
commands.addCommand(CommandIDs.createLauncher, {
|
|
|
|
|
label: trans.__('New Launcher'),
|
|
|
|
|
execute: () => Private.createLauncher(commands, browser)
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
commands.addCommand(CommandIDs.toggleNavigateToCurrentDirectory, {
|
|
|
|
|
label: trans.__('Show Active File in File Browser'),
|
|
|
|
|
isToggled: () => browser.navigateToCurrentDirectory,
|
|
|
|
|
@ -852,77 +696,6 @@ function addCommands(
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A menu widget that dynamically populates with different widget factories
|
|
|
|
|
* based on current filebrowser selection.
|
|
|
|
|
*/
|
|
|
|
|
class OpenWithMenu extends Menu {
|
|
|
|
|
protected onBeforeAttach(msg: Message): void {
|
|
|
|
|
// clear the current menu items
|
|
|
|
|
this.clearItems();
|
|
|
|
|
|
|
|
|
|
// get the widget factories that could be used to open all of the items
|
|
|
|
|
// in the current filebrowser selection
|
|
|
|
|
const factories = tracker.currentWidget
|
|
|
|
|
? OpenWithMenu._intersection(
|
|
|
|
|
map(tracker.currentWidget.selectedItems(), i => {
|
|
|
|
|
return OpenWithMenu._getFactories(i);
|
|
|
|
|
})
|
|
|
|
|
)
|
|
|
|
|
: undefined;
|
|
|
|
|
|
|
|
|
|
if (factories) {
|
|
|
|
|
// make new menu items from the widget factories
|
|
|
|
|
factories.forEach(factory => {
|
|
|
|
|
this.addItem({
|
|
|
|
|
args: { factory: factory },
|
|
|
|
|
command: CommandIDs.open
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
super.onBeforeAttach(msg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static _getFactories(item: Contents.IModel): Array<string> {
|
|
|
|
|
const factories = registry
|
|
|
|
|
.preferredWidgetFactories(item.path)
|
|
|
|
|
.map(f => f.name);
|
|
|
|
|
const notebookFactory = registry.getWidgetFactory('notebook')?.name;
|
|
|
|
|
if (
|
|
|
|
|
notebookFactory &&
|
|
|
|
|
item.type === 'notebook' &&
|
|
|
|
|
factories.indexOf(notebookFactory) === -1
|
|
|
|
|
) {
|
|
|
|
|
factories.unshift(notebookFactory);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return factories;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static _intersection<T>(iter: IIterator<Array<T>>): Set<T> | void {
|
|
|
|
|
// pop the first element of iter
|
|
|
|
|
const first = iter.next();
|
|
|
|
|
// first will be undefined if iter is empty
|
|
|
|
|
if (!first) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// "initialize" the intersection from first
|
|
|
|
|
const isect = new Set(first);
|
|
|
|
|
// reduce over the remaining elements of iter
|
|
|
|
|
return reduce(
|
|
|
|
|
iter,
|
|
|
|
|
(isect, subarr) => {
|
|
|
|
|
// filter out all elements not present in both isect and subarr,
|
|
|
|
|
// accumulate result in new set
|
|
|
|
|
return new Set(subarr.filter(x => isect.has(x)));
|
|
|
|
|
},
|
|
|
|
|
isect
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// matches anywhere on filebrowser
|
|
|
|
|
const selectorContent = '.jp-DirListing-content';
|
|
|
|
|
// matches all filebrowser items
|
|
|
|
|
@ -962,15 +735,6 @@ function addCommands(
|
|
|
|
|
rank: 1
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const openWith = new OpenWithMenu({ commands });
|
|
|
|
|
openWith.title.label = trans.__('Open With');
|
|
|
|
|
app.contextMenu.addItem({
|
|
|
|
|
type: 'submenu',
|
|
|
|
|
submenu: openWith,
|
|
|
|
|
selector: selectorNotDir,
|
|
|
|
|
rank: 2
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
app.contextMenu.addItem({
|
|
|
|
|
command: CommandIDs.openBrowserTab,
|
|
|
|
|
selector: selectorNotDir,
|
|
|
|
|
@ -1041,27 +805,6 @@ function addCommands(
|
|
|
|
|
* A namespace for private module data.
|
|
|
|
|
*/
|
|
|
|
|
namespace Private {
|
|
|
|
|
/**
|
|
|
|
|
* Create a launcher for a given filebrowser widget.
|
|
|
|
|
*/
|
|
|
|
|
export function createLauncher(
|
|
|
|
|
commands: CommandRegistry,
|
|
|
|
|
browser: FileBrowser
|
|
|
|
|
): Promise<MainAreaWidget<Launcher>> {
|
|
|
|
|
const { model } = browser;
|
|
|
|
|
|
|
|
|
|
return commands
|
|
|
|
|
.execute('launcher:create', { cwd: model.path })
|
|
|
|
|
.then((launcher: MainAreaWidget<Launcher>) => {
|
|
|
|
|
model.pathChanged.connect(() => {
|
|
|
|
|
if (launcher.content) {
|
|
|
|
|
launcher.content.cwd = model.path;
|
|
|
|
|
}
|
|
|
|
|
}, launcher);
|
|
|
|
|
return launcher;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get browser object given file path.
|
|
|
|
|
*/
|