4

I would like to identify when Emacs is running on WSL (Windows Subsystem for Linux).
Normally I use system-type variable to check if Emacs is on Linux, Windows or MacOS X.
Though in this case it returns gnu/linux:

system-type is a variable defined in ‘C source code’.
Its value is ‘gnu/linux’

Documentation:
The value is a symbol indicating the type of operating system you are using.
Special values:
  ‘gnu’          compiled for a GNU Hurd system.
  ‘gnu/linux’    compiled for a GNU/Linux system.
  ‘gnu/kfreebsd’ compiled for a GNU system with a FreeBSD kernel.
  ‘darwin’       compiled for Darwin (GNU-Darwin, macOS, ...).
  ‘ms-dos’       compiled as an MS-DOS application.
  ‘windows-nt’   compiled as a native W32 application.
  ‘cygwin’       compiled using the Cygwin library.
Anything else (in Emacs 26, the possibilities are: aix, berkeley-unix,
hpux, usg-unix-v) indicates some sort of Unix system.

Which is what it is expected, though...
I want to add a specific check to use the Windows native browser, not the one on WSL.
I currently do that setting:

(setq browse-url-browser-function 'my-browse-url-function)

But I only want to do this in WSL, not in real Linux.
Is there a way to do it?

nephewtom
  • 2,219
  • 17
  • 29

3 Answers3

4

I just happened to notice this while looking for a an already implemented wsl-browse-url (thanks!), so will offer one other option:

(when (string-match "-[Mm]icrosoft" operating-system-release)
  ;; WSL: WSL1 has "-Microsoft", WSL2 has "-microsoft-standard"
  )

It looks like that works on both my Debian WLinux WSL 2 environments.

Chris Bilson
  • 141
  • 3
  • This one is available without further system calls. Nice! – Tobias Feb 04 '20 at 16:00
  • Where is that `wsl-browse-url` function? I just made my own modifications to open native `chrome.exe` on WSL. which it might have problems in some cases, though I am happy with it. – nephewtom Feb 04 '20 at 18:28
3

I would check for an environment variable using getenv. You may want to check what variables are available in your typical WSL shell, but one option would be to check for a Windows-specific PATH entry, perhaps:

(string-match-p "Windows" (getenv "PATH"))
glucas
  • 20,175
  • 1
  • 51
  • 83
  • https://blogs.msdn.microsoft.com/commandline/2017/12/22/share-environment-vars-between-wsl-and-windows/ would be relevant (found via https://stackoverflow.com/q/43794915 ). – phils Feb 13 '19 at 03:32
3

You could also do (string-match-p "Microsoft" (shell-command-to-string "uname -a"))

Likely in your my-browse-url-function you're probably depending on a Windows specific path to exist. You could just check that it exists and is executable with file-executable-p like the following code does. However, this may not be enough if you dual boot and mount the windows C: drive to the same mount point.

;; setup browser function when running in WSL
(defconst powershell-exe "/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe")

(when (file-executable-p powershell-exe)
  (defun my\wsl-browse-url (url &optional _new-window)
    "Opens link via powershell.exe"
    (interactive (browse-url-interactive-arg "URL: "))
    (let ((quotedUrl (format "start '%s'" url)))
      (apply 'call-process powershell-exe
             nil 0 nil (list "-Command" quotedUrl))))

  (setq-default browse-url-browser-function 'my\wsl-browse-url))
willbush
  • 196
  • 1
  • 4