rozsazoltan
rozsazoltan

Reputation: 8835

Opening a file located on WSL with VSCode from the command line

I want to open the file I'm editing from a Vite instance running on WSL using the code command. For this, Vite passes the Linux-compatible path and the -r flag to the code command, but it ends up opening the file in Windows (and not Remote WSL), which fails to load the file properly due to incompatibilities between the systems, although it can find the filename based on the path.

code -r -g /path/to/file.vue

The goal is for VSCode to open the invoked file correctly in the appropriate WSL environment (if multiple WSL distributions are installed), using the Remote WSL extension.

I have no control over the invoked command, as I want to open it through either the vite-plugin-vue-devtools or vite-plugin-vue-inspector.

VSCode is not found on the WSL Linux system itself; it is only present on the Windows system, and it can manage the workspaces on the WSL file system using the Remote WSL extension.

Upvotes: 0

Views: 71

Answers (2)

Pablo Castellazzi
Pablo Castellazzi

Reputation: 4209

Let's assume ~/bin exists and it is in your PATH, or any other location of your choosing where binaries are stored, like /usr/local/bin.

On Windows, on a PowerShell command prompt run: Get-Command code | Select-Object Source. This will output the location of the code binary on your system. Something along the lines of C:\Users\<YOUR USER>\AppData\Local\Programs\Microsoft VS Code\bin\code.cmd. Note it is a CMD script, this will be important later.

Now on the WSL instance of your choice you can run: ln -s "$(wslpath -a 'C:\Users\<YOUR USER>\AppData\Local\Programs\Microsoft VS Code\bin\code')" ~/bin/code. Pay close attention to the file name, .cmd was intentionally removed.

code is now a "native" command on your WSL distribution. The conversion between UNC and Posix paths is handled automatically by WSL.

Behind the scenes WSL is using binfmt_misc to run the commands with a custom interpreter that handles interoperability.

You can learn more about this feature at Run Windows Tools From Linux

Upvotes: 1

rozsazoltan
rozsazoltan

Reputation: 8835

If I don't use the Windows environment variables on the WSL system and instead create my own code command, I have the ability to modify the attributes before invoking the actual Windows-based code command via PowerShell.

In my custom code command placed in /usr/local/bin/, I first manipulate the arguments, and secondly, pass them to the Windows-based code command via PowerShell.

# /usr/local/bin/code

distroName=$WSL_DISTRO_NAME
args=()
remoteAdded=false

# Modify arguments to add correctly --remote flag when detect Linux-based path
for arg in "$@"; do
  if [[ $arg =~ ^/ ]]; then
    # Add --remote and the Linux path
    args+=("--remote \"wsl+$distroName\"" "$arg")
    remoteAdded=true
  else
    args+=("$arg")
  fi
done

# Remove -r if --remote was added
if $remoteAdded; then
  args=("$(echo ${args[@]} | sed 's|^-r ||; s| -r$||; s| -r ||g')")
fi

# Invoke VSCode through PowerShell from Windows
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe "& {code ${args[@]}}"

Thus, when you invoke the

code -r -g /path/to/file.vue

command from a helper tool on Linux, the code file is transformed and forwarded to Windows, where it is opened with code.exe:

code --remote "wsl+DISTRO_NAME" -g /path/to/file.vue

After this, only a warning message will appear from PowerShell/VSCode for us:

CMD.EXE was started with the above path as the current directory.
UNC paths are not supported. Defaulting to Windows directory.

To hide it, we can simply disable the output of PowerShell's response (only in the case of $remoteAdded, because otherwise, with the code command, you can query things like --list-extensions, which is something that should work).

# Invoke VSCode through PowerShell from Windows
if $remoteAdded; then
  echo -e " > $(tput setaf 222)$(tput setab 0)Opening file:$(tput sgr0) $fileToOpen"
  # Don't need result message (disable warning: UNC paths are not supported)
  /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe "& {code ${args[@]} > \$null 2>&1}"
else
  /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe "& {code ${args[@]}}"
fi

Upvotes: 0

Related Questions