I am trying to open the following url:
:execute 'silent !open https://github.com/junegunn/fzf#environment-variables'
However, it seems like when I run this command, the # is replaced (again) with the filepath instead of appearing as # literally. How do I prevent this?
Escape it with a backslash:
:execute 'silent !open https://github.com/junegunn/fzf\#environment-variables'
Call escape():
:execute 'silent !open' escape('https://github.com/junegunn/fzf#environment-variables', '#')
Related
I am trying to use vim's :exe command to vimgrep the word under cursor, but I am having problems with the command construction:
If my command is
:execute "vimgrep " shellescape(expand("<cword>")) " somedir"
it expands to
execute "vimgrep 'foo' somedir"
But if my command is
execute "vimgrep " .. shellescape(expand("<cword>")) .. " somedir"
it expands to
execute "vimgrep '' somedir"
How do I correctly expand <cword> raw, without single quotes?
Wrapping something in single quotes is the main purpose of shellescape(). If you don't want those quotes, don't use shellescape().
:help shellescape() is used for preparing commands before they are shelled out. Since :help vimgrep is an internal tool and nothing is sent to a shell, there is no need for quoting.
This means that the following command should cover most of your needs:
:execute "vimgrep " .. expand("<cword>") .. " somedir"
Also, :vimgrep searches in files, not directories. Your command should then look more like:
:execute "vimgrep " .. expand("<cword>") .. " somedir/*"
I am trying execute a nested execute command within a vimscript. I know that this command works in ex mode:
g/\(^\n\|\%1l\).\_.\{-}\n$/execute "normal! vap:call MCformat()\<cr>"
I want to be able to run that command from within a script. I have tried a number of permutations of the following code but can't get it to work.
function! RunMCformat()
silent! execute "normal! g/\(^\n\|\%1l\).\_.\{-}\n$/execute \"normal! vap:call MCformat\(\)\<cr>\""
endfunction
Probably I am not escaping the string properly but I don't know where I am going wrong.
Because of the double quotes, you'd have to escape (i.e. double) the backslashes inside the /.../ pattern definition. However, the biggest problem is the first :normal!; :g[lobal] is an Ex command. So, you're lucky, you can just prepend :silent! (which invokes Ex commands like :global), are you should be done; no nested :execute is necessary:
function! RunMCformat()
silent! global/\(^\n\|\%1l\).\_.\{-}\n$/execute "normal! vap:call MCformat()\<cr>"
endfunction
In general, I would avoid nesting of :execute; that's not readable in any case. Rather, extract parts of your code into a function / custom command (in which you can use :execute), and invoke that.
I'm trying to export a variable to a file:
To simplify what I'm doing right now, I use the variable #" which contains the content of the current register :
function! CopyVar()
call system("printf '%s' '".#"."' > /tmp/varfile")
endfunction
nnoremap <Leader>y :call CopyVar()<cr>
This works fine, but doesn't work if the variable contains single quotes for example.
If the input is for example " hi ' , the command fails with E484: Can't open file /tmp/v7IzDCI/74
I think I could escape the #" (because if ' single quotes are present, the command will fail), however, I'm not sure it is the best method to export a variable to a file.
How can I do it to guarantee that it will work with any input (with quotes, multilines and other special characters) ?
I know that you can use the system clipboard, it's not what I'm trying to achieve here.
That is what shellescape() is for. BTW for better quoting, I would write your function like this:
function! CopyVar()
let cmd="printf '%s'". shellescape(#") . " > /tmp/varfile"
call system(cmd)
endfunction
nnoremap <Leader>y :call CopyVar()<cr>
However, your solution looks overly complex, by adding some shell quotation to the complex VimL quotation. That is not needed. I would rather do it differently:
:redir! > /tmp/varfile | sil exe 'echo #"' |redir end
This adds an extra leading blank line at the beginning, but you could remove this afterwards using sed or something.
Or even better, use the writefile() function:
nnoremap <Leader>y :call writefile(split(#", '\n'), '/tmp/varfile')
#" is a register, not a variable.
You can use a substitution to clean up your text:
let foo = substitute(getreg('"'), "'", "\"", "g")
before the "write" step.
I'll let you figure out what patterns you need to clean up.
Using redir is probably the most robust solution
function! CopyVar()
redir! > /tmp/varfile | sil exe 'echo #"' |redir end
call system ("sed '1d' /tmp/varfile > /tmp/tmpvarfile; mv /tmp/tmpvarfile /tmp/varfile")
endfunction
nnoremap <Leader>y :call CopyVar()<cr>
It works with any characters. The second part is needed because the redirection will add an additional newline which is not wanted, hence the sed command.
I'm trying to write a custom command in Vim to make setting the makeprg variable for an out-of-source build easier. Having read the command manual, so far I've got as far as this
command! -complete=file -nargs=1 Cmakeprg call set makeprg=cmake --build <args><CR>
but it isn't working. How do I call "set" within the command?
You :call functions, :set is an Ex command just like :call (as it's invoked with the : prefix).
A complication with :set is that whitespace must be escaped with \, but that can be avoided by using :let with the &option, and <q-args> automatically quotes the passed command arguments.
You also don't need <CR>; this isn't a mapping. Taken all together:
command! -complete=file -nargs=1 Cmakeprg let &makeprg = 'cmake --build ' . <q-args>
Add a colon in front of "set" and use a <CR> to execute it: :set … <CR>
Do not use call.
I mostly use vim from the terminal by vi command.
I want to create and save a file named something like getting started.txt (there is space between two words). I tried two methods:
Method #1
:sav getting started.txt
but I got an error : E172: Only one file name allowed
Method #2
:sav "getting started.txt"
This time I got : E471: Argument required
How can I achieve what I want?
Escape the space character:
:sav getting\ started.txt
Commenter #ib mentions fnameescape, here's how you can use it:
Enter :save and a space.
Press Ctrl-R then = to enter expression mode.
Enter fnameescape("Your spacey, special character'y file name"). Tab expansion works, so you can probably do fnTabeTab.
Press Enter to insert the escaped file name into your command line.
Poster iler.ml suggests a function to do this easily (I've modified his code slightly). Put this in your .vimrc:
" :W and :Save will escape a file name and write it
command! -bang -nargs=* W :call W(<q-bang>, <q-args>)
command! -bang -nargs=* Save :call Save(<q-bang>, <q-args>)
function! W(bang, filename)
:exe "w".a:bang." ". fnameescape(a:filename)
endfu
function! Save(bang, filename)
:exe "save".a:bang." ". fnameescape(a:filename)
endfu