fish-lsp
Version:
LSP implementation for fish/fish-shell
190 lines (189 loc) • 5.79 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.env = exports.EnvManager = void 0;
const process_env_1 = require("./process-env");
class FishVariableParser {
static parse(value) {
if (!value || value.trim() === '')
return [];
if (value.includes(':') && !value.includes(' ')) {
return this.parsePathVariable(value);
}
return this.parseSpaceSeparatedWithQuotes(value);
}
static parsePathVariable(value) {
return value.split(':').filter(Boolean);
}
static parseSpaceSeparatedWithQuotes(value) {
const result = [];
let currentToken = '';
let inSingleQuote = false;
let inDoubleQuote = false;
let wasEscaped = false;
for (let i = 0; i < value.length; i++) {
const char = value[i];
if (char === '\\' && !wasEscaped) {
wasEscaped = true;
continue;
}
if (char === "'" && !wasEscaped && !inDoubleQuote) {
inSingleQuote = !inSingleQuote;
continue;
}
if (char === '"' && !wasEscaped && !inSingleQuote) {
inDoubleQuote = !inDoubleQuote;
continue;
}
if (char === ' ' && !inSingleQuote && !inDoubleQuote && !wasEscaped) {
if (currentToken) {
result.push(currentToken);
currentToken = '';
}
continue;
}
currentToken += char;
wasEscaped = false;
}
if (currentToken) {
result.push(currentToken);
}
return result;
}
static getAtIndex(array, index) {
if (index < 1)
return undefined;
return array[index - 1];
}
static tokenSeparator(value) {
if (value.includes(':') && !value.includes(' ')) {
return ':';
}
return ' ';
}
}
class EnvManager {
static instance;
envStore = {};
processEnvKeys = new Set(Object.keys(process.env));
autoloadedKeys = new Set(process_env_1.AutoloadedPathVariables.all());
allKeys = new Set();
constructor() {
this.setAllKeys();
Object.assign(this.envStore, process.env);
}
setAllKeys() {
this.allKeys = new Set([
...this.getProcessEnvKeys(),
...this.getAutoloadedKeys(),
]);
}
static getInstance() {
if (!EnvManager.instance) {
EnvManager.instance = new EnvManager();
}
return EnvManager.instance;
}
has(key) {
return this.allKeys.has(key);
}
set(key, value) {
this.allKeys.add(key);
this.envStore[key] = value;
}
get(key) {
return this.envStore[key];
}
getAsArray(key) {
const value = this.envStore[key];
return FishVariableParser.parse(value || '');
}
getFirstValueInArray(key) {
return this.getAsArray(key).at(0);
}
static isArrayValue(value) {
return FishVariableParser.parse(value).length > 1;
}
isArray(key) {
return this.getAsArray(key).length > 1;
}
isAutoloaded(key) {
return this.autoloadedKeys.has(key);
}
isProcessEnv(key) {
return this.processEnvKeys.has(key);
}
append(key, value) {
const existingValue = this.getAsArray(key);
const untokenizedValue = this.get(key);
if (this.isArray(key)) {
const tokenSeparator = FishVariableParser.tokenSeparator(untokenizedValue || '');
existingValue.push(value);
this.envStore[key] = existingValue.join(tokenSeparator);
}
else {
this.envStore[key] = `${untokenizedValue || ''} ${value}`.trim();
}
}
prepend(key, value) {
const existingValue = this.getAsArray(key);
const untokenizedValue = this.get(key);
if (this.isArray(key)) {
const tokenSeparator = FishVariableParser.tokenSeparator(untokenizedValue || '');
existingValue.unshift(value);
this.envStore[key] = existingValue.join(tokenSeparator);
}
else {
this.envStore[key] = `${value} ${untokenizedValue || ''}`.trim();
}
}
get processEnv() {
return process.env;
}
get autoloadedFishVariables() {
const autoloadedFishVariables = {};
process_env_1.AutoloadedPathVariables.all().forEach((variable) => {
autoloadedFishVariables[variable] = this.getAsArray(variable);
});
return autoloadedFishVariables;
}
get keys() {
return Array.from(this.allKeys);
}
getAutoloadedKeys() {
return Array.from(this.autoloadedKeys);
}
getProcessEnvKeys() {
return Array.from(this.processEnvKeys);
}
findAutolaodedKey(key) {
if (key.startsWith('$')) {
key = key.slice(1);
}
return this.getAutoloadedKeys().find((k) => k === key || this.getAsArray(k).includes(key));
}
get values() {
const values = [];
for (const key in this.envStore) {
values.push(this.getAsArray(key));
}
return values;
}
get entries() {
return this.keys.map((key) => {
const value = this.get(key);
return [key, value || ''];
});
}
parser() {
return FishVariableParser;
}
clear() {
for (const key in this.envStore) {
delete this.envStore[key];
}
this.setAllKeys();
Object.assign(this.envStore, process.env);
}
}
exports.EnvManager = EnvManager;
exports.env = EnvManager.getInstance();