|
|
@ -1,10 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
import * as vscode from 'vscode';
|
|
|
|
import * as vscode from 'vscode';
|
|
|
|
import { loadConfigs } from './config';
|
|
|
|
import { loadConfigs } from './config';
|
|
|
|
|
|
|
|
import type { Connection } from './connection';
|
|
|
|
import type { FileSystemConfig } from './fileSystemConfig';
|
|
|
|
import type { FileSystemConfig } from './fileSystemConfig';
|
|
|
|
import { FileSystemRouter } from './fileSystemRouter';
|
|
|
|
import { FileSystemRouter } from './fileSystemRouter';
|
|
|
|
import { Logging } from './logging';
|
|
|
|
import { Logging } from './logging';
|
|
|
|
import { Manager } from './manager';
|
|
|
|
import { Manager } from './manager';
|
|
|
|
|
|
|
|
import type { SSHPseudoTerminal } from './pseudoTerminal';
|
|
|
|
|
|
|
|
|
|
|
|
function generateDetail(config: FileSystemConfig): string | undefined {
|
|
|
|
function generateDetail(config: FileSystemConfig): string | undefined {
|
|
|
|
const { username, host, putty } = config;
|
|
|
|
const { username, host, putty } = config;
|
|
|
@ -43,6 +45,17 @@ function getVersion(): string | undefined {
|
|
|
|
return ext && ext.packageJSON && ext.packageJSON.version;
|
|
|
|
return ext && ext.packageJSON && ext.packageJSON.version;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interface CommandHandler {
|
|
|
|
|
|
|
|
/** If set, a string/undefined prompts using the given options.
|
|
|
|
|
|
|
|
* If the input was a string, promptOptions.nameFilter is set to it */
|
|
|
|
|
|
|
|
promptOptions: PickComplexOptions;
|
|
|
|
|
|
|
|
handleString?(string: string): void;
|
|
|
|
|
|
|
|
handleUri?(uri: vscode.Uri): void;
|
|
|
|
|
|
|
|
handleConfig?(config: FileSystemConfig): void;
|
|
|
|
|
|
|
|
handleConnection?(connection: Connection): void;
|
|
|
|
|
|
|
|
handleTerminal?(terminal: SSHPseudoTerminal): void;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export function activate(context: vscode.ExtensionContext) {
|
|
|
|
export function activate(context: vscode.ExtensionContext) {
|
|
|
|
Logging.info(`Extension activated, version ${getVersion()}`);
|
|
|
|
Logging.info(`Extension activated, version ${getVersion()}`);
|
|
|
|
|
|
|
|
|
|
|
@ -56,32 +69,76 @@ export function activate(context: vscode.ExtensionContext) {
|
|
|
|
subscribe(vscode.window.createTreeView('sshfs-configs', { treeDataProvider: manager, showCollapseAll: true }));
|
|
|
|
subscribe(vscode.window.createTreeView('sshfs-configs', { treeDataProvider: manager, showCollapseAll: true }));
|
|
|
|
subscribe(vscode.tasks.registerTaskProvider('ssh-shell', manager));
|
|
|
|
subscribe(vscode.tasks.registerTaskProvider('ssh-shell', manager));
|
|
|
|
|
|
|
|
|
|
|
|
async function pickAndClick(func: (name: string | FileSystemConfig) => void, name?: string | FileSystemConfig, activeOrNot?: boolean) {
|
|
|
|
function registerCommandHandler(name: string, handler: CommandHandler) {
|
|
|
|
name = name || await pickConfig(manager, activeOrNot);
|
|
|
|
const callback = async (arg?: string | FileSystemConfig | Connection | SSHPseudoTerminal | vscode.Uri) => {
|
|
|
|
if (name) func.call(manager, name);
|
|
|
|
if (handler.promptOptions && (!arg || typeof arg === 'string')) {
|
|
|
|
|
|
|
|
arg = await pickComplex(manager, { ...handler.promptOptions, nameFilter: arg });
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof arg === 'string') return handler.handleString?.(arg);
|
|
|
|
|
|
|
|
if (!arg) return;
|
|
|
|
|
|
|
|
if (arg instanceof vscode.Uri) {
|
|
|
|
|
|
|
|
return handler.handleUri?.(arg);
|
|
|
|
|
|
|
|
} else if ('handleInput' in arg) {
|
|
|
|
|
|
|
|
return handler.handleTerminal?.(arg);
|
|
|
|
|
|
|
|
} else if ('client' in arg) {
|
|
|
|
|
|
|
|
return handler.handleConnection?.(arg);
|
|
|
|
|
|
|
|
} else if ('name' in arg) {
|
|
|
|
|
|
|
|
return handler.handleConfig?.(arg);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
Logging.warning(`CommandHandler for '${name}' could not handle input '${arg}'`);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
registerCommand(name, callback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// sshfs.new()
|
|
|
|
registerCommand('sshfs.new', () => manager.openSettings({ type: 'newconfig' }));
|
|
|
|
registerCommand('sshfs.new', () => manager.openSettings({ type: 'newconfig' }));
|
|
|
|
registerCommand('sshfs.settings', () => manager.openSettings());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
registerCommand('sshfs.connect', (name?: string | FileSystemConfig) => pickAndClick(manager.commandConnect, name, false));
|
|
|
|
// sshfs.add(target?: string | FileSystemConfig)
|
|
|
|
registerCommand('sshfs.disconnect', (name?: string | FileSystemConfig) => pickAndClick(manager.commandDisconnect, name, true));
|
|
|
|
registerCommandHandler('sshfs.add', {
|
|
|
|
registerCommand('sshfs.reconnect', (name?: string | FileSystemConfig) => pickAndClick(manager.commandReconnect, name, true));
|
|
|
|
promptOptions: { promptConfigs: true },
|
|
|
|
registerCommand('sshfs.terminal', async (configOrUri?: string | FileSystemConfig | vscode.Uri) => {
|
|
|
|
handleConfig: config => manager.commandConnect(config),
|
|
|
|
// SSH FS view context menu: [ config, null ]
|
|
|
|
});
|
|
|
|
// Explorer context menu: [ uri, [uri] ]
|
|
|
|
|
|
|
|
// Command: [ ]
|
|
|
|
// sshfs.disconnect(target: string | FileSystemConfig | Connection)
|
|
|
|
// And just in case, supporting [ configName ] too
|
|
|
|
registerCommandHandler('sshfs.disconnect', {
|
|
|
|
let config = configOrUri;
|
|
|
|
promptOptions: { promptConfigs: true, promptConnections: true },
|
|
|
|
let uri: vscode.Uri | undefined;
|
|
|
|
handleString: name => manager.commandDisconnect(name),
|
|
|
|
if (config instanceof vscode.Uri) {
|
|
|
|
handleConfig: config => manager.commandDisconnect(config.name),
|
|
|
|
uri = config;
|
|
|
|
handleConnection: con => manager.commandDisconnect(con),
|
|
|
|
config = config.authority;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
config = config || await pickConfig(manager);
|
|
|
|
// sshfs.termninal(target?: string | FileSystemConfig | Connection | vscode.Uri)
|
|
|
|
if (config) manager.commandTerminal(config, uri);
|
|
|
|
registerCommandHandler('sshfs.terminal', {
|
|
|
|
|
|
|
|
promptOptions: { promptConfigs: true, promptConnections: true },
|
|
|
|
|
|
|
|
handleConfig: config => manager.commandTerminal(config),
|
|
|
|
|
|
|
|
handleConnection: con => manager.commandTerminal(con),
|
|
|
|
|
|
|
|
handleUri: async uri => {
|
|
|
|
|
|
|
|
const con = await pickConnection(manager, uri.authority);
|
|
|
|
|
|
|
|
con && manager.commandTerminal(con, uri);
|
|
|
|
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
registerCommand('sshfs.configure', (name?: string | FileSystemConfig) => pickAndClick(manager.commandConfigure, name));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// sshfs.focusTerminal(target?: SSHPseudoTerminal)
|
|
|
|
|
|
|
|
registerCommandHandler('sshfs.focusTerminal', {
|
|
|
|
|
|
|
|
promptOptions: { promptTerminals: true },
|
|
|
|
|
|
|
|
handleTerminal: ({ terminal }) => terminal?.show(false),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// sshfs.closeTerminal(target?: SSHPseudoTerminal)
|
|
|
|
|
|
|
|
registerCommandHandler('sshfs.closeTerminal', {
|
|
|
|
|
|
|
|
promptOptions: { promptTerminals: true },
|
|
|
|
|
|
|
|
handleTerminal: terminal => terminal.close(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// sshfs.configure(target?: string | FileSystemConfig)
|
|
|
|
|
|
|
|
registerCommandHandler('sshfs.configure', {
|
|
|
|
|
|
|
|
promptOptions: { promptConfigs: true },
|
|
|
|
|
|
|
|
handleConfig: config => manager.commandConfigure(config),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// sshfs.reload()
|
|
|
|
registerCommand('sshfs.reload', loadConfigs);
|
|
|
|
registerCommand('sshfs.reload', loadConfigs);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// sshfs.settings()
|
|
|
|
|
|
|
|
registerCommand('sshfs.settings', () => manager.openSettings());
|
|
|
|
}
|
|
|
|
}
|
|
|
|