In the previous chapter, Setup Strategy Dispatcher, we acted like a General Contractor. We figured out which specialist to hire for the job (e.g., the "JSON Specialist" for VS Code).
Now, we are going to watch that specialist work. We will learn how to safely edit a user's configuration file without breaking their existing settings.
This is Chapter 4: Configuration File Patching.
Imagine you have a notebook where you write down your favorite recipes. You hand it to a friend to add a cookie recipe.
When our tool edits a configuration file (like VS Code's keybindings.json), it must be the Good Friend. We cannot simply overwrite the file; we must patch it.
To ensure we never lose user data, we follow a strict 4-step safety protocol, much like a careful editor revising a manuscript.
Let's walk through how this works in terminalSetup.tsx, focusing on the VS Code implementation (installBindingsForVSCodeTerminal).
First, we need to know where the user keeps their settings. This location is different on every operating system.
// Inside installBindingsForVSCodeTerminal...
const userDirPath = join(
homedir(),
platform() === 'win32'
? join('AppData', 'Roaming', 'Code', 'User') // Windows path
: join('Library', 'Application Support', 'Code', 'User') // Mac path
);
const keybindingsPath = join(userDirPath, 'keybindings.json');
platform() to decide if we look in AppData (Windows) or Library (Mac).Before we even read the file, we create a backup. If our code crashes or bugs out, the user can simply restore this file.
// Generate a random ID for the backup (e.g., .a1b2.bak)
const randomSha = randomBytes(4).toString('hex');
const backupPath = `${keybindingsPath}.${randomSha}.bak`;
try {
// Copy the original file to the backup location
await copyFile(keybindingsPath, backupPath);
} catch {
return 'Error backing up file. Bailing out.';
}
copyFile. If this fails (maybe due to permissions), we stop immediately. We never touch the original file if we can't back it up first.
VS Code uses a format called JSONC (JSON with Comments). Standard JSON parsers choke if they see // comments. We use a special utility to read it safely.
// Read the text from the hard drive
content = await readFile(keybindingsPath, { encoding: 'utf-8' });
// Parse it safely, ignoring comments
// If the file is broken or empty, default to an empty array []
keybindings = safeParseJSONC(content) ?? [];
Now we check if the keybinding exists. If not, we add it.
// Define the new rule we want to add
const newKeybinding = {
key: 'shift+enter',
command: 'workbench.action.terminal.sendSequence',
args: { text: '\u001b\r' }, // The code for a newline
when: 'terminalFocus',
};
// Add to the list and convert back to text
const updatedContent = addItemToJSONCArray(content, newKeybinding);
// Save to disk
await writeFile(keybindingsPath, updatedContent, 'utf-8');
addItemToJSONCArray instead of standard JSON.stringify. This ensures we keep the user's existing comments and formatting intact!Here is the lifecycle of a file patch:
While the example above focused on JSON (for VS Code), our strategy handles other formats too.
For the Alacritty terminal, the settings are stored in a .toml file. The logic in installBindingsForAlacritty is almost identical to VS Code, but the "Injection" step is simpler because TOML allows us to just append text to the end of the file.
// installBindingsForAlacritty
const ALACRITTY_KEYBINDING = `
[[keyboard.bindings]]
key = "Return"
mods = "Shift"
chars = "\\u001B\\r"`;
// ... verify backup ...
// Simply append the string to the end!
updatedContent += '\n' + ALACRITTY_KEYBINDING + '\n';
await writeFile(configPath, updatedContent, 'utf-8');
In this chapter, we learned the importance of being a "Careful Editor."
This approach works perfectly for files that live on the hard drive (like JSON or TOML).
But what if the settings aren't in a file? On macOS, Apple Terminal stores its settings in a system database called a Plist, managed by a background process. You can't just open it with a text editor.
To fix Apple Terminal, we need a different set of tools.
Next Chapter: Apple Terminal Plist Management
Generated by Code IQ