39

Can I retrieve the current operating system (Windows, Linux, OS X, ..) using pure Vimscript (no Python or Perl)?

I want to enable different settings in my (synchronized) .vimrc for different types of operation systems I am using.

  • Could you provide some specific examples of OS-dependent behaviours that you seek to implement? – 200_success Mar 16 '15 at 8:47
  • @200_success I have some scripts and key bindings for MS TFS and msbuild that are pretty useless in non-Windows environments, while I don't need tmux support in gVim on Windows. In addition, there are different fonts installed on different systems, and paths may differ as well. – muffel Mar 16 '15 at 8:52
43

The best way is to use has(), with this function you can check for features of Vim; OS specific features from :help feature-list:

macunix                 Macintosh version of Vim, using Unix files (OS-X).
unix                    Unix version of Vim.
win32                   Win32 version of Vim (MS-Windows 95 and later, 32 or
                        64 bits)
win32unix               Win32 version of Vim, using Unix files (Cygwin)

And some older (semi-deprecated) systems:

amiga                   Amiga version of Vim.
os2                     OS/2 version of Vim.
win16                   Win16 version of Vim (MS-Windows 3.1).
win64                   Win64 version of Vim (MS-Windows 64 bit).
win95                   Win32 version for MS-Windows 95/98/ME.

Example:

if has('win32')
    echo "Someone please open the Window(s)!"
endif

An alternative way with more flexibility is to call the external uname, this also allows you to get the version number and such:

let uname = system('uname -a')

Note that uname isn't present on most Windows systems.

It's generally best to use feature detection, rather than OS detection. For example by using one of the features in has() or checking if some path exists. 200_success' post gives a good overview of that, so I'll not repeat the same content here.

  • 5
    Very important to note romainl's answer if you want it to work on OS X, though. – Rich Mar 16 '15 at 10:33
  • +1 for pointer to :h feature-list – JESii Jun 4 '17 at 19:18
24

has() sounds like a good idea until you try it on Mac OS X: in the default /usr/bin/vim, has('unix') is true but both has('macunix') and has('mac') are false while, in the regular MacVim download, all three are true whether you use the GUI or the TUI.

So the best solution is a mix of has('winXX') for Windows and uname on unix-like systems. Note that the output of uname ends with a newline so it must be cleaned before use.

Here is the code I've been using for a while, updated for win64:

if !exists("g:os")
    if has("win64") || has("win32") || has("win16")
        let g:os = "Windows"
    else
        let g:os = substitute(system('uname'), '\n', '', '')
    endif
endif

After that, you can use the g:os variable anywhere in your vimrc:

if has("gui_running")
    if g:os == "Darwin"
        set guifont=Fira\ Mono:h12
    elseif g:os == "Linux"
        set guifont=Fira\ Mono\ 10
    elseif g:os == "Windows"
        set guifont=Fira_Mono:h12:cANSI
    endif
endif
  • Well, OSX is a UNIX system, I believe it's even "certified UNIX". So has('unix') is accurate. It's odd that has('macunix') is false, though. This almost sounds like a bug? – Martin Tournoij Mar 16 '15 at 10:48
  • 1
    I did some checking, and has('macunix') seems to depend on MACOS_X_UNIX, which is set if uname is Darwin in the configure script... – Martin Tournoij Mar 16 '15 at 10:56
  • Oddly enough, has ("win32") seems to work for me even in 64-bit Vim. – Rich Mar 16 '15 at 14:29
  • @Rich Yes, and that's documented as such. This is really the sane thing to do, do you care if your app is 32 or 64 bits? I don't. The reason it's called 'win32', is because that's the name Microsoft choose for their Windows NT API. Naming things isn't Microsoft's strong point. – Martin Tournoij Mar 16 '15 at 16:55
  • 1
    has('unix') is also true on Windows Git Bash, so it's not very useful for distinguishing real unix from emulated. – wisbucky Jun 5 '18 at 9:45
8

Environment variables would be useful.

To detect tmux, you could check if !empty($TMUX) or if $TERM == 'screen'.

You can also deduce the operating system from environment variables such as $MACHTYPE (which is set by Bash) or $PATH.

To detect whether a feature such as TFS is installed, you can use the executable() function.

  • "$MACHTYPE (which is set by Bash)". Actually, if a variable is set by Bash, that means it is not an environment variable, and you will not be able to access it in vim simply with $MACHTYPE. You will have to do something like let machtype=system('echo -n $MACHTYPE') first. – wisbucky Jun 6 '18 at 0:02
4

As others have already indicated, a reliable detection can be tricky. Better not reinvent the wheel, so I'd like to mention the vim-misc library, which provides xolox#misc#os#is_mac() and xolox#misc#os#is_win() functions.

2

I tried has('unix'), but I didn't find it helpful since all my Linux, Mac, and Windows Git Bash returned true for it.

I found uname to be suitable as it distinguishes between Linux, Mac, Windows, without too much granularity.

let uname = substitute(system('uname'), '\n', '', '')
" Example values: Linux, Darwin, MINGW64_NT-10.0, MINGW32_NT-6.1

if uname == 'Linux' || uname == 'Darwin'
    " do linux/mac command
else " windows
    " do windows command
endif

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.