Move File within Vim - vim

Is there a way to move a file within Vim? E.g. I opened a file foo/bar.txt in Vim. I know 2 ways to move this file:
First solution:
Delete the buffer with :bd bar.txt
Perform the move on the shell with mv foo/bar.txt foo/bar2.txt
Load the file in vim with :e foo/bar2.txt
Second solution:
Close Vim, so all buffer where closed.
Perform the move on the shell...
Start Vim and load the file.
But these two solutions are embarrassing. I know, there is a plugin for renaming files vim-enuch, but isn't there a Vim way for performing such basic functionality?

You could also use netrw (the default file explorer) rename functionality.
Open netrw with :E
Move your cursor to the line with the file you intend to rename, in this case bar.txt . You move to the file in question using h,j,k,l or you can search for it with / (e.g. /bar.txt)
Hit R. You will then be prompted for a new filepath. When done entering the filepath hit <CR>
Move your cursor to the new file and open it with <CR>
While this solution may not be as quick as using vim-eunch, it does allow you to see the project's structure as you rename the file. This will also allow you to move multiple files at once.
For further reading run :help netrw-move

There is no atomic way to move a file like that, but this should be close:
function! MoveFile(newspec)
let old = expand('%')
" could be improved:
if (old == a:newspec)
return 0
endif
exe 'sav' fnameescape(a:newspec)
call delete(old)
endfunction
command! -nargs=1 -complete=file -bar MoveFile call MoveFile('<args>')
Now you could say:
:MoveFile file2.txt
To rename to file2.txt
:MoveFile %.0
to move file2.txt to file2.txt.0

if you're in the bar.txt buffer:
:w bar2.txt
:!rm bar.txt
If bar2.txt already exists in the current directory, use :w!.

Related

Vifm. Edit file in opened gvim

I use Gvim to write code. And use vifm to make file management ( copy, move files, extract tar's ). Sometimes, when navigating in vifm i need to open some file to edit him. Using :e it opened vim in same window. Is there any way to open file to edit in already opened gvim program?
You can use Vim's client-server feature to send the :edit to the existing GVIM instance. In the terminal Vim / vifm, execute:
:!gvim --remote path/to/file
See :help remote.txt for details. You can also open the file in a new tab page with --remote-tab etc.
Partial solution/workaround (I'm using a mac fwiw):
In vfimrc, define
" yank current file path into the clipboard
nnoremap Cf :!echo -n %c:p | pbcopy %i<cr>
To copy filename and dir into system clipboard
Then in vifm, cursor over file and type
Cf
:!gvim "
<cmd-v>
to paste clipboard,
and finish expression with...
"
<enter>
and now that file should open in gvim. It worked for me

Show the list of the files inside the folder of the current file

Imagine I'm editing file, and I want to show the list of the files inside the folder who belongs the file I'm editing, to edit one of them.
How can I do that? Is there any way using FuzzyFinder?
Did you even read FuzzyFinder's documentation (:help fuzzyfinder)? Quickly opening nearby files is one of that plugin's main features.
Without installing anything, you can do:
:Ex[plore]
to open the netrw file tree. See :help netrw.
You can also do:
:e <Tab>
Add these lines to your ~/.vimrc to make command line completion even better:
set wildmenu
set wildmode=list:full
and read :help wildmenu and :help commandline-completion.
set autochdir is a useful option to add to your ~/.vimrc, by the way.
change vim current directory to current file's:
:cd %:h
then
FuzzyFinder can do what you want (pick and edit). (:FufFile) I have mapping :
nmap <Leader>ff :FufFile<cr>
NERDTree can do that as well.
Depends on what you mean by showing the file.
To include the list of files in the currently edited files, you can do something like:
:read !ls /path/to/file
(it can be shortened to :cd %:h | read !ls if you don't mind if vim changes it's current directory...)
If you want to pick another file to edit, I'd suggest to take a look at NerdTree plugin (here is a little intro). Or you can simply issue:
:cd %:h | e .

Create a new file in the directory of the open file in vim?

I find myself in the position where I want to create a new file in the same directory as the one that the open file is in. How do I create a new file in the directory of the open file in vim? Also, is there a a place where I can learn these things on my own? Googling didn't help.
From within Vim, new files are created like existing files are edited, via commands like :edit filename or :split filename. To persist them to disk, you need to (optionally type in contents and) persist them via :write.
Like a command prompt, Vim has a notion of current directory (:pwd lists it). All file paths are relative to it. You don't need to duplicate the path to your current file, there are some nice shortcuts for them: % refers to the current file, :h is a modifier for its directory, minus the file name (cp. :help filename-modifiers). So,
:e %:h/filename
:w
will create a new file named filename in the same directory as the currently open file, and write it.
Alternatively, some people like Vim to always change to the current file's directory. This can be configured by placing
:set autochdir
into your ~/.vimrc file (which is read on Vim startup). Then, above becomes simply
:e filename
:w
Finally, Vim has a great built-in :help. Learn to navigate and search it!
you should have a try with "nerdtree" plugin.
In the nerdtree window, you typed key m, and file operation choices will display to you
If you want to create a new file and also show it in the window next to your current file, you can try this:
:vsp newfile
The vsp stands for vertical split, and it splits the screen in half, one showing your current file, the other showing your new file (also works with just sp, which is a horizontal split).
Per #MartinLyne's comment above, this will create the file in the directory of the file in which you opened vim. To adjust for this, you can change the current working directory as follows:
:cd %:p:h
This command changes the current working directory to the directory of the active file, meaning that running the vsp command (or any of the commands above) will create the file in that directory.
I usually use:
:tabnew my-file
Then add some content and:
:w
It will create new tab with new file.
(I use Vim 8)
When you have opened vim in non existent location like
$ vim /etc/<some_folder/<next_folder>/file.cfg
then to create a new directory while being inside vim, just run in normal mode
:! mkdir -p /etc/<some_folder/<next_folder>
next save your doc as usual :w :x ZZ (whatever you like)
that's it
I'm quite late to the party, but another option is to open NERDtree with :E or :Explore (or its splitting alternatives :Vexplore/:Sexplore == :Vex/:Sex).
In NerdTree you can create a new file with %, and type the name. It will automatically open the file, and create it after you :w/save it.
This is for Gvim!
Enter this to see the current directory.
:cd
then change it with
:cd desktop/somefolder
then save or make new file there
:enew asd.cpp
now again see the file
:cd
With NERDtree
ma <FILENAME>
ma <DIRECTORY NAME> + /

How to create and open for editing a nonexistent file whose path is under the cursor in Vim?

I’m trying Vim for the first couple of hours with Ruby on Rails, and I’m loving it so far.
Specifically, the gf command is great, but I miss something:
If the file under the cursor does not exist yet, gf returns an error.
Is there a command to actually create and open the file if it does not exist?
Or, what is the most straightforward way to create it?
One can define a custom variant of the gf command that opens
a new buffer if the file under the cursor does not exist:
:noremap <leader>gf :e <cfile><cr>
where the :e command could be replaced with :tabe (to open
the buffer for the new file in a separate tab) or another
file-opening command.
It is also possible to just create a file with the name under the
cursor without opening it; see my answer to a similar question
“Create a file under the cursor in Vim”.
gf -> opens the file in a new tab
cf -> creates the file (if it doesn't exist) and opens it in new tab
nnoremap gf <C-W>gf
noremap <leader>cf :call CreateFile(expand("<cfile>"))<CR>
function! CreateFile(tfilename)
" complete filepath from the file where this is called
let newfilepath=expand('%:p:h') .'/'. expand(a:tfilename)
if filereadable(newfilepath)
echo "File already exists"
:norm gf
else
:execute "!touch ". expand(newfilepath)
echom "File created: ". expand(newfilepath)
:norm gf
endif
endfunction

Find a file (via recursive directory search) in Vim

Is there any way to search a directory recursively for a file (using wildcards when needed) in Vim? If not natively, is there a plugin that can handle this?
You can use wildcards with the :edit command. So,
:e **/test/Suite.java
will open test/Suite.java no matter where it is in the current directory hierarchy. This works with tab-completion so you can use [tab] to expand the wildcards before opening the file. See also the wildmode option for a way to browse through all possible extensions instead.
Another trick is to use
:r! find . -type f
to load a list of all files in the current directory into a buffer. Then you can use all the usual vim text manipulation tools to navigate/sort/trim the list, and CTRL+W gf to open the file under the cursor in a new pane.
There is a find command. If you add ** (see :help starstar) to your 'path' then you can search recursively:
:set path
will show you your current path, add ** by doing something like
:set path+=**
then you can just type
:find myfile.txt
and it opens magically!
If you add the set command to your .vimrc it'll make sure you can do recursive search in future. It doesn't seem to search dot directories (.ssh for example)
I'd recommend ctrlp.vim. It's a very good plugin, ideal to work inside large projects. It has search by file name or full path, regexp search, automatic detection of the project root (the one with the .git|hg|svn|bzr|_darcs folder), personalized file name exclusions, and many more.
Just press <c-p> and it will open a very intuitive pane where you can search what you want:
It's possible to select and open several files at once. It also accepts additional arbitrary commands, like jump to a certain line, string occurrence or any other Vim command.
Repo: https://github.com/kien/ctrlp.vim
vim as a builtin find command (:help find) but only open the first found file. However you can use this amazing plugin : FuzzyFinder which does everything you want and even more
You can browse the file system with :ex ., but I do not know how to search recursively (I am a Vim novice — I have been using it only ten years).
There are a few popular file browsers plug-ins:
NERD tree
Lusty explorer
vtreexplorer
See also this thread on SuperUser.
Command-T lets you find a file very fast just by typing some letters. You can also open the file in a new tab, but it need vim compiled with ruby support.
You can use ! to run shell commands :
:! find . -name *.xml
vim has bild in commands named grep, lgrep, vimgrep or lvimgrep that can do this
here is a tutorial on how to use them
http://vim.wikia.com/wiki/Find_in_files_within_Vim#Recursive_Search
you can also use an external command like find or grep from vim by executing it like this
:!find ...
Quickfix-like result browsing
Usage:
Find my.regex
Outcome:
a new tab opens
each line contains a relative path that matches a grep -E regex
hit:
<enter> or <C-w>gf to open the file on the current line in a new tab
gf to open the file on the current tab and lose the file list
Find all files instead:
Find
Alternative methods:
Gfind my.regex: only search for Git tracked files (git ls-files). Fugitive request: https://github.com/tpope/vim-fugitive/issues/132#issuecomment-200749743
Gtfind my.regex: like Gfind, but search from the git Top level instead of current directory
Locate somefile: locate version
Code:
function! Find(cmd)
let l:files = system(a:cmd)
if (l:files =~ '^\s*$')
echomsg 'No matching files.'
return
endif
tabedit
set filetype=filelist
set buftype=nofile
" TODO cannot open two such file lists with this. How to get a nice tab label then?
" http://superuser.com/questions/715928/vim-change-label-for-specific-tab
"file [filelist]
put =l:files
normal ggdd
nnoremap <buffer> <Enter> <C-W>gf
execute 'autocmd BufEnter <buffer> lcd ' . getcwd()
endfunction
command! -nargs=1 Find call Find("find . -iname '*'" . shellescape('<args>') . "'*'")
command! -nargs=1 Gfind call Find('git ls-files | grep -E ' . shellescape('<args>'))
command! -nargs=1 Gtfind call Find('git rev-parse --show-toplevel && git ls-files | grep -E ' . shellescape('<args>'))
command! -nargs=1 Locate call Find('locate ' . shellescape('<args>'))
Depending on your situation (that is, assuming the following command will find just a single file), perhaps use a command like:
:e `locate SomeUniqueFileName.java`
This will cause Vim to open, in the current tab (the e command) a file that is the result of running (in this example),
locate SomeUniqueFileName.java
Note that the magic here is the backticks around the command, which will convert the output from the shell command into text usable in the Vim command.
You don't need a plugin only for this function, below code snippet is enough.
function! FindFiles()
call inputsave()
let l:dir = input("Find file in: ", expand("%:p:h"), "dir")
call inputrestore()
if l:dir != ""
call inputsave()
let l:file = input("File name: ")
call inputrestore()
let l:nf = 'find '.l:dir.' -type f -iname '.l:file.' -exec grep -nH -m 1 ".*" {} \;'
lexpr system(l:nf)
endif
endfunction
nnoremap <silent> <leader>fo :call FindFiles()<CR>
Run:
:args `find . -name '*xml'`
Vim will run the shell command in backticks, put the list of files to arglist and open the first file.
Then you can use :args to view the arglist (i.e. list the files found) and :n and :N to navigate forward and bacwards through the files in arglist.
See https://vimhelp.org/editing.txt.html#%7Barglist%7D and https://vimhelp.org/editing.txt.html#backtick-expansion
You can find files recursively in your "path" with this plugin. It supports tab completion for the filename as well.
I am surprised no one mentioned Unite.vim yet.
Finding files (fuzzily or otherwise) is just the very tip of the iceberg of what it can do for a developer. It has built in support for ag, git, and a myriad of other programs/utilities/vim plugins. The learning curve can be a bit steep, but i cannot imagine my life without it. User base is big, and bugs are fixed immediately.
ag tool and corresponding Ag vim plugin solves this problem perfectly:
To find a file using some pattern use:
AgFile! pattern
It will open quickfix window with results where you can choose.
You can add vim keybinding to call this command using selected word as a pattern.
nnoremap <silent> <C-h> :AgFile! '<C-R><C-W>'<CR>
vnoremap <silent> <C-h> y :AgFile! '<C-R>"'<CR>

Resources