Well, I was hoping to feel better about the ethics of doing it before sharing the method, but…
First, let me say, it isn’t the best solution in the world, and it kind of hurts the intentions of Nix and IDX and creates headaches, and could easily break. And I wouldn’t use this in large scale production.
But here is how I’m doing it:
The following is a small bash script that, when given the argument of a package ID, including publisher, such as ms-python.vscode-pylance
, will fetch the latest verison’s .vsix from Microsoft’s VS Marketplace CDN, and install it:
msget.sh
#!/bin/bash
# Check if an extension ID is provided as an argument
if [ -z "$1" ]; then
echo "Usage: $0 <extension_id>"
exit 1
fi
extension_id="$1"
# Extract the publisher name and extension name from the ID
publisher=$(echo "$extension_id" | cut -d'.' -f1)
package=$(echo "$extension_id" | cut -d'.' -f2)
# Create the msget directory if it doesn't exist
msget_dir="msget"
mkdir -p "$msget_dir"
# Create the vsix subdirectory if it doesn't exist
vsix_dir="$msget_dir/vsix"
mkdir -p "$vsix_dir"
# Construct the download URL using the new format
download_url="https://${publisher}.gallery.vsassets.io/_apis/public/gallery/publisher/${publisher}/extension/${package}/latest/assetbyname/Microsoft.VisualStudio.Services.VSIXPackage"
# Construct the filename with the extension ID
vsix_filename="${extension_id}.vsix"
vsix_filepath="$vsix_dir/$vsix_filename"
# Download the VSIX file using the constructed URL, overwriting if it exists
curl -L -o "$vsix_filepath" "$download_url"
echo "Downloaded $vsix_filepath"
# Install the VSIX using the 'code' command
code --install-extension "$vsix_filepath"
echo "Installed $extension_name extension"
I save this script at ./msget/msget.sh
.
Then, in your ./.idx/dev.nix
file, you need to:
First, add pkgs.curl
, if you don’t already have it.
Then, you need to add to onCreate
/onStart
something akin to the following:
onCreate = {
msget_executable = ''chmod +x ./msget/msget.sh'';
msget_pylance = ''./msget/msget.sh ms-python.vscode-pylance'';
msget_colorize = ''./msget/msget.sh kamikillerto.vscode-colorize'';
};
onStart = {
msget_executable = ''chmod +x ./msget/msget.sh'';
msget_pylance = ''./msget/msget.sh ms-python.vscode-pylance'';
msget_colorize = ''./msget/msget.sh kamikillerto.vscode-colorize'';
};
I prefer to put these commands in both onCreate
and onStart
, so that it installs them when creating a workspace, and then updates them every time I rebuild the environment. You could add in checks so it isn’t so wasteful and all that, but I was lazy at that point.
So what we are doing in those commands there, first we make our script executable, then we simply pass a package ID as an argument to the script for each Extension we want to add.
It’s very nice to have this option, IMO, but it seems like really bad form if you’re doing anything professional here, just FYI.
I hope that helps and you guys enjoy it!