Modify function/variable values of the plugin via vim config - vim

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'

Related

Vim - Overwrite Plugin Scoped Function

I've a plugin in Vim and I don't like the behavior of a single function within it. But it isn't rly a case to open a pull request, but more an extension for it.
I know that overwriting a function ist possible by using a bang as postfix, as soon as the new definition comes after the previous one. But how can I do such thing, if this method is scoped to a script within a plugin?
I wasn't able to find a hint in _Vim_s help, nor by request a search engine. Anybody aware of this topic, at least if he can say that it is simply not possible.
A short example:
plugin/autoload/plugin.vim
...
function! s:foo() {
// behavior I would like to adjust
}
...
~/.vimrc
function! foo() {
// the "correct" behavior
}
Thanks for any help!
Actually it is possible. But as #romainl said, you'd better suggest your patch to the plugin maintainer or ask for a variation point.
Regarding the how.
First, you'll need to identify the script number of this autoload plugin. Let's say that :scriptname says it's 210. In order to do that automatically I have a lh#askvim#scriptid() function in my library plugin that does the job -- see the current definition at the end of the answer.
Then, to override the s:foo() function, you'll need to provide a new definition for
function! <SNR>210_Foo()
new definition
endfunction
(I've just tested it with vim 8.0-1157)
IOW, we can override a script-local function. However, I haven't found how to override a script-local variable directly without a reference to its s: dictionary. We could inject setter/getter functions to a specific variable or a function that returns the local s: dictionary.
lh#askvim#scriptid() current definition is the following
" Function: lh#askvim#execute(command) {{{3
" #since Version 4.0.0
if exists('*execute')
function! lh#askvim#execute(command) abort
return split(execute(a:command), "\n")
endfunction
else
function! lh#askvim#execute(command) abort
return s:beware_running_through_client_server ? [] : split(lh#askvim#exe(a:command), "\n")
endfunction
endif
" Function: lh#askvim#scriptnames() {{{3
function! lh#askvim#scriptnames() abort
let scripts = lh#askvim#execute('scriptnames')
let s:scripts = map(copy(scripts), 'split(v:val, "\\v:=\\s+")')
call lh#list#map_on(s:scripts, 1, 'fnamemodify(v:val, ":p")')
return s:scripts
endfunction
" Function: lh#askvim#scriptid(name) {{{3
function! lh#askvim#scriptid(name, ...) abort
let last_change = get(a:, 1, 0)
if last_change || !exists('s:scripts')
call lh#askvim#scriptnames()
endif
let matches = filter(copy(s:scripts), 'v:val[1] =~ a:name')
if len(matches) > 1
throw "Too many scripts match `".a:name."`: ".string(matches)
elseif empty(matches)
if last_change
throw "No script match `".a:name."`"
else
return lh#askvim#scriptid(a:name, 1)
endif
endif
return matches[0][0]
endfunction
That is not possible.
s:foo() is scoped to the script it belongs to (see :help s:) so it can't be accessed from anywhere else.
Fork it.
Make the desired changes to your fork.
Use your fork instead of the original.
Consider submitting a pull request.

Vim's custom foldmarker {,} doesn't work

I have a js file with following content:
function do_this(){
a = '{1}';
}
function do_that(a){
b = b + 1;
}
// vim: set fdm=marker fmr={,} :
When it folds it shows following:
function do_this(){
a = '{1}';
}
function do_that(a){ +-- 3 lines_____________
// vim: set fdm=marker fmr={,} :
I expect both functions to be folded. I guess "a = '{1}';" is getting in the way.
Is there a way to fix this using only the custom marker "{,}" within the modeline?
Unfortunately foldmarker does not allow regex matching, as specified by :h fmr. Therefore it will only match a literal string, so there's no way getting around the a = '{1}' in your example. However, it seems like what you really want is
// vim: set fdm=syntax fdls=1 :
with
let javaScript_fold=1
in your ~/.vimrc.

How to set an option using a string in a vim script

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.

Vim: How to write a function that searches the current buffer?

I am trying to write a function in Vim that searches the current buffer for a certain pattern and returns it. But, I'm failing horribly. Basically, what I want is a function that returns the (PHP) namespace of the file I am working in. The namespace is defined in the file itself:
namespace Foo\Bar;
What I would like is a function that returns the Foo\Bar part as a string. I.e. something that searches like /namespace\s\([^;]\+\) and returns the first submatch.
Edit: Here's the function I build thanks to the help I got:
func! PhpNamespace()
let l:lnr = 0
while l:lnr < line('$')
let l:str = matchstr(getline(l:lnr), '^\s*namespace\s\+[^;]\+')
if len(l:str)
return substitute(l:str, '^\s*namespace\s\+', '', '')
endif
let l:lnr = l:lnr + 1
endwhile
return ''
endfunc
One option is to use searchpos(), which gets you the start position; you then need to extract the text yourself. This is fast and easy, especially if you need to search forward / backward from the cursor position. With the 'n' flag, the cursor position will not change. Otherwise, you have to save and restore the cursor position (getpos('.'), setpos('.', saved_cursor)).
For your problem, it looks like the namespace declaration is likely at the beginning of the file, and is limited to a single line. Then, you could also get individual lines with getline(lnum) in a loop and extract the text with matchstr(), and break out of the loop once you have it.

Setting an option to the content of a file in .vimrc

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.

Resources