From 04797784c57857d7ca12ff9cc3406ee478c5e563 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Fri, 19 Apr 2019 17:50:50 -0700 Subject: [PATCH 1/2] Adding support for .env files for cppvsdbg This PR allows users to have a .env file that listed as KEY=VALUE or KEY="VALUE WITH SPACE" to be used as environment variables when launching a process. Anything that begins with '#' is treated as a comment. Blank lines are ignored. This .env file will be used if envFile passed in with the launch.json. It will also work with the existing environment variable, however anything listed in the .env file will overwrite anything from the environment field in the launch.json. --- Extension/package-lock.json | 76 ++++++++++++ Extension/package.json | 5 + .../src/Debugger/ParsedEnvironmentFile.ts | 85 +++++++++++++ .../src/Debugger/configurationProvider.ts | 32 ++++- .../unitTests/ParsedEnvironmentFile.test.ts | 112 ++++++++++++++++++ Extension/tools/OptionsSchema.json | 5 + 6 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 Extension/src/Debugger/ParsedEnvironmentFile.ts create mode 100644 Extension/test/unitTests/ParsedEnvironmentFile.test.ts diff --git a/Extension/package-lock.json b/Extension/package-lock.json index 5c8abb216..af65a7fff 100644 --- a/Extension/package-lock.json +++ b/Extension/package-lock.json @@ -2109,6 +2109,10 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "aproba": { @@ -2128,11 +2132,19 @@ "balanced-match": { "version": "1.0.0", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "balanced-match": "^1.0.0", @@ -2147,16 +2159,28 @@ "code-point-at": { "version": "1.1.0", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "core-util-is": { @@ -2261,6 +2285,10 @@ "inherits": { "version": "2.0.3", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "ini": { @@ -2271,6 +2299,10 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "number-is-nan": "^1.0.0" @@ -2284,6 +2316,10 @@ "minimatch": { "version": "3.0.4", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "brace-expansion": "^1.1.7" @@ -2292,11 +2328,19 @@ "minimist": { "version": "0.0.8", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "safe-buffer": "^5.1.2", @@ -2314,6 +2358,10 @@ "mkdirp": { "version": "0.5.1", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "minimist": "0.0.8" @@ -2388,6 +2436,10 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "object-assign": { @@ -2398,6 +2450,10 @@ "once": { "version": "1.4.0", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "wrappy": "1" @@ -2475,6 +2531,10 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "safer-buffer": { @@ -2505,6 +2565,10 @@ "string-width": { "version": "1.0.2", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "code-point-at": "^1.0.0", @@ -2523,6 +2587,10 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "ansi-regex": "^2.0.0" @@ -2563,11 +2631,19 @@ "wrappy": { "version": "1.0.2", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, +<<<<<<< HEAD +======= + "dev": true, +>>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true } } diff --git a/Extension/package.json b/Extension/package.json index 57e7924c8..21f40587f 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -1201,6 +1201,11 @@ }, "default": [] }, + "envFile": { + "type": "string", + "description": "Environment variables passed to the program by a file.", + "default": "${workspaceFolder}/.env" + }, "symbolSearchPath": { "type": "string", "description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".", diff --git a/Extension/src/Debugger/ParsedEnvironmentFile.ts b/Extension/src/Debugger/ParsedEnvironmentFile.ts new file mode 100644 index 000000000..151ca7416 --- /dev/null +++ b/Extension/src/Debugger/ParsedEnvironmentFile.ts @@ -0,0 +1,85 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'fs'; + +export interface Environment { + name: string; + value: string; +} + +export class ParsedEnvironmentFile { + public Env: Environment[]; + public Warning: string | null; + + private constructor(env: Environment[], warning: string | null) { + this.Env = env; + this.Warning = warning; + } + + public static CreateFromFile(envFile: string, initialEnv: Environment[] | undefined): ParsedEnvironmentFile { + let content: string = fs.readFileSync(envFile, "utf8"); + return this.CreateFromContent(content, envFile, initialEnv); + } + + public static CreateFromContent(content: string, envFile: string, initialEnv: Environment[] | undefined): ParsedEnvironmentFile { + + // Remove UTF-8 BOM if present + if (content.charAt(0) === '\uFEFF') { + content = content.substr(1); + } + + let parseErrors: string[] = []; + let env: Map = new Map(); + + if (initialEnv) { + // Convert array to map to prevent duplicate keys being created. + // If a duplicate key is found, replace it. + initialEnv.forEach((e) => { + env.set(e.name, e.value); + }); + } + + content.split("\n").forEach(line => { + // Split the line between key and value + const r: RegExpMatchArray = line.match(/^\s*([\w\.\-]+)\s*=\s*(.*)?\s*$/); + + if (r !== null) { + const key: string = r[1]; + let value: string = r[2] || ""; + if ((value.length > 0) && (value.charAt(0) === '"') && (value.charAt(value.length - 1) === '"')) { + value = value.replace(/\\n/gm, "\n"); + } + + value = value.replace(/(^['"]|['"]$)/g, ""); + + env.set(key, value); + } else { + // Blank lines and lines starting with # are no parse errors + const comments: RegExp = new RegExp(/^\s*(#|$)/); + if (!comments.test(line)) { + parseErrors.push(line); + } + } + }); + + // show error message if single lines cannot get parsed + let warning: string = null; + if (parseErrors.length !== 0) { + warning = "Ignoring non-parseable lines in envFile " + envFile + ": "; + parseErrors.forEach(function (value, idx, array): void { + warning += "\"" + value + "\"" + ((idx !== array.length - 1) ? ", " : "."); + }); + } + + // Convert env map back to array. + const arrayEnv: Environment[] = []; + for (let key of env.keys()) { + arrayEnv.push({name: key, value: env.get(key)}); + } + + return new ParsedEnvironmentFile(arrayEnv, warning); + } +} \ No newline at end of file diff --git a/Extension/src/Debugger/configurationProvider.ts b/Extension/src/Debugger/configurationProvider.ts index 7c312b3b6..385bab4ce 100644 --- a/Extension/src/Debugger/configurationProvider.ts +++ b/Extension/src/Debugger/configurationProvider.ts @@ -16,6 +16,7 @@ import { buildAndDebugActiveFileStr } from './extension'; import { IConfiguration, IConfigurationSnippet, DebuggerType, MIConfigurations, WindowsConfigurations, WSLConfigurations, PipeTransportConfigurations } from './configurations'; import { parse } from 'jsonc-parser'; import { PlatformInformation } from '../platform'; +import { Environment, ParsedEnvironmentFile } from './ParsedEnvironmentFile'; function isDebugLaunchStr(str: string): boolean { return str === "(gdb) Launch" || str === "(lldb) Launch" || str === "(Windows) Launch"; @@ -188,7 +189,7 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { // Disable debug heap by default, enable if 'enableDebugHeap' is set. if (!config.enableDebugHeap) { - const disableDebugHeapEnvSetting : any = {"name" : "_NO_DEBUG_HEAP", "value" : "1"}; + const disableDebugHeapEnvSetting : Environment = {"name" : "_NO_DEBUG_HEAP", "value" : "1"}; if (config.environment && util.isArray(config.environment)) { config.environment.push(disableDebugHeapEnvSetting); @@ -196,6 +197,24 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { config.environment = [disableDebugHeapEnvSetting]; } } + + // Add environment variables from .env file + if (config.envFile) { + try { + const parsedFile: ParsedEnvironmentFile = ParsedEnvironmentFile.CreateFromFile(config.envFile.replace(/\${workspaceFolder}/g, folder.uri.path), config["environment"]); + + // show error message if single lines cannot get parsed + if (parsedFile.Warning) { + CppConfigurationProvider.showFileWarningAsync(parsedFile.Warning, config.envFile); + } + + config.environment = parsedFile.Env; + + delete config.envFile; + } catch (e) { + throw new Error("Can't parse envFile " + config.envFile); + } + } } // Modify WSL config for OpenDebugAD7 @@ -224,6 +243,17 @@ class CppConfigurationProvider implements vscode.DebugConfigurationProvider { // if config or type is not specified, return null to trigger VS Code to open a configuration file https://github.com/Microsoft/vscode/issues/54213 return config && config.type ? config : null; } + + private static async showFileWarningAsync(message: string, fileName: string) : Promise { + const openItem: vscode.MessageItem = { title: 'Open envFile' }; + let result: vscode.MessageItem = await vscode.window.showWarningMessage(message, openItem); + if (result && result.title === openItem.title) { + let doc: vscode.TextDocument = await vscode.workspace.openTextDocument(fileName); + if (doc) { + vscode.window.showTextDocument(doc); + } + } + } } export class CppVsDbgConfigurationProvider extends CppConfigurationProvider { diff --git a/Extension/test/unitTests/ParsedEnvironmentFile.test.ts b/Extension/test/unitTests/ParsedEnvironmentFile.test.ts new file mode 100644 index 000000000..0afec524d --- /dev/null +++ b/Extension/test/unitTests/ParsedEnvironmentFile.test.ts @@ -0,0 +1,112 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { Environment, ParsedEnvironmentFile } from '../../src/Debugger/ParsedEnvironmentFile' +import * as assert from 'assert'; + +// Because the environment variable is set as an array, the index does not matter. +function AssertEnvironmentEqual(env: Environment[], name: string, value: string) { + let found: boolean = false; + for (let e of env) + { + if (e.name == name) + { + assert(e.value == value, `Checking if ${e.value} == ${value}`); + found = true; + break; + } + } + assert(found, `${name} was not found in env.`) +} + +suite("ParsedEnvironmentFile", () => { + test("Add single variable", () => { + const content = `MyName=VALUE`; + const fakeConfig : Environment[] = []; + const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]); + + assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`); + AssertEnvironmentEqual(result.Env, "MyName", "VALUE"); + }); + + test("Handle quoted values", () => { + const content = `MyName="VALUE"`; + const fakeConfig : Environment[] = []; + const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]); + + assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`); + AssertEnvironmentEqual(result.Env, "MyName", "VALUE"); + }); + + test("Handle BOM", () => { + const content = "\uFEFFMyName=VALUE"; + const fakeConfig : Environment[] = []; + const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]); + + assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`); + AssertEnvironmentEqual(result.Env, "MyName", "VALUE"); + }); + + test("Add multiple variables", () => { + const content = ` +MyName1=Value1 +MyName2=Value2 + +`; + const fakeConfig : Environment[] = []; + const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]); + + assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`); + AssertEnvironmentEqual(result.Env, "MyName1", "Value1"); + AssertEnvironmentEqual(result.Env, "MyName2", "Value2"); + }); + + test("Update variable", () => { + const content = ` +MyName1=Value1 +MyName2=Value2 + +`; + const initialEnv : Environment[] = []; + initialEnv.push({name : "MyName1", value: "Value7"}); + initialEnv.push({name : "ThisShouldNotChange", value : "StillHere"}); + + const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", initialEnv); + + assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`); + AssertEnvironmentEqual(result.Env, "MyName1", "Value1"); + AssertEnvironmentEqual(result.Env, "ThisShouldNotChange", "StillHere"); + AssertEnvironmentEqual(result.Env, "MyName2", "Value2"); + }); + + test("Handle comments", () => { + const content = `# This is an environment file +MyName1=Value1 +# This is a comment in the middle of the file +MyName2=Value2 +`; + const fakeConfig : Environment[] = []; + const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]); + + assert(result.Warning == null, `Failed to assert that Warning was empty: ${result.Warning}`); + AssertEnvironmentEqual(result.Env, "MyName1", "Value1"); + AssertEnvironmentEqual(result.Env, "MyName2", "Value2"); + }); + + test("Handle invalid lines", () => { + const content = ` +This_Line_Is_Wrong +MyName1=Value1 +MyName2=Value2 + +`; + const fakeConfig : Environment[] = []; + const result = ParsedEnvironmentFile.CreateFromContent(content, "TestEnvFileName", fakeConfig["env"]); + + assert(result.Warning.startsWith("Ignoring non-parseable lines in envFile TestEnvFileName"), 'Checking if warning exists'); + AssertEnvironmentEqual(result.Env, "MyName1", "Value1"); + AssertEnvironmentEqual(result.Env, "MyName2", "Value2"); + }); +}); \ No newline at end of file diff --git a/Extension/tools/OptionsSchema.json b/Extension/tools/OptionsSchema.json index 002642495..272221b00 100644 --- a/Extension/tools/OptionsSchema.json +++ b/Extension/tools/OptionsSchema.json @@ -429,6 +429,11 @@ }, "default": [] }, + "envFile": { + "type": "string", + "description": "Environment variables passed to the program by a file.", + "default": "${workspaceFolder}/.env" + }, "symbolSearchPath": { "type": "string", "description": "Semicolon separated list of directories to use to search for symbol (that is, pdb) files. Example: \"c:\\dir1;c:\\dir2\".", From 826ba4caeacb2e3af6d7f2161a10e765adce5a58 Mon Sep 17 00:00:00 2001 From: Andrew Wang Date: Wed, 24 Apr 2019 20:16:08 -0700 Subject: [PATCH 2/2] Update 'envFile' description and add documentation --- Extension/package-lock.json | 76 ------------------------------ Extension/package.json | 2 +- Extension/tools/OptionsSchema.json | 2 +- launch.md | 20 ++++++++ 4 files changed, 22 insertions(+), 78 deletions(-) diff --git a/Extension/package-lock.json b/Extension/package-lock.json index af65a7fff..5c8abb216 100644 --- a/Extension/package-lock.json +++ b/Extension/package-lock.json @@ -2109,10 +2109,6 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "aproba": { @@ -2132,19 +2128,11 @@ "balanced-match": { "version": "1.0.0", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "balanced-match": "^1.0.0", @@ -2159,28 +2147,16 @@ "code-point-at": { "version": "1.1.0", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "core-util-is": { @@ -2285,10 +2261,6 @@ "inherits": { "version": "2.0.3", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "ini": { @@ -2299,10 +2271,6 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "number-is-nan": "^1.0.0" @@ -2316,10 +2284,6 @@ "minimatch": { "version": "3.0.4", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "brace-expansion": "^1.1.7" @@ -2328,19 +2292,11 @@ "minimist": { "version": "0.0.8", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "safe-buffer": "^5.1.2", @@ -2358,10 +2314,6 @@ "mkdirp": { "version": "0.5.1", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "minimist": "0.0.8" @@ -2436,10 +2388,6 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "object-assign": { @@ -2450,10 +2398,6 @@ "once": { "version": "1.4.0", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "wrappy": "1" @@ -2531,10 +2475,6 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "safer-buffer": { @@ -2565,10 +2505,6 @@ "string-width": { "version": "1.0.2", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "code-point-at": "^1.0.0", @@ -2587,10 +2523,6 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true, "requires": { "ansi-regex": "^2.0.0" @@ -2631,19 +2563,11 @@ "wrappy": { "version": "1.0.2", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, -<<<<<<< HEAD -======= - "dev": true, ->>>>>>> 98912ec... Adding support for .env files for cppvsdbg "optional": true } } diff --git a/Extension/package.json b/Extension/package.json index 21f40587f..1ebf326d8 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -1203,7 +1203,7 @@ }, "envFile": { "type": "string", - "description": "Environment variables passed to the program by a file.", + "description": "Absolute path to a file containing environment variable definitions. These file has key value pairs sepearted by an equals sign per line. E.g. KEY=VALUE", "default": "${workspaceFolder}/.env" }, "symbolSearchPath": { diff --git a/Extension/tools/OptionsSchema.json b/Extension/tools/OptionsSchema.json index 272221b00..56a144a04 100644 --- a/Extension/tools/OptionsSchema.json +++ b/Extension/tools/OptionsSchema.json @@ -431,7 +431,7 @@ }, "envFile": { "type": "string", - "description": "Environment variables passed to the program by a file.", + "description": "Absolute path to a file containing environment variable definitions. These file has key value pairs sepearted by an equals sign per line. E.g. KEY=VALUE", "default": "${workspaceFolder}/.env" }, "symbolSearchPath": { diff --git a/launch.md b/launch.md index bbdf08e07..2c6f4d974 100644 --- a/launch.md +++ b/launch.md @@ -194,3 +194,23 @@ _Note: core dump debugging is not supported with MinGw._ * #### `sourceFileMap` This allows mapping of the compile time paths for source to local source locations. It is an object of key/value pairs and will resolve the first string-matched path. (example: `"sourceFileMap": { "/mnt/c": "c:\\" }` will map any path returned by the debugger that begins with `/mnt/c` and convert it to `c:\\`. You can have multiple mappings in the object but they will be handled in the order provided.) + +## Environment variable definitions file + +An environment variable definitions file is a simple text file containing key-value pairs in the form of `environment_variable=value`, with `#` used for comments. Multiline values are not supported. + +The `cppvsdbg` debugger configuration also contains an `envFile` property that allows you to easily set variables for debugging purposes. + +For example: + +**project.env file** + +```bash +# project.env + +# Example environment with key as 'MYENVRIONMENTPATH' and value as C:\\Users\\USERNAME\\Project +MYENVRIONMENTPATH=C:\\Users\\USERNAME\\Project + +# Variables with spaces +SPACED_OUT_PATH="C:\\This Has Spaces\\Project" +``` \ No newline at end of file