VIM source file on OS condition using interpolation in .vimrc? - vim

I'd like to source files based on my OS platform in my .vimrc configuration file. I'd like to do something like this:
source .vimrc/{uname -S}.vim
I'm doing this because I'd like to source files based on operating system. I know my syntax is wrong, but I think you get the idea. How would I do this? Thank you.

I think OP wants to source the vim file in vim (e.g. vimrc) not in shell. so you could try to add this line in your vimrc:
execute 'source path/to/'. substitute(system('uname -s'), "\n", "", "") . '.vim'

This what I have in my vimrc:
let os=substitute(system('uname'), '\n', '', '')
if os == 'Darwin'
" settings for Mac OS X
elseif os == 'Linux'
" settings for Linux
endif
-- EDIT --
For what it's worth, I've written that snippet a "long" time ago and I can't remember why I added Mac. I initially thought that, maybe, I had found out that uname reported Mac in some context for some reason, but no, it appears to be Darwin everywhere. So I've removed Mac for that snippet to make more sense and will do the same to my vimrc.

Related

Check if using Windows console in Vim while in Windows Subsystem for Linux?

I am using Vim inside the Windows Subsystem for Linux. The windows command prompt has a bug which renders the background color incorrectly.
The fix is set t_ut=. Rather than applying this fix in all situations, I assume it would make sense to only apply it when Vim is being used inside the Windows console.
Unfortunately, I am not sure how to detect whether the Windows console is being used, because I am inside the Windows Subsystem for Linux.
I used the following code that implemented Roadowl's comment.
let uname = substitute(system('uname'),'\n','','')
if uname == 'Linux'
if system('$PATH')=~ '/mnt/c/WINDOWS'
" We are in Windows Subsystem
endif
endif
Update: I combined roadowl's and bk2204's answer:
let uname = substitute(system('uname'),'\n','','')
if uname == 'Linux'
let lines = readfile("/proc/version")
if lines[0] =~ "Microsoft"
return 1
endif
endif
Typically, one addresses issues like this by detecting the terminal type, but it seems Microsoft Terminal reports xterm-256color when it really doesn't support this.
It's possible to detect whether one is running WSL with a function like the following:
function! IsWSL()
if has("unix")
let lines = readfile("/proc/version")
if lines[0] =~ "Microsoft"
return 1
endif
endif
return 0
endfunction
This is consistent with the way that Microsoft suggests that WSL be detected.

vimscript augment rtp with directory above result of system command

I'm trying to modify my vimrc to include a directory
let g:mydir = system('which someExecutable')
execute "set rtp+=" . g:mydir
The problem is that which someExecutable returns something like
/aDir/a/b.
I need g:mydir set to /aDir/, so two dirs above b.
Is there an easy way to do this in vimscript?
You're looking for fnamemodify(path, ":h")
If you version of vim is recent enough, you can even use exepath('someExecutable') instead of system('which someexecutable'). Which gives:
fnamemodify(exepath('someExecutable'), ":h")
PS: don't forget to escape what must be escaped if you use exe "set rtp+=....

Vimscript: How can I get the Operating System version?

Even though it's similar to this and this question I need to know the current version of the operating system while vim is running. The previous questions don't help me since they describe a feature set of the executable; what I need is a function to return the os version either name or number (e.g. as listed in this widows version chart).
Is there one?
I don't know about Windows but on Mac OS X you can do:
$ sw_vers -productVersion
and on Ubuntu you can do:
$ lsb_release -rs
This quick hack seems to work, you'll have to adapt it to your needs:
function! GetSysVersion()
let os=substitute(system('uname'), '\n', '', '')
if os == 'Darwin' || os == 'Mac'
let sys_version=substitute(system('sw_vers -productVersion'), '\n', '', '')
elseif os == 'Linux'
let sys_version=substitute(system('lsb_release -rs'), '\n', '', '')
endif
echo sys_version
endfunction
(Just to make 30 characters)
echo exec('cat "/etc/issue"')
To invoke the Win32 function GetVersionEx(), you have to write a DLL that exposes the function, and invoke it from Vim via libcall(). For all the implementation details, see
:help libcall()
Alternatively, you could write an executable and use system() to parse its output.

Vimscript: how do I get the OS that is running Vim?

I've got vim plugin that runs on different machines and sometimes needs to do things differently depending on whether it's Windows, Linux, Mac.
What's easiest way to test for the operating system? I know I could parse the output of :version command. Is there something simpler that will reveal the OS?
From google:
You can use has() and the list of features under :help feature-list to
determine what type of Vim (and therefore under which OS is running).
if has('win32')
... win32 specific stuff ...
endif
Search for "version of Vim" from the feature-list help topic and that
should bring you to the different versions for which you can check.
In addition to #John's answer here is a full list of possible operating systems:
"▶2 os.fullname
for s:os.fullname in ["unix", "win16", "win32", "win64", "win32unix", "win95",
\ "mac", "macunix", "amiga", "os2", "qnx", "beos", "vms"]
if has(s:os.fullname)
break
endif
let s:os.fullname='unknown'
endfor
"▶2 os.name
if s:os.fullname[-3:] is 'nix' || s:os.fullname[:2] is 'mac' ||
\s:os.fullname is 'qnx' || s:os.fullname is 'vms'
let s:os.name='posix'
elseif s:os.fullname[:2] is 'win'
let s:os.name='nt'
elseif s:os.fullname is 'os2'
let s:os.name='os2'
else
let s:os.name='other'
endif
"▲2
This is the code used by my frawor plugin for determining current operating system.
Due to my love of Python:
python << endpython
import sys
sys.platform
endpython
Also maybe os.name if needed.

Vim with Powershell

I'm using gvim on Windows.
In my _vimrc I've added:
set shell=powershell.exe
set shellcmdflag=-c
set shellpipe=>
set shellredir=>
function! Test()
echo system("dir -name")
endfunction
command! -nargs=0 Test :call Test()
If I execute this function (:Test) I see nonsense characters (non number/letter ASCII characters).
If I use cmd as the shell, it works (without the -name), so the problem seems to be with getting output from powershell into vim.
Interestingly, this works great:
:!dir -name
As does this:
:r !dir -name
UPDATE: confirming behavior mentioned by David
If you execute the set commands mentioned above in the _vimrc, :Test outputs nonsense. However, if you execute them directly in vim instead of in the _vimrc, :Test works as expected.
Also, I've tried using iconv in case it was an encoding problem:
:echo iconv( system("dir -name"), "unicode", &enc )
But this didn't make any difference. I could be using the wrong encoding types though.
Anyone know how to make this work?
It is a bit of a hack, but the following works in Vim 7.2. Notice, I am running Powershell within a CMD session.
if has("win32")
set shell=cmd.exe
set shellcmdflag=/c\ powershell.exe\ -NoLogo\ -NoProfile\ -NonInteractive\ -ExecutionPolicy\ RemoteSigned
set shellpipe=|
set shellredir=>
endif
function! Test()
echo system("dir -name")
endfunction
Tested with the following...
:!dir -name
:call Test()
I ran into a similar problem described by many here.
Specifically, calling
:set shell=powershell
manually from within vim would cause powershell to work fine, but as soon as I added:
set shell=powershell
to my vimrc file I would get the error "Unable to open temp file .... "
The problem is that by default when shell is modified, vim automatically sets shellxquote to " which means that shell commands will look like the following:
powershell -c "cmd > tmpfile"
Where as this command needs to look like this, in order for vim to read the temp file:
powershell -c "cmd" > tmpfile
Setting shellquote to " in my vimrc file and unsetting shellxquote (i.e. setting it to a blank space) seem to fix all my problems:
set shell=powershell
set shellcmdflag=-c
set shellquote=\"
set shellxquote=
I've also tried taking this further and scripting vim a bit using the system() call:
system() with powershell in vim
I suspect that the problem is that Powershell uses the native String encoding for .NET, which is UTF-16 plus a byte-order-mark.
When it's piping objects between commands it's not a problem. It's a total PITA for external programs though.
You can pipe the output through out-file, which does support changing the encoding, but still formats the output for the terminal that it's in by default (arrgh!), so things like "Get-Process" will truncate with ellipses, etc. You can specify the width of the virtual terminal that Out-File uses though.
Not sure how useful this information is, but it does illuminate the problem a bit more.
Try replacing
"dir \*vim\*"
with
" -command { dir \*vim\* }"
EDIT: Try using cmd.exe as the shell and put "powershell.exe" before "-command"
Interesting question - here is something else to add to the confusion. Without making any changes to my .vimrc file, if I then run the following commands in gvim:
:set shell=powershell.exe
:set shellcmdflag=-noprofile
:echo system("dir -name")
It behaves as expected!
If I make the same changes to my .vimrc file, though (the shell and shellcmdflag options), running :echo system("dir -name") returns the nonsense characters!
The initial example code works fine for me when I plop it in vimrc.
So now I'm trying to figure out what in my vimrc is making it function. Possibly:
set encoding=utf8
Edit: Yep, that appears to do it. You probably want to have VIM defaulting to unicode anyway, these days...
None of the answers on this page were working for me until I found this hint from https://github.com/dougireton/mirror_pond/blob/master/vimrc - set shellxquote= [space character] was the missing piece.
if has("win32") || has("gui_win32")
if executable("PowerShell")
" Set PowerShell as the shell for running external ! commands
" http://stackoverflow.com/questions/7605917/system-with-powershell-in-vim
set shell=PowerShell
set shellcmdflag=-ExecutionPolicy\ RemoteSigned\ -Command
set shellquote=\"
" shellxquote must be a literal space character.
set shellxquote=
endif
endif
Combining the answers in this and the related thread, add the following to your $profile assuming you installed diffutils from chocolatey:
Remove-Item Alias:diff -force
And add the following to your ~/.vimrc:
if (has('win32') || has('gui_win32')) && executable('pwsh')
set shell=pwsh
set shellcmdflag=\ -ExecutionPolicy\ RemoteSigned\ -NoProfile\ -Nologo\ -NonInteractive\ -Command
endif
make sure shellcmdflag is exactly as shown
All credit for these solutions to their respective contributors, this is merely an aggregation post.
I propose an hackish solution. It doesn't really solve the problem, but it get the job done somehow.
This Vim plugin automate the creation of a temporary script file, powershell call through cmd.exe and paste of the result. It's not as nice as a proper powershell handling by vim, but it works.
Try instead
set shellcmdflag=\ -c
Explanation:
Vim uses tempname() to generate a temp file path that system() reads.
If &shell contains 'sh' and &shellcmdflag starts with '-'
then tempname() generates a temp file path with forward slashes.
Thus, if
set shell=powershell
set shellcmdflag=-c
then Vim will try to read a temp file with forward slashes that
cannot be found.
A remedy is to set instead
set shellcmdflag=\ -c
that is, add a whitespace to &shellcmdflag so that the first character
is no longer '-' and tempname() produces a temp file path with backward
slashes that can be found by system().
I remarked on the vim_dev mailing list ( https://groups.google.com/forum/#!topic/vim_dev/vTR05EZyfE0 ) that this deserves better documentation.
actf answer works for me, but because of Powershell built in DIFF (which is different from the Linux one) you must add this line to your Powershell profile to have diff working again in VIM:
Remove-Item Alias:diff -force
I'm running GVim v8.2 (Windows).
Using the fullpath to the executable works for me:
set shell=C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe
I don't use VIM but Powershell's default output is Unicode. Notepad can read unicode, you could use it to see if you are getting the output you expect.

Resources