This question already has answers here:
How to redefine a command in Vim?
(3 answers)
Closed 2 years ago.
I want to map :bd to :bd! using:
command! -nargs=* -complete=buffer bd :call bd!
but vim told me "User defined commands must start with an uppercase letter"
update solutions from answer:
cnoremap bd bd!
another way
cnoreabbrev <expr> bd getcmdtype() == ":" && getcmdline() == 'bd' ? 'bd!' : 'bd'
You can create a "user-defined" command to wrap the target command, bd in your case. Then you have to let the command name start with an uppercase letter.
In fact, if I understand your requirement correctly, you want to always execute bd! when you type bd in command mode, then you can just create a mapping:
cnoremap bd bd!
In this way, when you type :bd the ! will be there automatically.
P.S.
When you used call, you are calling a function() instead of a command.
Related
I want to map <M-o> to quickly look up buflist from command-mode.
Here's an example normal-mode mapping:
nnoremap <M-o> :ls<CR>
Here's an attempt to do the same for command mode using execute():
cnoremap <M-o> <C-r>=execute(':ls')<CR>
This however simply appends whitespace-separated :ls results to the command line, with no side effect of the :ls table actually showing.
Is there a way to execute a command without leaving command-mode?
Update:
Closest I've come to cracking this using Vimscript is the following:
function! RunCmdFromCmdline(cmd)
let l:cmd_line = getcmdline()
echo execute(a:cmd)
return l:cmd_line
endfunction
cnoremap <M-o> <C-\>eRunCmdFromCmdline(':ls')<CR>
The echo makes it so the results of a:cmd do pop on the screen, however in invisible font. I tried playing with :redraw <bar> in different combinations with no success.
Exiting from the command mode from within a <C-r>= or <C-\>e prompt does not seem possible.
You can save the contents of the current command line in a register, then run ls and paste the contents of the register:
cnoremap <esc>o <home>let #x="<end>"<cr>:ls<cr>:<c-r>x
So if command line looks like this:
:echo 'some'
type <M-o> to get:
:ls
1 %a + "filename" line 1
:echo 'some'
This works. It uses global variables, but arguably this is an acceptable use for them, since there's only a single command-line you can be in at a time.
function! SaveCmdline()
let g:save_cmdline = getcmdline()
let g:save_cmdpos = getcmdpos()
return ''
endfunction
function! RestoreCmdline()
call setcmdpos(g:save_cmdpos)
return g:save_cmdline
endfunction
cnoremap <M-o> <C-\>eSaveCmdline()<CR>ls<CR>:<C-\>eRestoreCmdline()<CR>
This works with whatever quotes or unfinished syntax you have in your command-line, restores the full command-line and the cursor to the position it was before running the command, doesn't mess with any registers (only touches the two global variables) and doesn't mess with command-line history either (see q: command for history.)
It does have one tiny bug, in that cnoremap actually also works when you're typing a search expression (after / or ?) among a few other sub-modes (see getcmdtype() for a list of those.) If you use the mapping there, it will search for "ls" and then restore your search term as an Ex command, oops...
You can probably use getcmdtype() to detect that and possibly only perform the actions while you're typing an Ex command and not in the other modes.
UPDATE: This fixes the last part, only executing the command while in the Ex command-line, not in search or other context. It also makes the interjected command parameterizable.
function! CmdlineExecute(cmd)
if getcmdtype() != ':'
return ''
endif
return "\<C-\>eSaveCmdline()\r".a:cmd.
\ "\r:\<C-\>eRestoreCmdline()\r"
endfunction
cnoremap <expr> <M-o> CmdlineExecute('ls')
(Note this still needs the definition of the two functions above.)
This question already has answers here:
Vimrc settings to emulate Sublime's parenthesis auto-completion
(2 answers)
Closed 4 years ago.
Currently I moved to vim to use it as my text editor
but I have a problem. In my .vimrc file, I mapped {, [, and < to be {}, [], and <> respectively, it works right but vim makes a lot of blank spaces inside ( to be like ( )!
How can I solve that without adding a plugins if it possible?
Then I start vim (or gvim) with an rc file with only the following commands, it works as expected.
set nocompatible
inoremap { {}<left>
inoremap ( ()<left>
inoremap [ []<left>
inoremap < <lt>><left>
inoremap " ""<left>
inoremap ' ''<left>
Copy the above for a file (e.g. foo), and run vim -u foo, see if it works. If that doesn't work, I cannot reproduce your problem.
If the lines above work, then add the rest of your rc file piece-by-piece, and check where the behavior changes.
I am having trouble figuring out how to change the default trigger for fuzzy find within VIM.
The default trigger is :FZF
I would like the trigger to be :fzf
Thanks!
You can add your own mapping for fzf in your .vimrc.
nnoremap <silent> <C-p> :fzf<CR>
This will call :fzf when you issue Ctrl+P in normal mode.
You can create an abbrev for the command line
cnoreabbrev <expr> fzf getcmdtype() == ":" && getcmdline() == 'fzf' ? 'FZF' : 'fzf'
then if you type :fzf followed by enter or followed by space it will be automatically swapped to :FZF.
I've used Vim to code my Go script for a month, and I'm pretty comfortable with :Import and :Drop vim command when it comes to importing and unimporting any packages.
However, I've more and more tired of typing such a long word which includes Capital letter so frequently, so I came to think that if I can use :i and :d other than :Import and :Drop, I'd be satisfied even more. However, I'm not sure whether I can define such a command in Vim, since it involves 1) turning into command-line mode, and 2) taking a variable which is determined dynamically in typing.
So for example, if I import encoding/csv package, all I want to type in is :i encoding/csv, etc... Can I define those commands?
I stumbled upon this question, but I cannot get what it is doing nor I'm not sure whether the answer applies to this question in the first place. Can I solve the issue by replacing all of w and W on the linked post to i or d?
Also, does it differ from the case that doesn't take a variable (say, Fmt command to go-format the script)?
Thanks.
EDIT 2: As pointed out by glts below, it's better to use cnoreabbrev or cnorea as pointed out in this answer.
Better working example (paste into ~/.vimrc):
cnorea <expr> i ((getcmdtype() is# ':' && getcmdline() is# 'i')?('Import'):('i'))
cnorea <expr> d ((getcmdtype() is# ':' && getcmdline() is# 'd')?('Drop'):('d'))
EDIT: Simple answer. Just using cabbrev or ca (command abbreviation) seems to work:
WORKING EXAMPLE (Paste this in ~/.vimrc):
ca i Import
ca d Drop
Working on vim 7.3, Ubuntu 64 bit.
ORIGINAL ANSWER (more complex):
According to http://vim.wikia.com/wiki/Replace_a_builtin_command_using_cabbrev :
You can use :command to define your own commands, but user-defined commands must start with an uppercase letter to avoid confusion with built-in commands.
So, using :command, you can probably use :I and :D, but not :i and :d.
It goes on to say:
Suppose you have a user-defined :E command that you want to use to override the default :e command. You could do the following:
:cabbrev e <c-r>=(getcmdtype()==':' && getcmdpos()==1 ? 'E' : 'e')<CR>
The (getcmdtype()==':' && getcmdpos()) makes sure the replacement happens only in the first column of the command line (i.e. not later in the line, where it is most likely NOT intended to be used as a command, and not on the search line, which is also affected by cabbrev).
If you do this a lot, it would be useful to define a function to do it for you. Use this to quickly and easily define lowercase abbreviations for whatever command you want:
function! CommandCabbr(abbreviation, expansion)
execute 'cabbr ' . a:abbreviation . ' <c-r>=getcmdpos() == 1 && getcmdtype() == ":" ? "' . a:expansion . '" : "' . a:abbreviation . '"<CR>'
endfunction
command! -nargs=+ CommandCabbr call CommandCabbr(<f-args>)
" Use it on itself to define a simpler abbreviation for itself.
CommandCabbr ccab CommandCabbr
This not only creates the function, but also provides the (lowercase!) command :ccab to define such abbreviations "on the fly".
So using a function looks like one way to go if you want to use lowercase :i and :d.
The cmdalias.vim - Create aliases for Vim commands plugin allows you to set up lowercase aliases, e.g.:
:Alias i Import
A simple solution:
nnoremap <leader>i :Import<Space>
nnoremap <leader>d :Drop<Space>
In normal mode, <leader>i populates the command-line with
:Import | <--- cursor
ready for you to type in or <tab>-complete an argument.
Better:
nnoremap <leader>i :Import <C-d>
nnoremap <leader>d :Drop <C-d>
<leader>i populates the command-line with
:Import | <--- cursor
and shows a list of possible completions.
Even better:
set wildcharm=<C-z>
nnoremap <leader>i :Import <C-z>
nnoremap <leader>d :Drop <C-z>
Supposing you have wildmenu already setup, <leader>i populates the command-line with
:Import firstpackagenameinthelist
with the wildmenu open and ready for <tab>bing.
I'm currently using the following mapping to, essentially copy over any files written in my dev env to my local server via executing a script. It works fine for individual files. However, I have a habit of doing :wa to save all buffers open:
au BufWritePost /path/to/dev/* silent !$HOME/bin/somescript.sh %:p
Any suggestions for how I could rewrite this to be a conditional like:
if one file
exec script to copy just that file # like I already have
if :wa
# here I'd probably exec a script to just copy recursively
EDIT
Possible solution per ZyX's solution:
au BufWritePost /Users/rlevin/programming/sugar/Mango/sidecar/* silent !$HOME/bin/sugarbuild.sh %:p
" If we do :wa<CR> we check if command type is ':' and if command itself was
" 'wa'. If so, we call the command WA which calls BuildSidecarIfInProject.
" This checks if we're actually within the project's directory
cnoreabbrev <expr> wa ((getcmdtype() is# ':' && getcmdline() is# 'wa')?('WA'):('wa'))
command! WA :call BuildSidecarIfInProject()
function! BuildSidecarIfInProject()
if fnamemodify('.', ':p')[:44] is# '/Users/rlevin/programming/sugar/Mango/sidecar'
exec ":!$HOME/bin/toffeebuild.sh"
endif
endfunction
There is no way to determine number of files saved, but you can remap/abbreviate wa:
command WA # command that executes a script to just copy recursively
cnoreabbrev <expr> wa ((getcmdtype() is# ':' && getcmdline() is# 'wa')?('WA'):('wa'))
Some smart guy once said, "Premature optimization is the root of all evil." If you really need on-the-fly backup/deployment to your server, why don't you just run the recursive version every time, or possibly bound to a hotkey? I.e. don't treat the single-file case specially. For example, rsync is pretty good at avoiding unnecessary copying.