Skip to content

Commit

Permalink
Show SSH Targets View Conditionally (#9856)
Browse files Browse the repository at this point in the history
* Show SSH Targets View conditionally
  • Loading branch information
xisui-MSFT authored Sep 16, 2022
1 parent ba0cc65 commit 3a8e920
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 23 deletions.
13 changes: 12 additions & 1 deletion Extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@
{
"id": "CppSshTargetsView",
"name": "%c_cpp.contributes.views.sshTargetsView.title%",
"when": "showCppSshTargetsView"
"when": "enableCppSshTargetsView"
}
]
},
Expand Down Expand Up @@ -2761,6 +2761,17 @@
"default": false,
"markdownDescription": "%c_cpp.configuration.legacyCompilerArgsBehavior.markdownDescription%",
"scope": "resource"
},
"C_Cpp.sshTargetsView": {
"type": "string",
"enum": [
"enabled",
"disabled",
"default"
],
"default": "default",
"description": "%c_cpp.configuration.sshTargetsView.description%",
"scope": "window"
}
}
},
Expand Down
1 change: 1 addition & 0 deletions Extension/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
"c_cpp.configuration.debugger.useBacktickCommandSubstitution.markdownDescription": { "message": "If `true`, debugger shell command substitution will use obsolete backtick ``(`)``.", "comment": [ "Markdown text between `` should not be translated or localized (they represent literal text) and the capitalization, spacing, and punctuation (including the ``) should not be altered." ] },
"c_cpp.configuration.legacyCompilerArgsBehavior.markdownDescription": "Enable pre-v1.10.0 behavior for how shell escaping is handled in compiler arg settings. Shell escaping is no longer expected or supported by default in arg arrays starting in v1.10.0.",
"c_cpp.configuration.legacyCompilerArgsBehavior.deprecationMessage": "This setting is temporary to support transitioning to corrected behavior in v1.10.0.",
"c_cpp.configuration.sshTargetsView.description": "Controls whether the SSH Targets view is visible. By default, enable the view when an SSH command is invoked.",
"c_cpp.contributes.views.cppReferencesView.title": "C/C++: Other references results",
"c_cpp.contributes.views.sshTargetsView.title": { "message": "Cpptools: SSH targets", "comment": [ "Do not localize `Cpptools`." ] },
"c_cpp.contributes.viewsWelcome.contents": { "message": "To learn more about launch.json, see [Configuring C/C++ debugging](https://code.visualstudio.com/docs/cpp/launch-json-reference).", "comment": [ "Markdown text between () should not be altered: https://en.wikipedia.org/wiki/Markdown" ] },
Expand Down
79 changes: 62 additions & 17 deletions Extension/src/Debugger/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,23 @@ import { CppdbgDebugAdapterDescriptorFactory, CppvsdbgDebugAdapterDescriptorFact
import { DebuggerType } from './configurations';
import * as nls from 'vscode-nls';
import { getActiveSshTarget, initializeSshTargets, selectSshTarget, SshTargetsProvider } from '../SSH/TargetsView/sshTargetsProvider';
import { addSshTarget, BaseNode, refreshCppSshTargetsView } from '../SSH/TargetsView/common';
import { addSshTargetCmd, BaseNode, refreshCppSshTargetsViewCmd } from '../SSH/TargetsView/common';
import { setActiveSshTarget, TargetLeafNode } from '../SSH/TargetsView/targetNodes';
import { sshCommandToConfig } from '../SSH/sshCommandToConfig';
import { getSshConfiguration, getSshConfigurationFiles, writeSshConfiguration } from '../SSH/sshHosts';
import { pathAccessible } from '../common';
import * as fs from 'fs';
import { Configuration } from 'ssh-config';
import { CppSettings } from '../LanguageServer/settings';
import * as chokidar from 'chokidar';

// The extension deactivate method is asynchronous, so we handle the disposables ourselves instead of using extensionContext.subscriptions.
const disposables: vscode.Disposable[] = [];
const localize: nls.LocalizeFunc = nls.loadMessageBundle();

const fileWatchers: chokidar.FSWatcher[] = [];
let sshTargetsViewEnabled: boolean = false;
let sshTargetsViewSetting: string | undefined;
let sshConfigWatcher: chokidar.FSWatcher | undefined;

export async function initialize(context: vscode.ExtensionContext): Promise<void> {
// Activate Process Picker Commands
Expand Down Expand Up @@ -79,38 +82,80 @@ export async function initialize(context: vscode.ExtensionContext): Promise<void
await initializeSshTargets();
const sshTargetsProvider: SshTargetsProvider = new SshTargetsProvider();
disposables.push(vscode.window.registerTreeDataProvider('CppSshTargetsView', sshTargetsProvider));
disposables.push(vscode.commands.registerCommand(addSshTarget, addSshTargetImpl));
disposables.push(vscode.commands.registerCommand('C_Cpp.removeSshTarget', removeSshTargetImpl));
disposables.push(vscode.commands.registerCommand(refreshCppSshTargetsView, (node?: BaseNode) => sshTargetsProvider.refresh(node)));
disposables.push(vscode.commands.registerCommand(addSshTargetCmd, () => enableSshTargetsViewAndRun(addSshTargetImpl)));
disposables.push(vscode.commands.registerCommand('C_Cpp.removeSshTarget', (node?: BaseNode) => enableSshTargetsViewAndRun(removeSshTargetImpl, node)));
disposables.push(vscode.commands.registerCommand(refreshCppSshTargetsViewCmd, (node?: BaseNode) => enableSshTargetsViewAndRun((node?: BaseNode) => sshTargetsProvider.refresh(node), node)));
disposables.push(vscode.commands.registerCommand('C_Cpp.setActiveSshTarget', async (node: TargetLeafNode) => {
await enableSshTargetsView();
await setActiveSshTarget(node.name);
await vscode.commands.executeCommand(refreshCppSshTargetsView);
await vscode.commands.executeCommand(refreshCppSshTargetsViewCmd);
}));
disposables.push(vscode.commands.registerCommand('C_Cpp.selectSshTarget', selectSshTarget));
disposables.push(vscode.commands.registerCommand('C_Cpp.selectSshTarget', () => enableSshTargetsViewAndRun(selectSshTarget)));
disposables.push(vscode.commands.registerCommand('C_Cpp.selectActiveSshTarget', async () => {
await enableSshTargetsView();
const name: string | undefined = await selectSshTarget();
if (name) {
await setActiveSshTarget(name);
await vscode.commands.executeCommand(refreshCppSshTargetsView);
await vscode.commands.executeCommand(refreshCppSshTargetsViewCmd);
}
}));
disposables.push(vscode.commands.registerCommand('C_Cpp.activeSshTarget', getActiveSshTarget));
disposables.push(vscode.commands.registerCommand('C_Cpp.activeSshTarget', () => enableSshTargetsViewAndRun(getActiveSshTarget)));
disposables.push(sshTargetsProvider);
for (const sshConfig of getSshConfigurationFiles()) {
fileWatchers.push(chokidar.watch(sshConfig, {ignoreInitial: true})
.on('add', () => vscode.commands.executeCommand(refreshCppSshTargetsView))
.on('change', () => vscode.commands.executeCommand(refreshCppSshTargetsView))
.on('unlink', () => vscode.commands.executeCommand(refreshCppSshTargetsView)));

// Decide if we should show the SSH Targets View.
sshTargetsViewSetting = (new CppSettings()).sshTargetsView;
// Active SSH Target initialized in initializeSshTargets()
if (sshTargetsViewSetting === 'enabled' || (sshTargetsViewSetting === 'default' && await getActiveSshTarget(false))) {
// Don't wait
enableSshTargetsView();
}
vscode.commands.executeCommand('setContext', 'showCppSshTargetsView', true);

disposables.push(vscode.workspace.onDidChangeConfiguration(async (e: vscode.ConfigurationChangeEvent) => {
if (e.affectsConfiguration('C_Cpp.sshTargetsView')) {
sshTargetsViewSetting = (new CppSettings()).sshTargetsView;
if (sshTargetsViewSetting === 'enabled' || (sshTargetsViewSetting === 'default' && await getActiveSshTarget(false))) {
await enableSshTargetsView();
} else if (sshTargetsViewSetting === 'disabled') {
await disableSshTargetsView();
}
}
}));
}

export function dispose(): void {
// Don't wait
fileWatchers.forEach(watcher => watcher.close().then(() => {}, () => {}));
if (sshConfigWatcher) {
sshConfigWatcher.close();
sshConfigWatcher = undefined;
}
disposables.forEach(d => d.dispose());
}

async function enableSshTargetsViewAndRun<T>(func: (...paras: any[]) => T | Promise<T>, ...args: any[]): Promise<T> {
await enableSshTargetsView();
return func(...args);
}

async function enableSshTargetsView(): Promise<void> {
if (sshTargetsViewEnabled || sshTargetsViewSetting === 'disabled') {
return;
}
await vscode.commands.executeCommand('setContext', 'enableCppSshTargetsView', true);
sshConfigWatcher = chokidar.watch(getSshConfigurationFiles(), { ignoreInitial: true })
.on('add', () => vscode.commands.executeCommand(refreshCppSshTargetsViewCmd))
.on('change', () => vscode.commands.executeCommand(refreshCppSshTargetsViewCmd))
.on('unlink', () => vscode.commands.executeCommand(refreshCppSshTargetsViewCmd));
sshTargetsViewEnabled = true;
}

async function disableSshTargetsView(): Promise<void> {
await vscode.commands.executeCommand('setContext', 'enableCppSshTargetsView', false);
if (sshConfigWatcher) {
sshConfigWatcher.close();
sshConfigWatcher = undefined;
}
sshTargetsViewEnabled = false;
}

async function addSshTargetImpl(): Promise<string> {
const name: string | undefined = await vscode.window.showInputBox({
title: localize('enter.ssh.target.name', 'Enter SSH Target Name'),
Expand Down
4 changes: 4 additions & 0 deletions Extension/src/LanguageServer/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,10 @@ export class CppSettings extends Settings {
&& vscode.workspace.getConfiguration("workbench").get<string>("colorTheme") !== "Default High Contrast";
}

public get sshTargetsView(): string {
return super.Section.get<string>("sshTargetsView") ?? 'default';
}

public toggleSetting(name: string, value1: string, value2: string): void {
const value: string | undefined = super.Section.get<string>(name);
super.Section.update(name, value === value1 ? value2 : value1, getTarget());
Expand Down
4 changes: 2 additions & 2 deletions Extension/src/SSH/TargetsView/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,5 @@ export class LabelLeafNode implements BaseNode {
}
}

export const refreshCppSshTargetsView: string = 'C_Cpp.refreshCppSshTargetsView';
export const addSshTarget: string = 'C_Cpp.addSshTarget';
export const refreshCppSshTargetsViewCmd: string = 'C_Cpp.refreshCppSshTargetsView';
export const addSshTargetCmd: string = 'C_Cpp.addSshTarget';
6 changes: 3 additions & 3 deletions Extension/src/SSH/TargetsView/sshTargetsProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { getSshConfigHostInfos } from '../sshHosts';
import * as vscode from 'vscode';
import { addSshTarget, BaseNode, LabelLeafNode, refreshCppSshTargetsView } from './common';
import { addSshTargetCmd, BaseNode, LabelLeafNode, refreshCppSshTargetsViewCmd } from './common';
import { TargetLeafNode, filesWritable, setActiveSshTarget, _activeTarget, workspaceState_activeSshTarget } from './targetNodes';
import { extensionContext, ISshConfigHostInfo } from '../../common';
import * as nls from 'vscode-nls';
Expand Down Expand Up @@ -97,7 +97,7 @@ export async function getActiveSshTarget(selectWhenNotSet: boolean = true): Prom
throw Error(localize('active.ssh.target.selection.cancelled', 'Active SSH target selection cancelled.'));
}
await setActiveSshTarget(name);
await vscode.commands.executeCommand(refreshCppSshTargetsView);
await vscode.commands.executeCommand(refreshCppSshTargetsViewCmd);
}
return _activeTarget;
}
Expand All @@ -113,7 +113,7 @@ export async function selectSshTarget(): Promise<string | undefined> {
return undefined;
}
if (selection === addNewSshTarget) {
return vscode.commands.executeCommand(addSshTarget);
return vscode.commands.executeCommand(addSshTargetCmd);
}
return selection;
}

0 comments on commit 3a8e920

Please sign in to comment.