I use VIM on both MacOS and windows, with just one vimrc setting
And here's one of my lightweight key mapping binding:
map <leader>cmd:exec has("mac")==1? ':!open -a terminal' : ':!start cmd'
However, it doesn't work as I thought: press <leader>cmd and without pressing an enter key then cmd or terminal pops out.
What actually happens is the whole mapping string
exec has("mac")==1? ':!open -a terminal' : ':!start cmd' just appears in ex mode and waits for me to press the enter key to run itself.
As I know, if you use exe "your cmd string" in your mapping key setting , you don't need put a <cr> after it, but why when you are using the triple operator, it behaves differently?
So I put into the string, like
map <leader>cmd:exec has("mac")==1? ':!open -a terminal<cr>' : ':!start cmd<cr>'
vim tells me:

(Also, I cannot figure out why <cr>in `` should be escaped, isn't that a string in `` remains the original meaning?)
So I modified as following:
map <leader>cmd:exec has("mac")==1? ':!open -a terminal\<cr\>' : ':!start cmd\<cr\>'
But it just appears in ex mode again.
Any solutions, please?
First, let's clean up your command a little:
:nnoremap <leader>cmd :execute has("mac") ? "!open -a terminal" : "!start cmd"
nnoremap is better than map because it ensures non-recursiveness and it's explicit about the mode it's made for,has(),: are redundant.But none of that will actually fix your problem, namely that you don't have a carriage return at the end of your mapping:
:nnoremap <leader>cmd :execute has("mac") ? "!open -a terminal" : "!start cmd"<CR>
And you still have to press <CR> a second time anyway to get back to Vim so…
:nnoremap <leader>cmd :execute has("mac") ? "!open -a terminal" : "!start cmd"<CR><CR>
Now, here is a pretty clean and generic way to do things differently depending on the platform:
" Define a global variable containing the current environment's name
" if it hasn't been already defined.
if !exists('g:env')
if has('win64') || has('win32') || has('win16')
let g:env = 'WINDOWS'
else
let g:env = toupper(substitute(system('uname'), '\n', '', ''))
endif
endif
and a reworked version of your mapping, with an added path for the open command which you may or may not need depending on your use case:
nnoremap <leader>cmd :execute g:env == "DARWIN" ? "!open -a terminal ." : "!start cmd"<CR><CR>
and an alternative approach, just for the fun of it:
let cmds = { "DARWIN": "!open -a terminal .", "WINDOWS": "!start cmd" }
nnoremap <leader>cmd :execute cmds[g:env]<CR><CR>
In contrast to @romainl's answer, you don't need to dynamically evaluate the operating system during mapping execution (the operating system can hardly change while Vim is running; this is static information). Therefore, it's much easier to define the mappings conditionally:
if has("mac")
nnoremap <leader>cmd :!open -a terminal<CR>
else
nnoremap <leader>cmd :!start cmd<CR>
endif
This let's you get rid of the :execute, is a bit faster, and much easier to extend or tweak. (All the other caveats about :noremap and the missing <CR> from @romainl's answer still apply.)
in Lua:
if vim.fn.has("mac") == 1 then
vim.api.nvim_set_keymap("n", "<leader>cmd", "<cmd>!open -a terminal<cr><esc>", { noremap = true, silent = true })
else
vim.api.nvim_set_keymap("n", "<leader>cmd", "<cmd>cmd :!start cmd<cr><esc>", { noremap = true, silent = true })
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With