Vim netrw - Explore when modified without split - vim

I've opened a file and modified it - now I want to do :Explore without splitting.
It splits - because I have an unsaved buffer. By default this is nice, becasuse Vim generally doesn't allow to switch files, until you do something with the modified buffer (save or discard changes).
But I have set hidden option, so I can jump from buffer to buffer, switch files and everything - and save or not when I feel I want to. It seems Netrw doesn't follow this policy. How could I help it?
One way I know of is to map netrw explore to save & explore, but I'm not sure if autowriting is a good way of doing things... I am actually using other autowriting settings now, but I was just rethinking to maybe get rid of them.

So here is the function, that does just that:
function! ExploreWithHidden()
let s:cw = getcwd()
lcd %:p:h
enew
Explore
cd `=s:cw`
endfunction
Seems to work like expected.

You could use :Texplore instead. This is the same as explore except in a new tab (and will have no splits).
:h Texplore
Another thing you could do is use :lcd %:p:h to change the current working directory to the directory of the file. Then use :enew to create another buffer then open explore. (Make sure hidden is on if the buffer is modified)
:command! BExplore :lcd %:p:h | enew | Explore
To run the command use :BExplore.
The old buffer will be sitting in the background and the explore window is pointing at the directory the file was in.

You could just upgrade your netrw -- its up to v153s at http://www.drchip.org/astronaut/vim/index.html#NETRW, and it does avoid the split if the modified buffer is hidden.

tpope's vim-vinegar operates like this. It maps - to Explore the current file's directory. (That's the same key netrw uses to go up one directory.) It uses the current window instead of splitting.
When the current file is modified:
If you have 'hidden' set, it will not split and Explore from the current window.
If you do not have 'hidden' set, it will issue an error and do nothing.

Related

How to create a new separate buffer list in vim?

There are some occasions that I wanted to open several files to be references and didn't want them to mess up my current buffer list. I have tried :new, sp, vs, and :tabnew, however, the new opened files are always kept in my current buffer list. Are there a way to create a brand new buffer list in order to keep these opened files separately? So, I could close these files entirely, whenever I didn't need to see them anymore, by using 1,100bd. I have been googling it but still no luck.
You can try this plugin: vim-ctrlspace.
From README.md of mentioned plugin:
The answer are tabs – a secret weapon of Vim-CtrlSpace. Each tab holds
a separate list of buffers. And this is something very different when
compared to plain Vim. Tabs powered by the plugin can be seen as piles
of documents on the desk.
With tabs you can, for example:
group related buffers
extract to other tabs
name them accordingly
move or copy them
Tabs usage in Vim-CtrlSpace is quite more extensive than in Vim. This
is because they serve mainly as independent buffer lists, so you are
likely to have plenty of them. Tabs can be accessed and managed within
Tab List.
All your buffers, tabs, and tab layouts can be persisted as a
workspace. It's like taking a picture of your desk with an instant
camera. You can save multiple workspaces per project with Workspace
List.
Try using the argument list. See :help :args and surrounding sections. If all your reference files (and only those) are in your arg list, you could :argdo bd to get rid of them all. There are local arg lists too, if you are already using the global list.
Disclaimer: Using the plugin is almost certainly a more robust solution as I made this myself and I'm relatively new to vim. But this is at least a good exercise in the uses of quickfix lists.
My Answer:
You could use quickfix error lists as file lists. see :help quickfix for full documentation. Here is my work flow for when I want to go through all the files that differ from master (using git).
vim to open vim in the directory you are working on.
new to open a new buffer
read ! git diff --name-only master to paste the output of my bash command into the new buffer. You can run any command or manually enter a file list here. You may want to clean it a little by removing any blank lines.
w! /tmp/quickfix.txt to create a file name we can use later.
set errorformat+=%f to change the errorformat to accept vanilla lists of file paths. see :help errorformat for more details on that.
cfile /tmp/quickfix.txt to read the list of files and create a quickfix "error" list using the new errorformat.
set errorformat-="%f" (optional) this removes the added errorformat to make sure you're not messing with any other use of errorformat, like for a vimgrep.
Now you can use quickfix options to move between files. :copen to open an interactive list and :cnext/:cprevious to cycle them. You can also have multiple lists at once. I use :colder to go back to previous lists. You should be familiar with this if you use any grep commands in vim.
These are just the manual steps. You can make a function that does all this in one go or any part that you need. Here's what I'm using.
function! LoadQuickfixFileList(filename)
set errorformat+=%f
execute "cfile ".a:filename
set errorformat-=%f
endfunction
function! WriteBufferToQuickFixFileList(filename)
call writefile(getbufline(bufnr(bufname("%")), 0, "$"), a:filename)
endfunction
function! GitDiffNameOnlyMaster()
execute "new"
execute "read ! git diff --name-only master"
execute "normal! ggdd"
call WriteBufferToQuickFixFileList("/tmp/quickfix.txt")
call LoadQuickfixFileList("/tmp/quickfix.txt")
endfunction
nnoremap <silent> <leader>cgd :call GitDiffNameOnlyMaster()<CR>
nnoremap <silent> <leader>cw :call WriteBufferToQuickFixFileList("/tmp/quickfix.txt")<CR>
nnoremap <silent> <leader>cf :call LoadQuickfixFileList("/tmp/quickfix.txt")<CR>
<leader>cgd does the whole thing for git diff --name-only master. If I make a list of files in a new buffer myself, I can use <leader>cw to write it to /tmp/quickfix.txt. Once I've done that or if I create a /tmp/quickfix.txt file myself in another way I use <leader>cf to load that file.

How can I delete the current file in vim?

How can I delete from the disk the current open file from within vim? Would be nice to also close the buffer.
I see you can use NERDTree for that, but I don't use this plugin.
Using an external tool such as rm(1) is fine, but Vim also has its own delete() function for deleting files. This has the advantage of being portable.
:call delete(expand('%'))
An alternative way of expressing this is :call delete(#%), which uses the % (current file) register (tip by #accolade).
To completely purge the current buffer, both the file representation on disk and the Vim buffer, append :bdelete:
:call delete(expand('%')) | bdelete!
You'll probably want to map this according to your preferences.
Take a look at Delete files with a Vim command. The Comments section should have what you're looking for:
Basically, Rm will delete the current file; RM will delete the current file and quit the buffer (without saving) in one go.
Alternatively, you could just issue a shell command to remove the current file:
:!rm %
Sometimes a plugin can be an attractive solution even for a simple problem. In this case we're lucky as there is eunuch.vim by the almighty Tim Pope.
In its own words eunuch.vim provides
Vim sugar for the UNIX shell commands that need it the most. Delete or rename a buffer and the underlying file at the same time. Load a find or a locate into the quickfix list. And so on.
Perfect. It has what we need, plus some additional tools if we're on a UNIX system.
The command you are looking for is
:Remove!
Again, remap it if you need it a lot, e.g. :nnoremap <Leader>rm :Remove!<CR>.
I like being able to delete files from within vim, but I am also paranoid about accidentally deleting important work that, for one reason or another, is not yet under version control. I find it useful to combine the previous information from #glts and #accolade with this answer on how to use the confirm command to prompt before quitting vim.
Putting these together, I added a function to my ~/.vimrc, which prompts before deleting the file and closing the buffer, and mapped it to a key combination:
nnoremap <Leader>d. :call DeleteFileAndCloseBuffer()
fun! DeleteFileAndCloseBuffer()
let choice = confirm("Delete file and close buffer?", "&Do it!\n&Nonono", 1)
if choice == 1 | call delete(expand('%:p')) | q! | endif
endfun
If you are one keystroke less paranoid than I am, you can append <CR> to the first line
nnoremap <Leader>d. :call DeleteFileAndCloseBuffer()<CR>
and only have to press return once.
You can do it with two steps:
save as a new file
:w newfilename
delete the old file
! rm oldfilename
This may be an unpopular opinion but your file tree explorer (Netrw/NerdTree) is going to be the simplest and safest way to delete a file. Even if OP is not using NerdTree, the in-built plugin Netrw will work just as well.

closing pending vim windows to open

I know that I can close all opened buffers in vim by :qall.
I want to close event to pending opening buffers.
I have problem while reviewing my changes in P4 sandbox. When I have changes in multiple files and I try to review my code with "P4 diff" and set my P4DIFF to vimdiff.
It opens one by one vimdiff of all changed files. Now if I have 10 opened files and after reviewing 2 files I want to close diff for remaining 8 files. How can I do that?
Thanks,
This sounds like a job for hastily learnt Vimscript!
Particularly, the :bufdo, if, and match statements!
Try out the following:
:bufdo if match(expand("%"), ".vim") >= 0 | bw | endif
bw is for buffer wipe in Ex-mode (the : operator)
expand("%") returns the name of the current buffer
match(string, pattern) finds the index of a pattern in string
|'s separate lines if you're in Ex-mode
This matches buffers that contain .vim in their filenames and closes those buffers.
I'm guessing if these are temp buffers that are fed into vimdiff, they wouldn't have file names to begin with. Maybe you can use bufnr(".") to output the number of the current buffer. Then you can close all buffers past or before a certain number.
You can probably do even more buffer manipulation with certain plugins. I've been considering adopting one of the following three plugins that help manage plugins:
LustyExplorer
FuzzyFinder
minibufexpl
I can't speak for any merits, but I've heard them mentioned several times over the internet and on IRC.
I'm assuming you open vim with a number of arguments (known as... the argument list).
You should probably reset it:
:args %
You can also selectively manage the list (:argdelete). More information: :he arglist
DISCLAIMER: I've not used perforce, so I've had to make an assumption: that when multiple files have uncommitted changes, it will behave like a lot of VCS's and run the configured diff command (in this case, vimdiff) on each changed file in turn (I'm thinking this is what you meant by "opens one by one vimdiff of all changed files").
If this is the case, then vim won't have any references to any of the remaining files when viewing the changes for any particular file, so no amount of trickery within a single vim session is going to help you.
If you are willing to change your workflow at all, you may be able to do something with this vim script I found: http://www.vim.org/scripts/script.php?script_id=240
It claims to be modelled after the P4 GUI, so hopefully could fit neatly into your usage. From the overview of the script, it sounds like it should be able to show you a summary of which files have changed and allow you to view the changes.
If none of this is suitable for you, you could always try the old favourite Ctrl-C immediately after closing a vimdiff session for a file.
This is a bad hack but putting it here as no other answers worked for me.
Add "qall" without qoutes on top of your .vimrc .
:e ~/.vimrc
:source ~/.vimrc
:q
All files will close automatically after opening.
Then open vimrc in emacs or sed and remove qall.

GVim - How to handle multiple files

Sorry to ask such a novice question but I am looking for a way to handle multiple files. I dont want to type huge file paths to open every file using :tabnew and :e commands
Fuzzy Finder is a handy plugin to quickly find and open files.
Basically you have to only type a few letters like test and you'll get a pop-up menu to open in your current path :
footest.c
bartest.h
footest.h
...
It is a bit slow when used on NFS but it is useful if you don't want to type long path and file names.
Alternatively if you don't want to use any plugin, by default gvim/vim includes a file browser called netrw.
To start it, just type :e . you'll get the content of your current directory, you can then navigate through the directory structure quite easily. (There is even commands to delete, rename, etc like a standard file explorer)
:help netrwfor more information.
A couple of tips that you might be interested in:
You can configure Vim so that the
current directory "follows" the
directory of the file you are
currently editing. That way you can
edit another file from the same
directory without having to type the
full path. This can be achieved by
putting either set autochdir or
autocmd BufEnter * lcd %:p:h in
your .vimrc
You can use wildcards with tab
completion. e.g. to edit
a_file_with_a_long_name.txt you could
do :e a*long and then press
Tab followed by
Return.
Usually, vim supports buffers for that. Use :badd to add buffer, :bdelete to remove it and :ls (or :buffers) to list all opened buffers. I believe, GVim supports these features too.
For example, if you wanna edit all .rb files in your app/controllers/pages dir (in the case of Rails project), you type vim app/controllers/pages/*.rb in your terminal and then edit the first file (buffer) in the vim window. When you've done with all changes, save changes as usual with :w (note: do not use q! option - this will close all your buffers you've opened) and then use :bn<tab> (or fully, :bnext) or :bprevious to switch to the next file (buffer). When you run :bnext on the last buffer, you'll be dropped to the first one.
You can open a directory in Vim, search for the file o directory you are looking for with '/' and type [enter] to open it.

How do I close a single buffer (out of many) in Vim?

I open several files in Vim by, for example, running
vim a/*.php
which opens 23 files.
I then make my edit and run the following twice
:q
which closes all my buffers.
How can you close only one buffer in Vim?
A word of caution: “the w in bw does not stand for write but for wipeout!”
More from manuals:
:bd
Unload buffer [N] (default: current
buffer) and delete it from
the buffer list. If the buffer was changed, this fails,
unless when [!] is specified, in which case changes are
lost.
The file remains unaffected.
If you know what you’re doing, you can also use :bw
:bw
Like |:bdelete|, but really delete the
buffer.
If this isn't made obvious by the the previous answers:
:bd will close the current buffer. If you don't want to grab the buffer list.
Check your buffer id using
:buffers
you will see list of buffers there like
1 a.php
2 b.php
3 c.php
if you want to remove b.php from buffer
:2bw
if you want to remove/close all from buffers
:1,3bw
Rather than browse the ouput of the :ls command and delete (unload, wipe..) a buffer by specifying its number, I find that using file names is often more effective.
For instance, after I opened a couple of .txt file to refresh my memories of some fine point.. copy and paste a few lines of text to use as a template of sorts.. etc. I would type the following:
:bd txt <Tab>
Note that the matching string does not have to be at the start of the file name.
The above displays the list of file names that match 'txt' at the bottom of the screen and keeps the :bd command I initially typed untouched, ready to be completed.
Here's an example:
doc1.txt doc2.txt
:bd txt
I could backspace over the 'txt' bit and type in the file name I wish to delete, but where this becomes really convenient is that I don't have to: if I hit the Tab key a second time, Vim automatically completes my command with the first match:
:bd doc1.txt
If I want to get rid of this particular buffer I just need to hit Enter.
And if the buffer I want to delete happens to be the second (third.. etc.) match, I only need to keep hitting the Tab key to make my :bd command cycle through the list of matches.
Naturally, this method can also be used to switch to a given buffer via such commands as :b.. :sb.. etc.
This approach is particularly useful when the 'hidden' Vim option is set, because the buffer list can quickly become quite large, covering several screens, and making it difficult to spot the particular buffer I am looking for.
To make the most of this feature, it's probably best to read the following Vim help file and tweak the behavior of Tab command-line completion accordingly so that it best suits your workflow:
:help wildmode
The behavior I described above results from the following setting, which I chose for consistency's sake in order to emulate bash completion:
:set wildmode=list:longest,full
As opposed to using buffer numbers, the merit of this approach is that I usually remember at least part of a given file name letting me target the buffer directly rather than having to first look up its number via the :ls command.
Use:
:ls - to list buffers
:bd#n - to close buffer where #n is the buffer number (use ls to get it)
Examples:
to delete buffer 2:
:bd2
You can map next and previous to function keys too, making cycling through buffers a breeze
map <F2> :bprevious<CR>
map <F3> :bnext<CR>
from my vimrc
Close buffer without closing the window
If you want to close a buffer without destroying your window layout (current layout based on splits), you can use a Plugin like bbye. Based on this, you can just use
:Bdelete (instead of :bdelete)
:Bwipeout (instead of :bwipeout)
Or just create a mapping in your .vimrc for easier access like
:nnoremap <Leader>q :Bdelete<CR>
Advantage over vim's :bdelete and :bwipeout
From the plugin's documentation:
Close and remove the buffer.
Show another file in that window.
Show an empty file if you've got no other files open.
Do not leave useless [no file] buffers if you decide to edit another file in that window.
Work even if a file's open in multiple windows.
Work a-okay with various buffer explorers and tabbars.
:bdelete vs :bwipeout
From the plugin's documentation:
Vim has two commands for closing a buffer: :bdelete and :bwipeout. The former removes the file from the buffer list, clears its options, variables and mappings. However, it remains in the jumplist, so Ctrl-o takes you back and reopens the file. If that's not what you want, use :bwipeout or Bbye's equivalent :Bwipeout where you would've used :bdelete.
How about
vim -O a a
That way you can edit a single file on your left and navigate the whole dir on your right...
Just a thought, not the solution...
[EDIT: this was a stupid suggestion from a time I did not know Vim well enough. Please don't use tabs instead of buffers; tabs are Vim's "window layouts"]
Maybe switch to using tabs?
vim -p a/*.php opens the same files in tabs
gt and gT switch tabs back and forth
:q closes only the current tab
:qa closes everything and exits
:tabo closes everything but the current tab
Those using a buffer or tree navigation plugin, like Buffergator or NERDTree, will need to toggle these splits before destroying the current buffer - else you'll send your splits into wonkyville
I use:
"" Buffer Navigation
" Toggle left sidebar: NERDTree and BufferGator
fu! UiToggle()
let b = bufnr("%")
execute "NERDTreeToggle | BuffergatorToggle"
execute ( bufwinnr(b) . "wincmd w" )
execute ":set number!"
endf
map <silent> <Leader>w <esc>:call UiToggle()<cr>
Where "NERDTreeToggle" in that list is the same as typing :NERDTreeToggle. You can modify this function to integrate with your own configuration.

Resources