VSCode — отличный инструмент для разработки. Я пользуюсь им уже много лет, и он меня полностью устраивал для работы с Go. Расширение vscode-go просто замечательное: оно поддерживает всё необходимое — от сниппетов до отладки через Delve. Но оно кривовато.
Недавно мне понадобилось работать с проектом, в котором вместо нормального конфигурационного файла использовался большой .env-файл с самыми разными настройками. Да, подход так себе, но в принципе жить можно. К сожалению, среди переменных окружения были такие, где указывались многострочные значения. Не спрашивайте, зачем в переменные окружения вставлять куски YAML вместо того, чтобы использовать обычный YAML-конфиг. Так исторически сложилось, и ничего с этим не поделать.
К сожалению, расширение Go для VSCode не умеет работать с многострочными значениями переменных окружения. Но мы же программисты, а значит, сможем всё нагуглить.
Первое, на что мы наткнёмся, — это открытый ишью в репозитории расширения: "Use dotenv for reading env files". Автор предлагает использовать JavaScript-библиотеку dotenv для парсинга переменных окружения и приводит примеры того, как это реализовано в расширениях для JavaScript и Java. Решение занимает всего несколько строк кода:

Ишью открыт уже больше года, и до сих пор ничего не сделано. Автору предложили не использовать библиотеку dotenv, поскольку она не сохраняет порядок следования переменных. Вместо этого можно переписать текущую реализацию, используя код из dotenv, но с сохранением порядка.
Для нас это значит, что готового решения проблемы нет и нужно засучить рукава. Будем делать свою версию плагина с блэкджеком и dotenv. Для начала клонируем проект локально. После этого находим код, который нужно поправить. Вся магия происходит в методе parseEnvFile() здесь, в файле extension/src/utils/envUtils.ts:
export function parseEnvFile(envFilePath: string, globalVars?: NodeJS.Dict<string>): { [key: string]: string } {
const env: { [key: string]: string } = {};
if (!envFilePath) {
return env;
}
if (!globalVars) {
globalVars = {};
}
try {
const buffer = stripBOM(fs.readFileSync(envFilePath, 'utf8'));
buffer.split('\n').forEach((line) => {
const r = line.match(/^\s*(export\s+)?([\w\.\-]+)\s*=\s*(.*)?\s*$/);
if (r !== null) {
let value = r[3] || '';
if (value.length > 0 && value.charAt(0) === '"' && value.charAt(value.length - 1) === '"') {
value = value.replace(/\\n/gm, '\n');
}
const v = value.replace(/(^['"]|['"]$)/g, '');
env[r[2]] = substituteEnvVars(v, env, globalVars!);
}
});
return env;
} catch (e) {
throw new Error(`Cannot load environment variables from file ${envFilePath}: ${e}`);
}
}
Для начала добавим библиотеку dotenv в проект:
cd extension
npm ci
npm install dotenv
Теперь можно переписать парсинг переменных окружения:
import * as dotenv from 'dotenv';
// ...
export function parseEnvFile(envFilePath: string, globalVars?: NodeJS.Dict<string>): { [key: string]: string } {
const env: { [key: string]: string } = {};
if (!envFilePath) {
return env;
}
if (!globalVars) {
globalVars = {};
}
try {
const buffer = stripBOM(fs.readFileSync(envFilePath, 'utf8'));
const parsedEnv = dotenv.parse(Buffer.from(buffer));
return parsedEnv;
} catch (e) {
throw new Error(`Cannot load environment variables from file ${envFilePath}: ${e}`);
}
}
Как видите, всё максимально просто. Теперь нужно собрать наш плагин и установить его. Для сборки запускаем:
npm install -g vsce
cd vscode-go/extension
npm ci
vsce package
Эта команда сгенерирует расширение для VSCode в виде файла go-0.52.0-dev.vsix. Теперь нужно удалить старое расширение и установить его заново с помощью только что созданного файла. Чтобы установить расширение из файла, откройте панель команд (Ctrl+Shift+P или Cmd+Shift+P) и выберите команду Extensions: Install from VSIX. Укажите нужный файл и наслаждайтесь результатом.
Ссылки
- Как контрибьютить в расширение vscode-go
- Ишью "Use dotenv for reading env files"
- Ссылка на расширение в сторе