I need to have one of
set foo=bar
or
set foo=baz
in .vimrc. I'd like to read either "bar" or "baz" from a certain file. That is, what one would do in sh with foo=cat file`` (I don't know how to escape backticks...). How does one do that?
let &foo = readfile('filename', '', 1)[0]
The let &foo syntax lets you set options to arbitrary expressions.
Related
I use https://github.com/pbogut/fzf-mru.vim plugin which writes information in:
/Users/karl/.cache/fzf_mru/cache.txt
but I would like to set my own path to the file. As far as I understood by default there is no such possibility, so I'm looking for a way to do it via vim config, i.e. without changing plugin itself.
This plugin basically consists of 3 files and in:
https://github.com/pbogut/fzf-mru.vim/blob/master/autoload/fzf_mru/mrufiles.vim
we can see that there is a function fzf_mru#mrufiles#cachefile() which points to the necessary file. :echo fzf_mru#mrufiles#cachefile() also points to:
/Users/karl/.cache/fzf_mru/cache.txt
and if I understand correctly then I need to change the value of variables of this function. Something like let g:cafile='/a/b/file.txt' in the config.
But all my attempts were unsuccessful, apparently I do not quite understand how to do it. Maybe someone can give me a hint. Maybe it is not possible to do this at all without modifying the plugin itself?
s:cache_dir is a script-local variable that can't be overridden with a global one so you can't change the behaviour of the functions from the outside. This means that the code must be changed to allow user customisation.
You have two options:
do it yourself… and send a PR,
open an issue and let the maintainer do it.
If you choose option #1, you will have to change that function:
fu! fzf_mru#utils#opts()
let s:lash = fzf_mru#utils#lash()
let usrhome = $HOME . s:lash( $HOME )
let cahome = exists('$XDG_CACHE_HOME') ? $XDG_CACHE_HOME : usrhome.'.cache'
let cadir = cahome.s:lash(cahome).'fzf_mru'
let s:cache_dir = cadir
endf
to something like:
fu! fzf_mru#utils#opts()
let s:lash = fzf_mru#utils#lash()
if exists('g:fzf_mru_cache_dir')
let s:cache_dir = g:fzf_mru_cache_dir
else
let usrhome = $HOME . s:lash( $HOME )
let cahome = exists('$XDG_CACHE_HOME') ? $XDG_CACHE_HOME : usrhome.'.cache'
let cadir = cahome.s:lash(cahome).'fzf_mru'
let s:cache_dir = cadir
endif
endf
which should allow you to define your cache directory in your vimrc:
let g:fzf_mru_cache_dir = '$HOME/foo/bar'
I'm trying to get the list of absolute paths to my buffers, but cannot work out how to add the :p to expand as in expand("v:val:p") into map.
let l:buffers = filter(range(1, bufnr('$')), 'buflisted(v:val)')
let l:buffiles = map(copy(l:buffers), 'expand(bufname(v:val).":p")')
The above does not work and append :p to end of each filename loaded as buffer. .e.g.
['.vim/vimrc:p']
What's the right way to pass an expand modifier inside map or filter expression?
The right way is :h getbufinfo().
let l:files = map(getbufinfo({'buflisted': 1}), 'v:val.name')
Concerning arbitrary file name expansion, it is what :h fnamemodify() is used for.
echo fnamemodify('filename.ext', ':p')
On the other hand, :h expand() performs an expansion of :h cmdline-special.
I'm a heavy VIM user but I missing one thing…
setting a fix jump marker in a comment on different parts of a (large) current open file
What I expect:
setting a marker in a comment like: // vim: marker(x)
jumping to the marker with: 'x
example (using tcl code) using 'x to jump to function p_structDEF_MqC
proc p_func_arg_name_DEF_MqC {key value} {
set cmd "N"
regexp {^(\w)#(.*)} $value dummy cmd value
set ::ARG_DEFAULT(k,$key) $cmd
set ::ARG_DEFAULT(v,$key) $value
}
proc p_arg_name_DEF_MqC {key value} {
func_arg_name_DEF_${::LANG}_MqC $key $value
}
## vim: marker(x)
proc p_structDEF_MqC {name} {
global xCLASS xPREFIX
set prefix [string range $name 0 end-1]
if {$prefix ne "Mq"} {
lappend xPREFIX "$prefix"
}
lappend xCLASS "${prefix}C"
}
proc p_enumDEF_MqC {name argv} {
}
proc p_typeDEF_MqC {VAR VALUE} {
}
proc p_fupuDEF_MqC {name ret argv} {
}
You can create an autocommand that scans files for those marks,
and create them using setpos(). You can go as complex as
you want in your scripting, i.e. to analyze the next line
and determine where the mark should be. Here is a simple
implementation in a single command that creates marks on the
first character of the next line:
au BufRead * g/vim: marker([a-z])/call setpos(
\ "'".matchstr(getline('.'), '(\zs\w'),
\ [0, getpos('.')[1]+1, 1, 0] )
This answer is based mainly on :autocmd and :g. You should
check the help files for both (:h :au and :h :g). An
autocommand runs the specified command when a certain event
happens for files matching a specific pattern. So, more help
topics for you to read:
autocmd-events
autocmd-patterns
You can use the pattern to restrict this to certain files.
Then, we have the :g command which searches for lines matching
a pattern and executes a command. The search is where you modify
which flags are you looking for. Based on your comment, let's say
for example you want to make the space after : optional. Then
update your regex to:
vim: *marker([a-z])
Modify this as you need.
The command is centered in the setpos() (again search the help
for it... everything I'm saying is in the help anyway). It takes
two arguments, one is what to set and the other is what to set
to. We want to set a mark, so we need to give it an expression
like "'a" to set mark a. To figure out which letter is the
mark supposed to be applied to, we use:
matchstr(getline('.', '(\zs\w')
Here we search for the first letter after the first parenthesis
(with (\zs\w) on the text of our current line, retrieved with
getline(). Search for the help of all these functions. This is
concatenated to a quote, with "'" . {expr} to make a "'x" if
the letter was x.
Then for the second argument, if must be an array similar to what
getpos() returns. Search the help again. However we are
modifying it, to set the mark on the beginning of the next
line. Thus we only use the line item returned by getpos(),
which is the second item, and add 1 to it.
[{buffer}, {line}, {col}, {virtual-offset}]
[0, getpos('.')[1]+1, 1, 0]
the working solution based on previous answer:
au BufRead *.c silent! g/vim: \*Marker(\[a-z])/call setpos(
\ "'".matchstr(getline('.'), '(\zs\w'),
\ [0, getpos('.')[1]+1, 1, 0] )
→ thanks to #sidyll for the help.
i want to read a input from the user. I do this that way:
let wordUnderCursor = expand("<cword>")
call inputsave()
let filePattern = input('Searchterm: ')
call inputrestore()
Now my goal is to already put something into the searchterm so that the user (me) doesnt has to write the whole searchterm.
So is it possible to prepopulate the input-function with a string?
thx in advance
Check out :help input(); it tells you that there are optional additional arguments; the first one is exactly the default text you've been looking for:
input({prompt} [, {text} [, {completion}]])
[...]
If the optional {text} argument is present and not empty, this
is used for the default reply, as if the user typed this.
For your example:
let filePattern = input('Searchterm: ', wordUnderCursor)
If you don't want the preset, you can remove it via <BS> character-by-character, or in one fell swoop with <C-u> (as in any command-line).
I am trying to set an option but it does not work when using a variable.
This is what actually works:
set runtimepath+=~/.vim/bundle/foo/foo.vim/
When I try this, it DOES NOT work anymore:
g:foo_path = '~/.vim/bundle/foo/foo.vim/'
set runtimepath+=g:foo_path
I have seen a similar topic here and they use the following command to set an option with a variable:
let &backupdir=s:vimetc.'backups/'
However, when I try this:
let &runtimepath+=g:foo_path
It still DOES NOT work. I am getting:
E734: Wrong variable type for +=
Any ideas? Thanks.
The problem is set does not support using string variables and let does not support += for string types.
This should work:
let g:foo_path = '~/.vim/bundle/foo/foo.vim/'
let &rtp.= ',' . g:foo_path
another workaround
exe 'set runtimpath='.a:lines
after reviewer's comment, a 2.0 version
exe 'set runtimepath='.&runtimepath.','.g:foo_path
You've almost got it. Appending options is done (regardless of the type of the option value, i.e. string vs. number) via :set option+=val, whereas the concatenation operation with String variables is done via :let &option .= var. You get the E734 error because += with :let is for numerical addition only.