Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 77 additions & 6 deletions lib/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import AerospaceDisplayManager from "./components/settings/aerospace-display-man
export { Component, styles, Wrapper } from "./components/settings/settings.jsx";

const SETTINGS_STORAGE_KEY = "simple-bar-settings";
const originalSubstitutions = {};


// The available themes are retrieved from the Themes collection
// They are then split into dark and light themes
Expand Down Expand Up @@ -1050,14 +1052,13 @@ export async function set(newSettings) {

/**
* Saves the provided settings to the configuration file.
*
* @param {Object} newSettings - The new settings to be saved.
* @returns {Promise<void>} A promise that resolves when the settings have been saved.
* @throws Will throw an error if the settings cannot be saved.
*/
async function saveToConfigFile(newSettings) {
try {
const settings = JSON.stringify(newSettings, undefined, 2);
// Restore original shell substitutions before saving
const settingsToSave = restoreSubstitutions(newSettings);

const settings = JSON.stringify(settingsToSave, undefined, 2);
const cleanSettings = settings.replace(/'/g, "'\"'\"'");
await Uebersicht.run(`echo '${cleanSettings}' | tee ~/.simplebarrc`);
} catch (e) {
Expand All @@ -1066,6 +1067,8 @@ async function saveToConfigFile(newSettings) {
}
}



/**
* Checks if the configuration file for simple-bar exists.
*
Expand Down Expand Up @@ -1103,14 +1106,82 @@ function pruneObsoleteSettings(settings) {
delete settings.widgets.undefined;
}

async function expandPathSubstitution(value, key) {
if (typeof value !== 'string' || value.trim() === '') return value;

if (value.includes('$(')) {
originalSubstitutions[key] = value;

try {
// Build command that sets PATH and evaluates the substitution
const cmd = `PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH" sh -c 'eval "echo ${value}"'`;
const result = await Uebersicht.run(cmd);
const expanded = result.trim();

return expanded || value;
} catch (e) {
// eslint-disable-next-line no-console
console.warn('Failed to expand:', value, e);
return value;
}
}

return value;
}

/**
* Restores shell substitutions before saving to config file.
*/
function restoreSubstitutions(config) {
const restored = JSON.parse(JSON.stringify(config));

for (const [key, originalValue] of Object.entries(originalSubstitutions)) {
const parts = key.split('.');
let obj = restored;

for (let i = 0; i < parts.length - 1; i++) {
if (!obj[parts[i]]) obj[parts[i]] = {};
obj = obj[parts[i]];
}

obj[parts[parts.length - 1]] = originalValue;
}

return restored;
}

/**
* Loads the external configuration file for simple-bar.
*/
export async function loadExternalConfig() {
const configFileExists = await checkIfConfigFileExists();
if (!configFileExists) return;
try {
const config = JSON.parse(await Uebersicht.run(`cat ~/.simplebarrc`));
const rawConfig = await Uebersicht.run(`cat ~/.simplebarrc`);
const config = JSON.parse(rawConfig);

// Expand paths with keys for tracking
if (config.global) {
if (config.global.aerospacePath) {
config.global.aerospacePath = await expandPathSubstitution(
config.global.aerospacePath,
'global.aerospacePath'
);
}
if (config.global.yabaiPath) {
config.global.yabaiPath = await expandPathSubstitution(
config.global.yabaiPath,
'global.yabaiPath'
);
}
if (config.global.flashspacePath) {
config.global.flashspacePath = await expandPathSubstitution(
config.global.flashspacePath,
'global.flashspacePath'
);
}
}

const settings = Utils.mergeDeep(defaultSettings, config);
return settings;
} catch (e) {
Expand Down