* UI View and some bug fixes.

* Added tree.ts missed by mistake from the previous commit

* Small followup.
This commit is contained in:
Andreea Isac 2020-09-03 09:47:23 -07:00 коммит произвёл GitHub
Родитель 36cfef01bc
Коммит aeab2e24df
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
9 изменённых файлов: 477 добавлений и 17 удалений

Просмотреть файл

@ -49,7 +49,18 @@
"onCommand:makefile.configure",
"onCommand:makefile.cleanConfigure",
"onCommand:makefile.preConfigure",
"onCommand:makefile.outline.setBuildConfiguration",
"onCommand:makefile.outline.setBuildTarget",
"onCommand:makefile.outline.buildTarget",
"onCommand:makefile.outline.buildCleanTarget",
"onCommand:makefile.outline.setLaunchConfiguration",
"onCommand:makefile.outline.launchDebug",
"onCommand:makefile.outline.launchRun",
"onCommand:makefile.outline.configure",
"onCommand:makefile.outline.cleanConfigure",
"onCommand:makefile.outline.preConfigure",
"onCommand:makefile.resetState",
"onView:makefile.outline",
"workspaceContains:makefile",
"workspaceContains:Makefile"
],
@ -104,6 +115,74 @@
"command": "makefile.preConfigure",
"title": "Makefile: Pre-Configure"
},
{
"command": "makefile.outline.buildTarget",
"title": "Build",
"icon": {
"light": "res/light/build.svg",
"dark": "res/dark/build.svg"
}
},
{
"command": "makefile.outline.buildCleanTarget",
"title": "Build clean"
},
{
"command": "makefile.outline.launchDebug",
"title": "Debug",
"icon": {
"light": "res/light/debug.svg",
"dark": "res/dark/debug.svg"
}
},
{
"command": "makefile.outline.launchRun",
"title": "Run in terminal",
"icon": {
"light": "res/light/run.svg",
"dark": "res/dark/run.svg"
}
},
{
"command": "makefile.outline.setBuildConfiguration",
"title": "Change build configuration",
"icon": {
"light": "res/light/edit.svg",
"dark": "res/dark/edit.svg"
}
},
{
"command": "makefile.outline.setBuildTarget",
"title": "Change build target",
"icon": {
"light": "res/light/edit.svg",
"dark": "res/dark/edit.svg"
}
},
{
"command": "makefile.outline.setLaunchConfiguration",
"title": "Change launch configuration",
"icon": {
"light": "res/light/edit.svg",
"dark": "res/dark/edit.svg"
}
},
{
"command": "makefile.outline.configure",
"title": "Configure",
"icon": {
"light": "res/light/configure.svg",
"dark": "res/dark/configure.svg"
}
},
{
"command": "makefile.outline.cleanConfigure",
"title": "Clean configure"
},
{
"command": "makefile.outline.preConfigure",
"title": "Pre-Configure"
},
{
"command": "makefile.resetState",
"title": "Makefile: Reset the Makefile Tools Extension workspace state (For troubleshooting)"
@ -306,6 +385,109 @@
"scope": "resource"
}
}
},
"viewsContainers": {
"activitybar": [
{
"id": "makefile__viewContainer",
"title": "Makefile",
"icon": "res/viewcontainer.svg"
}
]
},
"views": {
"makefile__viewContainer": [
{
"id": "makefile.outline",
"name": ""
}
]
},
"menus": {
"view/title": [
{
"command": "makefile.outline.preConfigure",
"when": "view == makefile.outline",
"group": "1_makefileOutline@1"
},
{
"command": "makefile.outline.configure",
"when": "view == makefile.outline",
"group": "1_makefileOutline@2"
},
{
"command": "makefile.outline.cleanConfigure",
"when": "view == makefile.outline",
"group": "1_makefileOutline@3"
},
{
"command": "makefile.outline.buildTarget",
"when": "view == makefile.outline",
"group": "navigation@1"
},
{
"command": "makefile.outline.buildCleanTarget",
"when": "view == makefile.outline",
"group": "1_makefileOutline@4"
},
{
"command": "makefile.outline.launchDebug",
"when": "view == makefile.outline",
"group": "navigation@2"
},
{
"command": "makefile.outline.launchRun",
"when": "view == makefile.outline",
"group": "navigation@3"
}
],
"view/item/context": [
{
"command": "makefile.outline.configure",
"when": "view == makefile.outline && viewItem =~ /nodeType=configuration/",
"group": "1_stateActions@1"
},
{
"command": "makefile.outline.cleanConfigure",
"when": "view == makefile.outline && viewItem =~ /nodeType=configuration/",
"group": "1_stateActions@2"
},
{
"command": "makefile.outline.setBuildConfiguration",
"when": "view == makefile.outline && viewItem =~ /nodeType=configuration/",
"group": "inline@1"
},
{
"command": "makefile.outline.buildTarget",
"when": "view == makefile.outline && viewItem =~ /nodeType=buildTarget/",
"group": "1_stateActions@1"
},
{
"command": "makefile.outline.buildCleanTarget",
"when": "view == makefile.outline && viewItem =~ /nodeType=buildTarget/",
"group": "1_stateActions@2"
},
{
"command": "makefile.outline.setBuildTarget",
"when": "view == makefile.outline && viewItem =~ /nodeType=buildTarget/",
"group": "inline@1"
},
{
"command": "makefile.outline.launchDebug",
"when": "view == makefile.outline && viewItem =~ /nodeType=launchTarget/",
"group": "1_stateActions@1"
},
{
"command": "makefile.outline.launchRun",
"when": "view == makefile.outline && viewItem =~ /nodeType=launchTarget/",
"group": "1_stateActions@2"
},
{
"command": "makefile.outline.setLaunchConfiguration",
"when": "view == makefile.outline && viewItem =~ /nodeType=launchTarget/",
"group": "inline@1"
}
]
}
},
"scripts": {

8
res/dark/build.svg Normal file
Просмотреть файл

@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.854 6.6L10.354 4.1L9.646 3.4L8 5.043V0H7V5.043L5.354 3.4L4.646 4.1L7.146 6.6H7.854Z" fill="#C5C5C5"/>
<path d="M14 14.5V5H13V14H2V5H1V14.5L1.5 15H13.5L14 14.5Z" fill="#C5C5C5"/>
<path d="M5 12.5V11.5L4.5 11H3.5L3 11.5V12.5L3.5 13H4.5L5 12.5Z" fill="#C5C5C5"/>
<path d="M9 11.5V12.5L8.5 13H7.5L7 12.5V11.5L7.5 11H8.5L9 11.5Z" fill="#C5C5C5"/>
<path d="M7 9.5V8.5L6.5 8H5.5L5 8.5V9.5L5.5 10H6.5L7 9.5Z" fill="#C5C5C5"/>
<path d="M11 8.5V9.5L10.5 10H9.5L9 9.5V8.5L9.5 8H10.5L11 8.5Z" fill="#C5C5C5"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 613 B

8
res/light/build.svg Normal file
Просмотреть файл

@ -0,0 +1,8 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.854 6.6L10.354 4.1L9.646 3.4L8 5.043V0H7V5.043L5.354 3.4L4.646 4.1L7.146 6.6H7.854Z" fill="#424242"/>
<path d="M14 14.5V5H13V14H2V5H1V14.5L1.5 15H13.5L14 14.5Z" fill="#424242"/>
<path d="M5 12.5V11.5L4.5 11H3.5L3 11.5V12.5L3.5 13H4.5L5 12.5Z" fill="#424242"/>
<path d="M9 11.5V12.5L8.5 13H7.5L7 12.5V11.5L7.5 11H8.5L9 11.5Z" fill="#424242"/>
<path d="M7 9.5V8.5L6.5 8H5.5L5 8.5V9.5L5.5 10H6.5L7 9.5Z" fill="#424242"/>
<path d="M11 8.5V9.5L10.5 10H9.5L9 9.5V8.5L9.5 8H10.5L11 8.5Z" fill="#424242"/>
</svg>

После

Ширина:  |  Высота:  |  Размер: 613 B

Просмотреть файл

@ -662,6 +662,10 @@ export async function initFromStateAndSettings(): Promise<void> {
analyzeConfigureParams();
extension._projectOutlineProvider.update(extension.getState().buildConfiguration || "unset",
extension.getState().buildTarget || "unset",
extension.getState().launchConfiguration || "unset");
// Verify the dirty state of the IntelliSense config provider and update accordingly.
// The makefile.configureOnEdit setting can be set to false when this behavior is inconvenient.
vscode.window.onDidChangeActiveTextEditor(e => {
@ -911,6 +915,7 @@ export async function initFromStateAndSettings(): Promise<void> {
export function setConfigurationByName(configurationName: string): void {
extension.getState().buildConfiguration = configurationName;
setCurrentMakefileConfiguration(configurationName);
extension._projectOutlineProvider.updateConfiguration(configurationName);
}
export function prepareConfigurationsQuickPick(): string[] {
@ -989,6 +994,7 @@ export function setTargetByName(targetName: string) : void {
statusBar.setTarget(displayTarget);
logger.message("Setting target " + displayTarget);
extension.getState().buildTarget = currentTarget;
extension._projectOutlineProvider.updateBuildTarget(targetName);
}
// Fill a drop-down with all the target names run by building the makefile for the current configuration
@ -1001,7 +1007,10 @@ export async function selectTarget(): Promise<void> {
}
// warn about an out of date configure state and configure if makefile.configureAfterCommand allows.
if (extension.getState().configureDirty) {
if (extension.getState().configureDirty ||
// The configure state might not be dirty from the last session but if the project is set to skip
// configure on open and no configure happened yet we still must warn.
(configureOnOpen === false && !extension.getRanConfigureInSession())) {
logger.message("The project needs a configure to populate the build targets correctly.");
if (configureAfterCommand) {
let retc: number = await make.cleanConfigure(make.TriggeredBy.configureBeforeTargetChange);
@ -1084,6 +1093,8 @@ export function setLaunchConfigurationByName(launchConfigurationName: string) :
extension.getState().launchConfiguration = undefined;
statusBar.setLaunchConfiguration("No launch configuration set");
}
extension._projectOutlineProvider.updateLaunchTarget(launchConfigurationName);
}
// Fill a drop-down with all the launch configurations found for binaries built by the makefile
@ -1096,7 +1107,10 @@ export async function selectLaunchConfiguration(): Promise<void> {
}
// warn about an out of date configure state and configure if makefile.configureAfterCommand allows.
if (extension.getState().configureDirty) {
if (extension.getState().configureDirty ||
// The configure state might not be dirty from the last session but if the project is set to skip
// configure on open and no configure happened yet we still must warn.
(configureOnOpen === false && !extension.getRanConfigureInSession())) {
logger.message("The project needs a configure to populate the launch targets correctly.");
if (configureAfterCommand) {
let retc: number = await make.cleanConfigure(make.TriggeredBy.configureBeforeLaunchTargetChange);
@ -1109,12 +1123,24 @@ export async function selectLaunchConfiguration(): Promise<void> {
// TODO: create a quick pick with description and details for items
// to better view the long targets commands
// In the quick pick, include also any makefile.launchConfigurations entries,
// as long as they exist on disk and without allowing duplicates.
let launchTargetsNames: string[] = launchTargets;
launchConfigurations.forEach(launchConfiguration => {
if (util.checkFileExistsSync(launchConfiguration.binaryPath)) {
launchTargetsNames.push(launchConfigurationToString(launchConfiguration));
}
});
launchTargetsNames = launchTargetsNames.sort().filter(function (elem, index, self): boolean {
return index === self.indexOf(elem);
});
let options: vscode.QuickPickOptions = {};
options.ignoreFocusOut = true; // so that the logger and the quick pick don't compete over focus
if (launchTargets.length === 0) {
options.placeHolder = "No launch targets identified";
}
const chosen: string | undefined = await vscode.window.showQuickPick(launchTargets, options);
const chosen: string | undefined = await vscode.window.showQuickPick(launchTargetsNames, options);
if (chosen) {
let currentLaunchConfiguration: LaunchConfiguration | undefined = getCurrentLaunchConfiguration();

Просмотреть файл

@ -9,6 +9,7 @@ import * as make from './make';
import * as parser from './parser';
import * as state from './state';
import * as telemetry from './telemetry';
import * as tree from './tree';
import * as ui from './ui';
import * as util from './util';
import * as vscode from 'vscode';
@ -20,6 +21,12 @@ let launcher: launch.Launcher = launch.getLauncher();
export let extension: MakefileToolsExtension;
export class MakefileToolsExtension {
public readonly _projectOutlineProvider = new tree.ProjectOutlineProvider();
private readonly _projectOutlineTreeView = vscode.window.createTreeView('makefile.outline', {
treeDataProvider: this._projectOutlineProvider,
showCollapseAll: false
});
private readonly cppConfigurationProvider = new cpptools.CppConfigurationProvider();
private mementoState = new state.StateManager(this.extensionContext);
private cppToolsAPI?: cpp.CppToolsApi;
@ -36,6 +43,7 @@ export class MakefileToolsExtension {
}
public dispose(): void {
this._projectOutlineTreeView.dispose();
if (this.cppToolsAPI) {
this.cppToolsAPI.dispose();
}
@ -184,6 +192,46 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
extension.getState().reset();
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.configure', () => {
return vscode.commands.executeCommand("makefile.configure");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.cleanConfigure', () => {
return vscode.commands.executeCommand("makefile.cleanConfigure");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.preConfigure', () => {
return vscode.commands.executeCommand("makefile.preConfigure");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.setLaunchConfiguration', () => {
return vscode.commands.executeCommand("makefile.setLaunchConfiguration");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.launchDebug', () => {
return vscode.commands.executeCommand("makefile.launchDebug");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.launchRun', () => {
return vscode.commands.executeCommand("makefile.launchRun");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.setBuildTarget', () => {
return vscode.commands.executeCommand("makefile.setBuildTarget");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.buildTarget', () => {
return vscode.commands.executeCommand("makefile.buildTarget");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.buildCleanTarget', () => {
return vscode.commands.executeCommand("makefile.buildCleanTarget");
}));
context.subscriptions.push(vscode.commands.registerCommand('makefile.outline.setBuildConfiguration', () => {
return vscode.commands.executeCommand("makefile.setBuildConfiguration");
}));
configuration.readLoggingLevel();
configuration.readExtensionLog();

Просмотреть файл

@ -542,16 +542,13 @@ export async function runPreConfigureScript(progress: vscode.Progress<{}>, scrip
}
try {
let stdoutStr: string = "";
let stderrStr: string = "";
let stdout: any = (result: string): void => {
stdoutStr += result;
progress.report({increment: 1, message: "..."});
logger.messageNoCR(result);
};
let stderr: any = (result: string): void => {
stderrStr += result;
logger.messageNoCR(result);
};
let closing: any = (retCode: number, signal: string): void => {
@ -559,7 +556,6 @@ export async function runPreConfigureScript(progress: vscode.Progress<{}>, scrip
logger.message("The pre-configure succeeded.");
} else {
logger.message("The pre-configure script failed. This project may not configure successfully.");
logger.message(stderrStr);
}
// Apply the environment produced by running the pre-configure script.

Просмотреть файл

@ -609,7 +609,7 @@ function currentPathAfterCommand(line: string, currentPathHistory: string[]): st
// equivalent to pushd
let match: RegExpMatchArray | null = line.match("(.*)(Entering directory ')(.*)'");
if (match) {
newCurrentPath = util.makeFullPath(match[3], lastCurrentPath) || "";
newCurrentPath = util.makeFullPath(match[4], lastCurrentPath) || "";
} else {
newCurrentPath = "Could not parse directory";
}

190
src/tree.ts Normal file
Просмотреть файл

@ -0,0 +1,190 @@
// Tree.ts
import * as configuration from './configuration';
import * as util from './util';
import * as vscode from 'vscode';
interface NamedItem {
name: string;
}
abstract class BaseNode {
constructor(public readonly id: string) { }
abstract getTreeItem(): vscode.TreeItem;
abstract getChildren(): BaseNode[];
}
export class BuildTargetNode extends BaseNode {
constructor(targetName: string) {
super(`buildTarget:${targetName}`);
this._name = targetName;
}
_name: string;
update(targetName: string): void {
this._name = `Build target: [${targetName}]`;
}
getChildren(): BaseNode[] {
return [];
}
getTreeItem(): vscode.TreeItem {
try {
const item: vscode.TreeItem = new vscode.TreeItem(this._name);
item.collapsibleState = vscode.TreeItemCollapsibleState.None;
item.tooltip = "The makefile target currently selected for build.";
item.contextValue = [
`nodeType=buildTarget`,
].join(',');
return item;
} catch (e) {
return new vscode.TreeItem(`${this._name} (There was an issue rendering this item.)`);
}
}
}
export class LaunchTargetNode extends BaseNode {
_name: string;
_toolTip: string;
// Keep the tree node label as short as possible.
// The binary path is the most important component of a launch target.
getShortLaunchTargetName(completeLaunchTargetName: string): string {
let launchConfiguration: configuration.LaunchConfiguration | undefined = configuration.stringToLaunchConfiguration(completeLaunchTargetName);
let shortName: string;
if (!launchConfiguration) {
shortName = "Unset";
} else {
if (vscode.workspace.workspaceFolders) {
// In a complete launch target string, the binary path is relative to cwd.
// In here, since we don't show cwd, make it relative to current workspace folder.
shortName = util.makeRelPath(launchConfiguration.binaryPath, vscode.workspace.workspaceFolders[0].uri.fsPath);
} else {
// Just in case, if for some reason we don't have a workspace folder, return full binary path.
shortName = launchConfiguration.binaryPath;
}
}
return `Launch target: [${shortName}]`;
}
constructor(targetName: string) {
super(`launchTarget:${targetName}`);
// Show the complete launch target name as tooltip and the short name as label
this._name = this.getShortLaunchTargetName(targetName);
this._toolTip = targetName;
}
update(targetName: string): void {
// Show the complete launch target name as tooltip and the short name as label
this._name = this.getShortLaunchTargetName(targetName);
this._toolTip = targetName;
}
getChildren(): BaseNode[] {
return [];
}
getTreeItem(): vscode.TreeItem {
try {
const item: vscode.TreeItem = new vscode.TreeItem(this._name);
item.collapsibleState = vscode.TreeItemCollapsibleState.None;
item.tooltip = `The launch target currently selected for debug and run in terminal.\n${this._toolTip}`;
item.contextValue = [
`nodeType=launchTarget`,
].join(',');
return item;
} catch (e) {
return new vscode.TreeItem(`${this._name} (There was an issue rendering this item.)`);
}
}
}
export class ConfigurationNode extends BaseNode {
constructor(configurationName: string) {
super(`configuration:${configurationName}`);
this._name = configurationName;
}
_name: string;
update(configurationName: string): void {
this._name = `Configuration: [${configurationName}]`;
}
getChildren(): BaseNode[] {
return [];
}
getTreeItem(): vscode.TreeItem {
try {
const item: vscode.TreeItem = new vscode.TreeItem(this._name);
item.collapsibleState = vscode.TreeItemCollapsibleState.None;
item.tooltip = "The makefile configuration currently selected from settings ('makefile.configurations').";
item.contextValue = [
`nodeType=configuration`,
].join(',');
return item;
} catch (e) {
return new vscode.TreeItem(`${this._name} (There was an issue rendering this item.)`);
}
}
}
export class ProjectOutlineProvider implements vscode.TreeDataProvider<BaseNode> {
private readonly _changeEvent = new vscode.EventEmitter<BaseNode | null>();
constructor() {
this._currentConfigurationItem = new ConfigurationNode("Unset");
this._currentBuildTargetItem = new BuildTargetNode("Unset");
this._currentLaunchTargetItem = new LaunchTargetNode("Unset");
}
private _currentConfigurationItem: ConfigurationNode;
private _currentBuildTargetItem: BuildTargetNode;
private _currentLaunchTargetItem: LaunchTargetNode;
get onDidChangeTreeData(): any {
return this._changeEvent.event;
}
async getTreeItem(node: BaseNode): Promise<vscode.TreeItem> {
return node.getTreeItem();
}
getChildren(node?: BaseNode): BaseNode[] {
if (node) {
return node.getChildren();
}
return [this._currentConfigurationItem, this._currentBuildTargetItem, this._currentLaunchTargetItem];
}
update(configuration: string, buildTarget: string, launchTarget: string): void {
this._currentConfigurationItem.update(configuration);
this._currentBuildTargetItem.update(buildTarget);
this._currentLaunchTargetItem.update(launchTarget);
this._changeEvent.fire(null);
}
updateConfiguration(configuration: string): void {
this._currentConfigurationItem.update(configuration);
this._changeEvent.fire(null);
}
updateBuildTarget(buildTarget: string): void {
this._currentBuildTargetItem.update(buildTarget);
this._changeEvent.fire(null);
}
updateLaunchTarget(launchTarget: string): void {
this._currentLaunchTargetItem.update(launchTarget);
this._changeEvent.fire(null);
}
}

Просмотреть файл

@ -1,4 +1,6 @@
// UI support for this extension: buttons and quickpicks.
// Deprecated UI support for buttons and quickpicks.
// Replaced by makefile.outline view in the left side bar.
// To be removed, hidden for now.
import * as vscode from 'vscode';
@ -35,35 +37,35 @@ export class UI {
this.configurationButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 4.6);
this.configurationButton.command = "makefile.setBuildConfiguration";
this.configurationButton.tooltip = "Click to select the workspace make configuration";
this.configurationButton.show();
this.configurationButton.hide();
this.targetButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 4.5);
this.targetButton.command = "makefile.setBuildTarget";
this.targetButton.tooltip = "Click to select the target to be run by make";
this.targetButton.show();
this.targetButton.hide();
this.buildButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 4.4);
this.buildButton.command = "makefile.buildTarget";
this.buildButton.tooltip = "Click to build the selected target";
this.buildButton.text = "$(gear) Build";
this.buildButton.show();
this.buildButton.hide();
this.launchConfigurationButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 4.3);
this.launchConfigurationButton.command = "makefile.setLaunchConfiguration";
this.launchConfigurationButton.tooltip = "Click to select the make launch configuration (binary, args and current path)";
this.launchConfigurationButton.show();
this.launchConfigurationButton.hide();
this.debugButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 4.2);
this.debugButton.command = "makefile.launchDebug";
this.debugButton.tooltip = "Click to debug the selected executable";
this.debugButton.text = "$(bug) Debug";
this.debugButton.show();
this.debugButton.hide();
this.runButton = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 4.1);
this.runButton.command = "makefile.launchRun";
this.runButton.tooltip = "Click to launch the selected executable";
this.runButton.text = "$(terminal) Run";
this.runButton.show();
this.runButton.hide();
}
public dispose(): void {