Skip to content

Instantly share code, notes, and snippets.

@mattdeboard
Created January 30, 2021 00:31
Show Gist options
  • Save mattdeboard/753662934944d6454a6bbbd7b76045cd to your computer and use it in GitHub Desktop.
Save mattdeboard/753662934944d6454a6bbbd7b76045cd to your computer and use it in GitHub Desktop.
Modify workspace settings dynamically by passing a custom settings fragment when starting VS Code at the command line
#!/usr/bin/env bash
# VS Code does not have workspace settings per user. Or user settings
# per workspace. Either way, I made this script because when I open up
# my Rails repo, I want it to have a different visual theme than my
# TypeScript repo.
# This script creates a workspace file dynamically with modifications
# specified in `custom` variable. When the VS Code process exits, it
# cleans up the temporary file.
# Usage: ./dynamic_workspace.sh <parent workspace file
# to mod> <JSON settings string OR /path/to/settings_changes.json>
# Example usage:
# Say we want to set a custom theme for ourselves in only this workspace.
# Passing a string:
# ./dynamic_workspace.sh myProject.code-workspace '{"settings": {"workbench.colorTheme": "Monokai Dimmed"}}'
# Passing a file:
# ./dynamic_workspace.sh myProject.code-workspace custom-settings.json
# This is a `jq` function to deeply merge two objects
read -r -d '' deepmerge <<-"EOM"
def deepmerge(a;b):
reduce b[] as $item (a;
reduce ($item | keys_unsorted[]) as $key (.;
$item[$key] as $val | ($val | type) as $type | .[$key] = if ($type == "object") then
deepmerge({}; [if .[$key] == null then {} else .[$key] end, $val])
elif ($type == "array") then
(.[$key] + $val | unique)
else
$val
end)
);
deepmerge({}; .)
EOM
# Create a workspace file in the current directory
tmppath=$(pwd)/dyn.code-workspace
# Erase the temp file if it already exists for some reason
if [ -e $tmppath ]; then rm $tmppath; fi
tmpworkspace=$(mktemp $tmppath)
# Generate the new workspace file, with the settings modifications
# data. It will merge the settings mod with the content of the settings
# file that's passed as the first argument to the script.
if [[ -e $2 ]]; then
jq -sM "$deepmerge" "$1" "$2" >$tmpworkspace
else
jq -sM "$deepmerge" "$1" <(echo "$2") >$tmpworkspace
fi
# Run the VS Code process, and tell it to wait.
code -w "$tmpworkspace" &
# Grab the PID of the VS Code process we just started
PID=$!
# While the temporary file still exists, check if the VS Code process is
# still running. If it's not, remove the temp file.
while [[ -e $tmpworkspace ]]; do
if [[ $(ps -p $PID | wc -l) -eq 1 ]]; then
rm $tmpworkspace
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment