feat(cursor/setup): add support for vscode in setup script

This commit is contained in:
2025-02-23 21:58:08 +00:00
parent 1ef2937eb4
commit b6c291c44c
3 changed files with 270 additions and 97 deletions

View File

@@ -1,5 +1,5 @@
# Cursor Extensions
# Generated on Sun Feb 23 16:35:53 GMT 2025
# Generated on Sun Feb 23 21:53:44 GMT 2025
alefragnani.project-manager@12.8.0
antiantisepticeye.vscode-color-picker@0.0.4
@@ -10,8 +10,10 @@ bodil.file-browser@0.2.11
bufbuild.vscode-buf@0.7.0
carlos-algms.make-task-provider@2.5.1
christian-kohler.path-intellisense@2.10.0
connor4312.esbuild-problem-matchers@0.0.3
connorshea.vscode-ruby-test-adapter@0.9.2
ctf0.macros@1.1.1
dbaeumer.vscode-eslint@3.0.10
dnut.rewrap-revived@1.16.3
emeraldwalk.runonsave@0.2.7
exiasr.hadolint@1.1.2
@@ -26,9 +28,11 @@ gruntfuggly.todo-tree@0.0.226
hashicorp.terraform@2.34.3
hbenl.vscode-test-explorer@2.22.1
humao.rest-client@0.25.1
joshbolduc.commitlint@2.6.0
kahole.magit@0.6.66
karunamurti.haml@1.4.1
m4ns0ur.base64@1.0.0
mattn.lisp@0.1.12
mhutchie.git-graph@1.30.0
ms-azuretools.vscode-docker@1.29.4
ms-python.debugpy@2024.6.0
@@ -37,6 +41,7 @@ ms-python.vscode-pylance@2024.8.1
ms-vscode-remote.remote-containers@0.394.0
ms-vscode-remote.remote-ssh@0.113.1
ms-vscode-remote.remote-ssh-edit@0.87.0
ms-vscode.extension-test-runner@0.0.12
ms-vscode.hexeditor@1.11.1
ms-vscode.remote-explorer@0.4.3
ms-vscode.remote-repositories@0.42.0
@@ -44,7 +49,7 @@ ms-vscode.remote-server@1.5.2
ms-vscode.test-adapter-converter@0.2.1
ms-vscode.vscode-speech@0.12.1
ms-vsliveshare.vsliveshare@1.0.5948
ninoseki.vscode-gem-lens@0.4.3
ninoseki.vscode-mogami@0.0.42
pflannery.vscode-versionlens@1.16.2
pkief.material-icon-theme@5.19.0
redhat.vscode-xml@0.27.2

View File

@@ -0,0 +1,73 @@
# Vscode-insiders Extensions
# Generated on Sun Feb 23 21:54:30 GMT 2025
alefragnani.project-manager@12.8.0
antiantisepticeye.vscode-color-picker@0.0.4
antyos.openscad@1.3.2
arahata.linter-actionlint@0.1.0
bibhasdn.unique-lines@1.0.0
bodil.file-browser@0.2.11
bufbuild.vscode-buf@0.7.0
carlos-algms.make-task-provider@2.5.1
christian-kohler.path-intellisense@2.10.0
connor4312.esbuild-problem-matchers@0.0.3
connorshea.vscode-ruby-test-adapter@0.9.2
ctf0.macros@1.1.1
dbaeumer.vscode-eslint@3.0.10
dnut.rewrap-revived@1.16.3
emeraldwalk.runonsave@0.2.7
exiasr.hadolint@1.1.2
fnando.linter@0.0.19
foxundermoon.shell-format@7.2.5
github.codespaces@1.17.3
github.copilot@1.273.1390
github.copilot-chat@0.25.2025022101
github.github-vscode-theme@6.3.5
github.remotehub@0.64.0
github.vscode-github-actions@0.27.1
github.vscode-pull-request-github@0.104.1
gofenix.go-lines@0.0.10
golang.go@0.44.0
gruntfuggly.todo-tree@0.0.226
hashicorp.terraform@2.34.3
hbenl.vscode-test-explorer@2.22.1
humao.rest-client@0.25.1
joshbolduc.commitlint@2.6.0
kahole.magit@0.6.66
karunamurti.haml@1.4.1
m4ns0ur.base64@1.0.0
mattn.lisp@0.1.12
mhutchie.git-graph@1.30.0
ms-azuretools.vscode-docker@1.29.4
ms-python.debugpy@2025.0.1
ms-python.python@2025.0.0
ms-python.vscode-pylance@2025.2.1
ms-vscode-remote.remote-containers@0.398.0
ms-vscode-remote.remote-ssh@0.117.1
ms-vscode-remote.remote-ssh-edit@0.87.0
ms-vscode.extension-test-runner@0.0.12
ms-vscode.hexeditor@1.11.1
ms-vscode.remote-explorer@0.4.3
ms-vscode.remote-repositories@0.42.0
ms-vscode.remote-server@1.5.2
ms-vscode.test-adapter-converter@0.2.1
ms-vscode.vscode-speech@0.12.1
ms-vsliveshare.vsliveshare@1.0.5948
ninoseki.vscode-mogami@0.0.42
pflannery.vscode-versionlens@1.16.2
pkief.material-icon-theme@5.19.0
redhat.vscode-xml@0.27.2
redhat.vscode-yaml@1.16.0
rrudi.vscode-dired@0.0.9
rust-lang.rust-analyzer@0.3.2308
shopify.ruby-extensions-pack@0.1.12
shopify.ruby-lsp@0.9.6
sorbet.sorbet-vscode-extension@0.3.37
sumneko.lua@3.13.6
swellaby.vscode-rust-test-adapter@0.11.0
tamasfe.even-better-toml@0.21.2
tuttieee.emacs-mcx@0.65.1
viktorzetterstrom.non-breaking-space-highlighter@0.0.3
wenhoujx.swiper@2.1.2
zhuangtongfa.material-theme@3.19.0
zxh404.vscode-proto3@0.5.5

View File

@@ -4,6 +4,9 @@
# Settings
# ==============================================================================
# Default editor to configure (cursor, vscode, or vscode-insiders)
SETUP_EDITOR="cursor"
# List of config files to symlink from current directory.
CONFIG_SOURCES=(
"settings.json"
@@ -14,8 +17,10 @@ CONFIG_SOURCES=(
# Detect current script directory.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Extensions lockfile path
EXTENSIONS_LOCK="${SCRIPT_DIR}/extensions.lock"
# Get extensions lockfile path for current editor
get_extensions_lock() {
echo "${SCRIPT_DIR}/extensions.${SETUP_EDITOR}.lock"
}
# ==============================================================================
# Help
@@ -23,15 +28,20 @@ EXTENSIONS_LOCK="${SCRIPT_DIR}/extensions.lock"
show_help() {
cat <<EOF
Usage: $(basename "$0") COMMAND
Usage: $(basename "$0") EDITOR COMMAND
Editors:
cursor Cursor editor
vscode Visual Studio Code
vscode-insiders Visual Studio Code Insiders
Commands:
config, conf Create symlinks for Cursor config files
dump-extensions, dump Export installed Cursor extensions to extensions.txt
extensions, ext Install Cursor extensions from extensions.txt
config, conf Create symlinks for editor config files
dump-extensions, dump Export installed editor extensions to extensions.txt
extensions, ext Install editor extensions from extensions.txt
Description:
This script manages Cursor editor configuration files and extensions.
This script manages editor configuration files and extensions.
It can create symlinks for settings, keybindings, and snippets,
as well as backup and restore extensions.
EOF
@@ -41,14 +51,42 @@ EOF
# Functions
# ==============================================================================
# Determine Cursor config directory.
cursor_config_dir() {
# Determine editor config directory
editor_config_dir() {
case "$(uname -s)" in
"Darwin")
echo "${HOME}/Library/Application Support/Cursor/User"
case "${SETUP_EDITOR}" in
"cursor")
echo "${HOME}/Library/Application Support/Cursor/User"
;;
"vscode")
echo "${HOME}/Library/Application Support/Code/User"
;;
"vscode-insiders")
echo "${HOME}/Library/Application Support/Code - Insiders/User"
;;
*)
echo "Error: Invalid editor '${SETUP_EDITOR}' for macOS"
exit 1
;;
esac
;;
"Linux")
echo "${HOME}/.config/Cursor/User"
case "${SETUP_EDITOR}" in
"cursor")
echo "${HOME}/.config/Cursor/User"
;;
"vscode")
echo "${HOME}/.config/Code/User"
;;
"vscode-insiders")
echo "${HOME}/.config/Code - Insiders/User"
;;
*)
echo "Error: Invalid editor '${SETUP_EDITOR}' for Linux"
exit 1
;;
esac
;;
*)
echo "Error: Unsupported operating system"
@@ -87,9 +125,9 @@ backup_and_link() {
# Create symlinks
do_symlink() {
# Create Cursor config directory if it doesn't exist
# Create editor config directory if it doesn't exist
local config_dir
config_dir="$(cursor_config_dir)"
config_dir="$(editor_config_dir)"
mkdir -p "${config_dir}"
for path in "${CONFIG_SOURCES[@]}"; do
@@ -99,116 +137,98 @@ do_symlink() {
echo "Symlink setup complete!"
}
# Find the cursor CLI command
find_cursor_cmd() {
local cursor_cmd=""
# Find the editor CLI command
find_editor_cmd() {
local editor_cmd=""
# Check for cursor CLI in multiple possible locations
for cmd in "cursor" "/Applications/Cursor.app/Contents/Resources/app/bin/cursor" "${HOME}/Applications/Cursor.app/Contents/Resources/app/bin/cursor"; do
if command -v "${cmd}" >/dev/null 2>&1; then
cursor_cmd="${cmd}"
break
fi
done
case "${SETUP_EDITOR}" in
"cursor")
# Check for cursor CLI in multiple possible locations
for cmd in "cursor" "/Applications/Cursor.app/Contents/Resources/app/bin/cursor" "${HOME}/Applications/Cursor.app/Contents/Resources/app/bin/cursor"; do
if command -v "${cmd}" >/dev/null 2>&1; then
editor_cmd="${cmd}"
break
fi
done
;;
"vscode")
# Check for VSCode CLI in multiple possible locations
for cmd in "code" "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code" "${HOME}/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code"; do
if command -v "${cmd}" >/dev/null 2>&1; then
editor_cmd="${cmd}"
break
fi
done
;;
"vscode-insiders")
# Check for VSCode Insiders CLI in multiple possible locations
for cmd in "code-insiders" "/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code" "${HOME}/Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/bin/code"; do
if command -v "${cmd}" >/dev/null 2>&1; then
editor_cmd="${cmd}"
break
fi
done
;;
*)
echo "Error: Invalid editor '${SETUP_EDITOR}'"
exit 1
;;
esac
if [[ -z "${cursor_cmd}" ]]; then
echo "Error: cursor command not found" >&2
if [[ -z "${editor_cmd}" ]]; then
echo "Error: ${SETUP_EDITOR} command not found" >&2
exit 1
fi
echo "${cursor_cmd}"
echo "${editor_cmd}"
}
# Dump installed extensions to extensions.lock
do_dump_extensions() {
local cursor_cmd
cursor_cmd="$(find_cursor_cmd)"
local editor_cmd
editor_cmd="$(find_editor_cmd)"
local current_date
current_date="$(date)"
local extensions_lock
extensions_lock="$(get_extensions_lock)"
{
echo "# Cursor Extensions"
echo "# ${SETUP_EDITOR^} Extensions"
echo "# Generated on ${current_date}"
echo
"${cursor_cmd}" --list-extensions --show-versions
} >"${EXTENSIONS_LOCK}"
"${editor_cmd}" --list-extensions --show-versions
} >"${extensions_lock}"
echo "Extensions list dumped to ${EXTENSIONS_LOCK}"
echo "Extensions list dumped to ${extensions_lock}"
}
# Global variable to cache installed extensions
_INSTALLED_EXTENSIONS=""
# Check if extension is already installed with exact version
# Check if extension is already installed, ignoring version
is_extension_installed() {
local cursor_cmd="$1"
local editor_cmd="$1"
local extension="$2"
local version="$3"
# Build cache if not already built
if [[ -z "${_INSTALLED_EXTENSIONS}" ]]; then
_INSTALLED_EXTENSIONS="$("${cursor_cmd}" --list-extensions --show-versions)"
_INSTALLED_EXTENSIONS="$("${editor_cmd}" --list-extensions --show-versions)"
fi
# Check if extension@version exists in cached list
echo "${_INSTALLED_EXTENSIONS}" | grep -q "^${extension}@${version}$"
}
# Download and install a single extension.
#
# This is needed for cursor right now as installing an extension based on its
# ID yields a signature error. But installing from a .vsix file works fine.
download_and_install_extension() {
local cursor_cmd="$1"
local extension="$2"
local version="$3"
local extensions_dir="$4"
# Check if already installed with correct version
if is_extension_installed "${cursor_cmd}" "${extension}" "${version}"; then
echo "Extension ${extension}@${version} is already installed, skipping"
return 0
fi
local vsix_path="${extensions_dir}/${extension}@${version}.vsix"
# Create extensions directory if it doesn't exist
mkdir -p "${extensions_dir}"
# If .vsix doesn't exist, download it
if [[ ! -f "${vsix_path}" ]]; then
local publisher_id="${extension%%.*}"
local extension_id="${extension#*.}"
local vsix_url="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher_id}/vsextensions/${extension_id}/${version}/vspackage"
echo "Downloading ${extension}@${version}.vsix..."
echo " - URL: ${vsix_url}"
if ! curl --compressed -L -o "${vsix_path}" "${vsix_url}"; then
echo "Failed to download ${extension}@${version}.vsix"
return 1
fi
fi
# Install the extension from .vsix file
echo "Installing extension from ${vsix_path}"
if ! "${cursor_cmd}" --install-extension "${vsix_path}"; then
echo "Failed to install ${extension}@${version}"
return 1
fi
# Clean up the .vsix file after successful installation
rm "${vsix_path}"
return 0
# Check if extension exists in cached list
echo "${_INSTALLED_EXTENSIONS}" | grep -q "^${extension}@"
}
# Install extensions from extensions.lock
do_install_extensions() {
local cursor_cmd
cursor_cmd="$(find_cursor_cmd)"
local extensions_dir="${SCRIPT_DIR}/cache/extensions"
local editor_cmd
editor_cmd="$(find_editor_cmd)"
local extensions_cache_dir="${SCRIPT_DIR}/cache/extensions"
local extensions_lock
extensions_lock="$(get_extensions_lock)"
if [[ ! -f "${EXTENSIONS_LOCK}" ]]; then
echo "Error: ${EXTENSIONS_LOCK} not found"
if [[ ! -f "${extensions_lock}" ]]; then
echo "Error: ${extensions_lock} not found"
exit 1
fi
@@ -218,14 +238,54 @@ do_install_extensions() {
extension="${line%@*}"
version="${line#*@}"
if ! download_and_install_extension "${cursor_cmd}" "${extension}" "${version}" "${extensions_dir}"; then
# Check if already installed with correct version
if is_extension_installed "${editor_cmd}" "${extension}"; then
echo "Extension ${extension} is already installed, skipping"
continue
fi
# For VSCode and VSCode Insiders we can install directly from the marketplace
if [[ "${SETUP_EDITOR}" == "vscode" || "${SETUP_EDITOR}" == "vscode-insiders" ]]; then
echo "Installing ${extension}@${version}"
if ! "${editor_cmd}" --install-extension "${extension}@${version}"; then
echo "Warning: Failed to install ${extension}@${version}"
fi
continue
fi
# For Cursor we need to download and install from .vsix file
local vsix_path="${extensions_cache_dir}/${extension}@${version}.vsix"
# Create extensions directory if it doesn't exist
mkdir -p "${extensions_cache_dir}"
# If .vsix doesn't exist, download it
if [[ ! -f "${vsix_path}" ]]; then
local publisher_id="${extension%%.*}"
local extension_id="${extension#*.}"
local vsix_url="https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher_id}/vsextensions/${extension_id}/${version}/vspackage"
echo "Downloading ${extension}@${version}.vsix..."
echo " - URL: ${vsix_url}"
if ! curl --compressed -L -o "${vsix_path}" "${vsix_url}"; then
echo "Warning: Failed to download ${extension}@${version}.vsix"
continue
fi
fi
# Install the extension from .vsix file
echo "Installing extension from ${vsix_path}"
if ! "${editor_cmd}" --install-extension "${vsix_path}"; then
echo "Warning: Failed to install ${extension}@${version}"
fi
# Clean up the .vsix file after installation attempt
rm "${vsix_path}"
fi
done <"${EXTENSIONS_LOCK}"
done <"${extensions_lock}"
# Clean up extensions directory if empty
rmdir "${extensions_dir}" 2>/dev/null || true
rmdir "${extensions_cache_dir}" 2>/dev/null || true
echo "Extensions installation complete!"
}
@@ -234,7 +294,42 @@ do_install_extensions() {
# ==============================================================================
main() {
case "${1:-}" in
if [[ $# -lt 1 ]]; then
echo "Error: No editor specified"
show_help
exit 1
fi
if [[ $# -lt 2 ]]; then
echo "Error: No command specified"
show_help
exit 1
fi
# Set editor from first argument
editor="$(echo "${1}" | tr '[:upper:]' '[:lower:]')"
case "${editor}" in
"vscode" | "code")
SETUP_EDITOR="vscode"
;;
"vscode-insiders" | "code-insiders" | "insiders")
SETUP_EDITOR="vscode-insiders"
;;
"cursor")
SETUP_EDITOR="cursor"
;;
*)
echo "Error: Unsupported editor '${editor}'"
echo "Supported editors: cursor, vscode, vscode-insiders"
exit 1
;;
esac
# Get command from second argument
local command="${2}"
# Handle commands
case "${command}" in
"config" | "conf")
do_symlink
;;
@@ -250,7 +345,7 @@ main() {
exit 1
;;
*)
echo "Error: Unknown command '$1'"
echo "Error: Unknown command '${command}'"
show_help
exit 1
;;