Look for VSCode variants

We've had requests for this in Homebrew/bundle a few times so let's
implement it both for there and for `brew edit`.

Tested on my machine with `cursor` and working as expected.
This commit is contained in:
Mike McQuaid 2025-03-19 11:42:37 +00:00
parent f8baea29cb
commit d84fac5af4
No known key found for this signature in database
12 changed files with 38 additions and 30 deletions

View File

@ -32,7 +32,14 @@ module Homebrew
end end
def vscode_installed? def vscode_installed?
@vscode_installed ||= which("code").present? @vscode_installed ||= which_vscode.present?
end
def which_vscode
@which_vscode ||= which("code", ORIGINAL_PATHS)
@which_vscode ||= which("codium", ORIGINAL_PATHS)
@which_vscode ||= which("cursor", ORIGINAL_PATHS)
@which_vscode ||= which("code-insiders", ORIGINAL_PATHS)
end end
def whalebrew_installed? def whalebrew_installed?

View File

@ -44,7 +44,7 @@ module Homebrew
Bundle.exchange_uid_if_needed! do Bundle.exchange_uid_if_needed! do
vscode_extensions.each do |extension| vscode_extensions.each do |extension|
Kernel.system "code", "--uninstall-extension", extension Kernel.system(Bundle.which_vscode, "--uninstall-extension", extension)
end end
end end

View File

@ -13,7 +13,7 @@ module Homebrew
def extensions def extensions
@extensions ||= if Bundle.vscode_installed? @extensions ||= if Bundle.vscode_installed?
Bundle.exchange_uid_if_needed! do Bundle.exchange_uid_if_needed! do
`code --list-extensions 2>/dev/null` `"#{Bundle.which_vscode}" --list-extensions 2>/dev/null`
end.split("\n").map(&:downcase) end.split("\n").map(&:downcase)
else else
[] []

View File

@ -33,7 +33,7 @@ module Homebrew
puts "Installing #{name} VSCode extension. It is not currently installed." if verbose puts "Installing #{name} VSCode extension. It is not currently installed." if verbose
return false unless Bundle.exchange_uid_if_needed! do return false unless Bundle.exchange_uid_if_needed! do
Bundle.system("code", "--install-extension", name, verbose:) Bundle.system(Bundle.which_vscode, "--install-extension", name, verbose:)
end end
installed_extensions << name installed_extensions << name

View File

@ -10,7 +10,7 @@ module Homebrew
usage_banner <<~EOS usage_banner <<~EOS
`bundle` [<subcommand>] `bundle` [<subcommand>]
Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code. Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants).
`brew bundle` [`install`]: `brew bundle` [`install`]:
Install and upgrade (by default) all dependencies from the `Brewfile`. Install and upgrade (by default) all dependencies from the `Brewfile`.
@ -105,10 +105,10 @@ module Homebrew
switch "--whalebrew", switch "--whalebrew",
description: "`list` or `dump` Whalebrew dependencies." description: "`list` or `dump` Whalebrew dependencies."
switch "--vscode", switch "--vscode",
description: "`list` or `dump` VSCode extensions." description: "`list` or `dump` VSCode (and forks/variants) extensions."
switch "--no-vscode", switch "--no-vscode",
env: :bundle_dump_no_vscode, env: :bundle_dump_no_vscode,
description: "`dump` without VSCode extensions. " \ description: "`dump` without VSCode (and forks/variants) extensions. " \
"This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set." "This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set."
switch "--describe", switch "--describe",
env: :bundle_dump_describe, env: :bundle_dump_describe,

View File

@ -332,8 +332,8 @@ module Kernel
editor = Homebrew::EnvConfig.editor editor = Homebrew::EnvConfig.editor
return editor if editor return editor if editor
# Find VS Code, Sublime Text, Textmate, BBEdit, or vim # Find VS Code variants, Sublime Text, Textmate, BBEdit, or vim
editor = %w[code subl mate bbedit vim].find do |candidate| editor = %w[code codium cursor code-insiders subl mate bbedit vim].find do |candidate|
candidate if which(candidate, ORIGINAL_PATHS) candidate if which(candidate, ORIGINAL_PATHS)
end end
editor ||= "vim" editor ||= "vim"

View File

@ -186,6 +186,7 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do
context "when there are VSCode extensions to uninstall" do context "when there are VSCode extensions to uninstall" do
before do before do
described_class.reset! described_class.reset!
allow(Homebrew::Bundle).to receive(:which_vscode).and_return(Pathname("code"))
allow(described_class).to receive_messages(casks_to_uninstall: [], allow(described_class).to receive_messages(casks_to_uninstall: [],
formulae_to_uninstall: [], formulae_to_uninstall: [],
taps_to_untap: [], taps_to_untap: [],
@ -193,7 +194,7 @@ RSpec.describe Homebrew::Bundle::Commands::Cleanup do
end end
it "uninstalls extensions" do it "uninstalls extensions" do
expect(Kernel).to receive(:system).with("code", "--uninstall-extension", "GitHub.codespaces") expect(Kernel).to receive(:system).with(Pathname("code"), "--uninstall-extension", "GitHub.codespaces")
expect(described_class).to receive(:system_output_no_stderr).and_return("") expect(described_class).to receive(:system_output_no_stderr).and_return("")
described_class.run(force: true) described_class.run(force: true)
end end

View File

@ -20,7 +20,7 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do
context "when VSCode is installed" do context "when VSCode is installed" do
before do before do
allow(Homebrew::Bundle).to receive(:vscode_installed?).and_return(true) allow(Homebrew::Bundle).to receive(:which_vscode).and_return(Pathname("code"))
end end
context "when extension is installed" do context "when extension is installed" do
@ -45,8 +45,8 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do
end end
it "installs extension" do it "installs extension" do
expect(Homebrew::Bundle).to receive(:system).with("code", "--install-extension", "foo", expect(Homebrew::Bundle).to \
verbose: false).and_return(true) receive(:system).with(Pathname("code"), "--install-extension", "foo", verbose: false).and_return(true)
expect(described_class.preinstall("foo")).to be(true) expect(described_class.preinstall("foo")).to be(true)
expect(described_class.install("foo")).to be(true) expect(described_class.install("foo")).to be(true)
end end
@ -56,8 +56,8 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do
expect(Process::UID).to receive(:re_exchangeable?).and_return(true).once expect(Process::UID).to receive(:re_exchangeable?).and_return(true).once
expect(Process::UID).to receive(:re_exchange).twice expect(Process::UID).to receive(:re_exchange).twice
expect(Homebrew::Bundle).to receive(:system).with("code", "--install-extension", "foo", expect(Homebrew::Bundle).to \
verbose: false).and_return(true) receive(:system).with(Pathname("code"), "--install-extension", "foo", verbose: false).and_return(true)
expect(described_class.preinstall("foo")).to be(true) expect(described_class.preinstall("foo")).to be(true)
expect(described_class.install("foo")).to be(true) expect(described_class.install("foo")).to be(true)
end end
@ -67,8 +67,8 @@ RSpec.describe Homebrew::Bundle::VscodeExtensionInstaller do
expect(Process::UID).to receive(:re_exchangeable?).and_return(false).once expect(Process::UID).to receive(:re_exchangeable?).and_return(false).once
expect(Process::Sys).to receive(:seteuid).twice expect(Process::Sys).to receive(:seteuid).twice
expect(Homebrew::Bundle).to receive(:system).with("code", "--install-extension", "foo", expect(Homebrew::Bundle).to \
verbose: false).and_return(true) receive(:system).with(Pathname("code"), "--install-extension", "foo", verbose: false).and_return(true)
expect(described_class.preinstall("foo")).to be(true) expect(described_class.preinstall("foo")).to be(true)
expect(described_class.install("foo")).to be(true) expect(described_class.install("foo")).to be(true)
end end

View File

@ -493,7 +493,7 @@ __fish_brew_complete_arg 'bump-unversioned-casks' -a '(__fish_brew_suggest_casks
__fish_brew_complete_arg 'bump-unversioned-casks' -a '(__fish_brew_suggest_taps_installed)' __fish_brew_complete_arg 'bump-unversioned-casks' -a '(__fish_brew_suggest_taps_installed)'
__fish_brew_complete_cmd 'bundle' 'Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code' __fish_brew_complete_cmd 'bundle' 'Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants)'
__fish_brew_complete_sub_cmd 'bundle' 'install' __fish_brew_complete_sub_cmd 'bundle' 'install'
__fish_brew_complete_sub_cmd 'bundle' 'dump' __fish_brew_complete_sub_cmd 'bundle' 'dump'
__fish_brew_complete_sub_cmd 'bundle' 'cleanup' __fish_brew_complete_sub_cmd 'bundle' 'cleanup'
@ -517,12 +517,12 @@ __fish_brew_complete_arg 'bundle' -l install -d 'Run `install` before continuing
__fish_brew_complete_arg 'bundle' -l mas -d '`list` or `dump` Mac App Store dependencies' __fish_brew_complete_arg 'bundle' -l mas -d '`list` or `dump` Mac App Store dependencies'
__fish_brew_complete_arg 'bundle' -l no-restart -d '`dump` does not add `restart_service` to formula lines' __fish_brew_complete_arg 'bundle' -l no-restart -d '`dump` does not add `restart_service` to formula lines'
__fish_brew_complete_arg 'bundle' -l no-upgrade -d '`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set' __fish_brew_complete_arg 'bundle' -l no-upgrade -d '`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set'
__fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set' __fish_brew_complete_arg 'bundle' -l no-vscode -d '`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set'
__fish_brew_complete_arg 'bundle' -l quiet -d 'Make some output more quiet' __fish_brew_complete_arg 'bundle' -l quiet -d 'Make some output more quiet'
__fish_brew_complete_arg 'bundle' -l tap -d '`list` or `dump` Homebrew tap dependencies' __fish_brew_complete_arg 'bundle' -l tap -d '`list` or `dump` Homebrew tap dependencies'
__fish_brew_complete_arg 'bundle' -l upgrade -d '`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set. ' __fish_brew_complete_arg 'bundle' -l upgrade -d '`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set. '
__fish_brew_complete_arg 'bundle' -l verbose -d '`install` prints output from commands as they are run. `check` lists all missing dependencies' __fish_brew_complete_arg 'bundle' -l verbose -d '`install` prints output from commands as they are run. `check` lists all missing dependencies'
__fish_brew_complete_arg 'bundle' -l vscode -d '`list` or `dump` VSCode extensions' __fish_brew_complete_arg 'bundle' -l vscode -d '`list` or `dump` VSCode (and forks/variants) extensions'
__fish_brew_complete_arg 'bundle' -l whalebrew -d '`list` or `dump` Whalebrew dependencies' __fish_brew_complete_arg 'bundle' -l whalebrew -d '`list` or `dump` Whalebrew dependencies'
__fish_brew_complete_arg 'bundle' -l zap -d '`cleanup` casks using the `zap` command instead of `uninstall`' __fish_brew_complete_arg 'bundle' -l zap -d '`cleanup` casks using the `zap` command instead of `uninstall`'

View File

@ -149,7 +149,7 @@ __brew_internal_commands() {
'bump-formula-pr:Create a pull request to update formula with a new URL or a new tag' 'bump-formula-pr:Create a pull request to update formula with a new URL or a new tag'
'bump-revision:Create a commit to increment the revision of formula' 'bump-revision:Create a commit to increment the revision of formula'
'bump-unversioned-casks:Check all casks with unversioned URLs in a given tap for updates' 'bump-unversioned-casks:Check all casks with unversioned URLs in a given tap for updates'
'bundle:Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code' 'bundle:Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants)'
'casks:List all locally installable casks including short names' 'casks:List all locally installable casks including short names'
'cat:Display the source of a formula or cask' 'cat:Display the source of a formula or cask'
'cleanup:Remove stale lock files and outdated downloads for all formulae and casks, and remove old versions of installed formulae' 'cleanup:Remove stale lock files and outdated downloads for all formulae and casks, and remove old versions of installed formulae'
@ -659,12 +659,12 @@ _brew_bundle() {
'--mas[`list` or `dump` Mac App Store dependencies]' \ '--mas[`list` or `dump` Mac App Store dependencies]' \
'--no-restart[`dump` does not add `restart_service` to formula lines]' \ '--no-restart[`dump` does not add `restart_service` to formula lines]' \
'--no-upgrade[`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \ '--no-upgrade[`install` does not run `brew upgrade` on outdated dependencies. `check` does not check for outdated dependencies. Note they may still be upgraded by `brew install` if needed. This is enabled by default if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set]' \
'(--all --vscode)--no-vscode[`dump` without VSCode extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \ '(--all --vscode)--no-vscode[`dump` without VSCode (and forks/variants) extensions. This is enabled by default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set]' \
'--quiet[Make some output more quiet]' \ '--quiet[Make some output more quiet]' \
'--tap[`list` or `dump` Homebrew tap dependencies]' \ '--tap[`list` or `dump` Homebrew tap dependencies]' \
'(--install)--upgrade[`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set. ]' \ '(--install)--upgrade[`install` runs `brew upgrade` on outdated dependencies, even if `$HOMEBREW_BUNDLE_NO_UPGRADE` is set. ]' \
'--verbose[`install` prints output from commands as they are run. `check` lists all missing dependencies]' \ '--verbose[`install` prints output from commands as they are run. `check` lists all missing dependencies]' \
'(--no-vscode)--vscode[`list` or `dump` VSCode extensions]' \ '(--no-vscode)--vscode[`list` or `dump` VSCode (and forks/variants) extensions]' \
'--whalebrew[`list` or `dump` Whalebrew dependencies]' \ '--whalebrew[`list` or `dump` Whalebrew dependencies]' \
'--zap[`cleanup` casks using the `zap` command instead of `uninstall`]' \ '--zap[`cleanup` casks using the `zap` command instead of `uninstall`]' \
- subcommand \ - subcommand \

View File

@ -136,7 +136,7 @@ and are now no longer needed.
### `bundle` \[*`subcommand`*\] ### `bundle` \[*`subcommand`*\]
Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store,
Whalebrew and Visual Studio Code. Whalebrew and Visual Studio Code (and forks/variants).
`brew bundle` \[`install`\] `brew bundle` \[`install`\]
@ -288,12 +288,12 @@ flags which will help with finding keg-only dependencies like `openssl`,
`--vscode` `--vscode`
: `list` or `dump` VSCode extensions. : `list` or `dump` VSCode (and forks/variants) extensions.
`--no-vscode` `--no-vscode`
: `dump` without VSCode extensions. This is enabled by default if : `dump` without VSCode (and forks/variants) extensions. This is enabled by
`$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set. default if `$HOMEBREW_BUNDLE_DUMP_NO_VSCODE` is set.
`--describe` `--describe`

View File

@ -83,7 +83,7 @@ Uninstall formulae that were only installed as a dependency of another formula a
\fB\-n\fP, \fB\-\-dry\-run\fP \fB\-n\fP, \fB\-\-dry\-run\fP
List what would be uninstalled, but do not actually uninstall anything\. List what would be uninstalled, but do not actually uninstall anything\.
.SS "\fBbundle\fP \fR[\fIsubcommand\fP]" .SS "\fBbundle\fP \fR[\fIsubcommand\fP]"
Bundler for non\-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code\. Bundler for non\-Ruby dependencies from Homebrew, Homebrew Cask, Mac App Store, Whalebrew and Visual Studio Code (and forks/variants)\.
.TP .TP
\fBbrew bundle\fP [\fBinstall\fP] \fBbrew bundle\fP [\fBinstall\fP]
Install and upgrade (by default) all dependencies from the \fBBrewfile\fP\&\. Install and upgrade (by default) all dependencies from the \fBBrewfile\fP\&\.
@ -178,10 +178,10 @@ Run \fBinstall\fP before continuing to other operations e\.g\. \fBexec\fP\&\.
\fBlist\fP or \fBdump\fP Whalebrew dependencies\. \fBlist\fP or \fBdump\fP Whalebrew dependencies\.
.TP .TP
\fB\-\-vscode\fP \fB\-\-vscode\fP
\fBlist\fP or \fBdump\fP VSCode extensions\. \fBlist\fP or \fBdump\fP VSCode (and forks/variants) extensions\.
.TP .TP
\fB\-\-no\-vscode\fP \fB\-\-no\-vscode\fP
\fBdump\fP without VSCode extensions\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\. \fBdump\fP without VSCode (and forks/variants) extensions\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_NO_VSCODE\fP is set\.
.TP .TP
\fB\-\-describe\fP \fB\-\-describe\fP
\fBdump\fP adds a description comment above each line, unless the dependency does not have a description\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_DESCRIBE\fP is set\. \fBdump\fP adds a description comment above each line, unless the dependency does not have a description\. This is enabled by default if \fB$HOMEBREW_BUNDLE_DUMP_DESCRIBE\fP is set\.