How to create custom find files command using fzf.vim? - vim

I am using fzf.vim, I have set FZF_DEFAULT_COMMAND='fd' to improve search speed.
But 'fd' default behavior will respect .gitignore, .ignore files, and filter hidden files. It's useful in most cases, but not all.
So I want to create another command FilesUnrestrict, still using 'fd', but with two options: '--no-ignore --hidden', so all files will be find.
Here is my command:
command! -bang -nargs=? FilesUnrestrict
\ call fzf#vim#grep('fd -tf -tl -i -u --exclude ".git" '.shellescape(<q-args>), 0, fzf#vim#with_preview(), <bang>0)
It is good to open fd and fuzzy search the files, but when type Enter to open the file, there is an error:
Here is the related issue:https://github.com/junegunn/fzf.vim/issues/1454
How could I solve this issue?

Finally I found this issue: https://github.com/junegunn/fzf.vim/issues/462.
Using fzf#run fzf#wrap could solve this issue.

Related

fzf to read file into nvim buffer

I have a directory with a group of templates used for technical writing and shared with other people (they use it as part of a sublime package). Since I use nvim, I will often open a separate tmux pane, use :Files from fzf.vim to open the template, copy its content, and paste it into my buffer.
Alternatively, I can read :r from the template directory, but that doesn't come with a fuzzy search, making it hard to find the right file among hundreds of options. gotbletu's https://www.youtube.com/watch?v=Zew0mgJwAh8 would be a perfect solution, except that I can't add the tags on top of each template that his script requires (again, the templates are shared with other people).
I've tried to combine :r with fzf in a shell function, but so far nothing works. Any thoughts on how to get this done?
you may try putting something like the following in your init.vim
let g:pathToTemplates='/tmp/'
function! GoSink(file)
execute ':r '.g:pathToTemplates.a:file
endfunction
command! Go call fzf#run({
\ 'source': 'ls '.g:pathToTemplates,
\ 'sink': function('GoSink')})
then just type :Go
if you really want to do this from the terminal then you'll want this in your bashrc/zshrc/...
function fzfreadtemplate(){
local templatedir='/tmp/'
filename="$templatedir"$(ls "$templatedir" | fzf)
if [[ -f "$filename" ]]; then
vim -c ':r '"$filename"
fi
}

How to fix duplicate cscope ? is it a better way?

It is several years I am programming with vim and I used ctags.
I am working with a reasonably large C/C++ package and I need to find definition of functions. I usually use grep + ctags.
Recently I tried to use cscope instead of ctags and installed it with Vundle.
I see the following error for some of my files
E568: duplicate cscope database not added
I searched the web and found this:
https://blogs.oracle.com/natarajan/entry/avoiding_duplicate_cscope_database_error
It doesn't work.
How can I fix this?
Expanding on Artem's answer:
The Vim help for cscopeverbose is as follows:
If 'cscopeverbose' is not set (the default), messages will not be printed
indicating success or failure when adding a cscope database. Ideally, you
should reset this option in your .vimrc before adding any cscope databases,
and after adding them, set it. From then on, when you add more databases
within Vim, you will get a (hopefully) useful message should the database fail
to be added.
The problem here is that (a) there are multiple scripts attempting to load the cscope.out file and (b) they're not following the best practices of disabling the "verbose" cscope warnings before loading the file then re-enabling it afterwards, as suggested by the help text above.
The full error output should tell you which script is triggering this warning; for me it looked like this:
Error detected while processing /home/me_and/.vim/plugin/cscope_maps.vim:
line 42:
E568: duplicate cscope database not added
The fix was then to edit the ~/.vim/plugin/cscope_maps.vim file to add set nocscopeverbose immediately before the cs add ... lines. My version of this file already had set cscopeverbose immediately after, but if yours doesn't you should add that too.
Found the solution which worked for me (here: http://thoughtsolo.blogspot.com/2014/02/cscope-issue-duplicate-cscope-database.html):
Just add this line "set nocscopeverbose " to your ~/.vimrc file.
As per the blog, "This error pops up when VIM is already compiled with 'CSCOPE' module and you have also installed "cscopemenu.vim"". I assume that you have a vim executable with has been configured with --enable-cscope option.
Here's what I do:
Download cscope source and build it, install the executable in a directory which is available in your PATH
Download vim source code and configure it with --enable-cscope, build the source and install the executable
Download cscope_maps.vim and place it under $HOME/.vim/plugin directory. This contains cscope settings for vim.
Create cscope database out of the source and header files. You may do something like the following
find $PROJECT_HOME -name *.c -o -name "*.cpp" -o -name "*.cc" -o -name "*.h" -o -name "*.hpp" > cscope.files
cscope -qbR -i cscope.files
You can add these commands in an alias and excute the alias every time you want to update your cscope database. These two commands create finally create cscope.out database file.
Update .vimrc file to have the following
if has("cscope")
set csprg=<location to cscope executable>
set csto=0
cs add <location to cscope.out>
endif
I hope after doing these steps you should be able to use cscope with vim easily.
Note that if you are working on multiple projects, you should be able to add appropriate environment variables to enable vim to pick the correct cscope database.
To answer your second question, may I suggest using tagbar. This will list your function names in the current source or header file. You can install it using Vundle. Add the following line to your .vimrc
Plugin 'majutsushi/tagbar'
Add this to your .vimrc to toggle tagbar view
nmap <F4> :TagbarToggle<CR>
Note that F4 is just an example and you may use any binding to do the same.

VIM - Sourcing tags from multiple locations in project

Good day,
I typically work on relatively small (less than 20,000 lines of code) projects that are all self contained within a single directory, have their own Makefile, and are fairly easy to work with.
VIM is my preferred editor, and when I open a project, I typically build the ctags list via a mapping to the F10 key:
map <F10> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<CR>
This allows me to jump to the definition of a variable/struct/etc via moving the cursor over the text, and hitting CTRL+], as well as using code completion with a drop-down list via OmniCppComplete.
However, I am now working on a slightly larger project which makes use of LOTS of structures. Furthermore, many of these structures have arrays of other custom structures as members, so code completion is a very useful and important tool for me right now.
I have two paths that include a lot of .C files and .h files, and they may change from machine to machine. On each machine, however, we have an environment variable in our .bashrc file that points to them like so:
SDK_SRC_PLUS_HEADERS=/public/sdk
THIRD_PARTY_SDK=/private/sdk
I would like to be able to have VIM automatically refer to the contents of these additional paths when I attempt to do code completion (via VIM's built-in OmniCppComplete feature), or to jump to the files in these locations when I use CTRL+] in VIM to jump to the definition of a struct, function, variable, etc.
So, for both of the above paths, I cd into them, and generate the tags via ctags -R. Then, I modified my ~/.vimrc file to include additional tags paths, like so:
tags=./tags
tags+=$SDK_SRC_PLUS_HEADERS/tags
tags+=$THIRD_PARTY_SDK/tags
I then cd into my project at /home/user1/projects/test, start VIM, and hit F10 in VIM to index it. However, this does not work at all. In fact, it breaks my ability to even use tags just for the project itself (ie: CTRL+] now does nothing).
Does anyone have any suggestions on how I could have code completion source tags and jump-to-definitions using multiple source directories via environment variables?
Thank you all in advance for your time and assistance!
I wanted to add to the solution provided by #sehe.
This is the final set of changes I made to my .vimrc. The first lines are for adding expanded environment variable paths to my tags variable. The other is for auto-updating tags in the event that I have to update my SDK and don't want to be able to accidentally use out-of-date tags:
" CTAGS tag generation for OmniCppComplete
set tags+=./tags
exec expand("set tags+=$SDK_SRC_PLUS_HEADERS/tags")
exec expand("set tags+=$THIRD_PARTY_SDK/tags")
" Can verify taglist is correct via ":set verbose tags?" command
" Create a mapping to delete the old tags, re-generate them, and use them
map <F10> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q . \| rm -f $SDK_SRC_PLUS_HEADERS/tags \| ctags -R -f $SDK_SRC_PLUS_HEADERS/tags $SDK_SRC_PLUS_HEADERS/tags \| rm -f $THIRD_PARTY_SDK/tags \| ctags -R -f $THIRD_PARTY_SDK/tags $THIRD_PARTY_SDK/tags \| echo "Done re-generating tags."<CR>
It indeed appears to be the problem that you can't use environment variables inside the tags setting.
I came up with this as a workaround:
:let &tags.=expand(",$SDK_SRC_PLUS_HEADERS/tags")
This might be slightly more friendly:
:exec expand("set tags+=$SDK_SRC_PLUS_HEADERS/tags")

Indenting in VIM with all the files in Folder

I have a folder containing hundreds of TTL (TeraTermLanguage) files.
Now I wanted indent all these files.
I have created teraterm.vim for indentation and I open a file using VIM and do "gg=G" and whole file gets indented properly.
But is there any way, where I can indent all the files in folder.
I wanted to do with help of Shell. But in VIM I couldnt pass file indent command as the argument to VIM.
Please suggest which is the best way I can do indentation to all the files in VIM.
Much simpler than scripting vim from the bash command line is to use vimscript from inside of vim (or perhaps a much simpler one-liner for scripting vim from the command line). I personally prefer using the arg list for all multi-file manipulation. For example:
:args ~/src/myproject/**/*.ttl | argdo execute "normal gg=G" | update
args sets the arglist, using wildcards (** will match the current directory as well as subdirectories)
| lets us run multiple commands on one line
argdo runs the following commands on each arg (it will swallow up the second |)
execute prevents normal from swallowing up the next pipe.
normal runs the following normal mode commands (what you were working with in the first place)
update is like :w, but only saves when the buffer is modified.
This :args ... | argdo ... | update pattern is very useful for any sort of project wide file manipulation (e.g. search and replace via %s/foo/bar/ge or setting uniform fileformat or fileencoding).
(other people prefer a similar pattern using the buffer list and :bufdo, but with the arg list I don't need to worry about closing current buffers or opening up new vim session.)
Open up a terminal. Type:
$ vim -w indentme.scr foo.c
Then, type this exactly (in command mode):
gg=G:wq
This will close vim, saving the process of indenting all lines in the file to a Vim script called indentme.scr.
Note: indentme.scr will contain a record of all key commands typed, so when you are done indenting the file, don't spend a lot of time using the arrow keys to look around the file, because this will lead to a much larger script and will severely slow down batch operations.
Now, in order to indent all the lines in a file, just type the following command:
$ vim -s indentme.scr unindented-file.c
Vim will flash open-shut (if you're on a fast computer and not editing a huge file), indenting all lines, then saving the file in-place.
Unfortunately, this will only work on one file at a time, but you can scale the functionality easily using sh's for loop:
for filename in *.ttl ; do
vim -s indentme.scr "$filename"
done
Note: This will save-over any file. Unless set bk is in your ~/.vimrc, don't expect a backup to be saved.
I went off of amphetamachine's solution. However, I needed to recursively search through multiple directories. Here's the solution that I used:
$ find . -type f -name '*.ttl' -exec vim -s indentme.scr "{}" \;
Taking reference from the above answers I would like to make this complete.
I will start from the scratch so that a beginner can understand.
Step-1
Install astyle (tool used for formatting ) by using the following command
Open up a terminal. Type:
sudo apt-get install astyle
Step-2 Make sure you have vim installed on your system.Run the below commands from the directory in which your code files are.The below command will create a script that we intend to run recursively so as to beautify each and every file in our directory.(as mentioned in the above answer)
vim -w indentme.scr foo.c
Step-3 Then, type this exactly (in command mode) and press enter
:%!astyle
Step-4Then type this exactly (in command mode) and press enter
:wq
Step-5 Last run this recursively by the following command:
find . -type f -name '*.cpp' -exec vim -s indentme.scr "{}" \;
All your cpp files will be formatted properly.

How can I open several files at once in Vim?

Is there a way to open all the files in a directory from within Vim? So a :command that would say in effect "Open all the files under /some/path into buffers".
Ideally, it would be great to open all the files under a dir recursively.
The command you are looking for is args:
For example:
:args /path_to_dir/*
will open all files in the directory
Why it doesn't work if I want to open all files ending with a certain extension?
I tried
:n ./**.cs
and opens only the files in the currenty directory.
I found the answer.The correct code is :n **/*.cs
For more information :h find
Did you try
:n /some/path/*
It will open all files in /some/path
I don't think it'll open file recursively though.
EDIT
Maybe using ** will open recursively as daf mentionned
A method that doesn't require messing with args is to put the list of files in a text file, and then use the :so command to run the commands in that file.
For example, if you want to open all the files that end in .php in a given directory, first create files.txt containing the list of files, prepended with whatever command you want to use to open them.
sp alpha.php
sp bravo.php
sp charlie.php
Then, within vim:
:so files.txt
If the list of files is large, it's relatively trivial to generate the files.txt file quickly, by redirecting the output of ls to a file, and then using a vim macro to prepend sp before each filename.
This obviously isn't as elegant as using the args and argdo commands, but those commands are also a lot more complicated.
There also might be a way to do this with a single command on the command line, but even after 16 years I still find vim programming to be strange and arcane.
Another way to open files recursively
find . -type f -exec vi {} \;
If you'd like to add to the argument list;
:arga what_you-d_like_to_add
see
:he arga
from/in vim for more information.

Resources