Vim ignore pathname in file completion - vim

Let's say I'm in /tmp and I have two files open in vim: test.txt and tmpfile.txt. Now I want to remove the tmpfile.txt buffer. I type :bd tmTAB. The behavior I want is for it to autocomplete tmpfile.txt; the behavior I get is a list of tmpfile.txt and /tmp/test.log, as it's autocompleting on the directory name as well as the filename. How can I make vim behave like I want?

Use ^tm instead to match at the beginning of the file name. (You have to be in /tmp for this to work so that the relative path is just the filename.)

That is not possible, the list comes from what's on the buffer list, not from your local path, you could be at any place (:pwd), it doesn't matter, when you press tab the result comes from the in memory list, thats why /tmp appears because if you're on /tmp, /tmp shouldn't appear again.
if you look at :help :bd it takes bufname as param, not fname as :badd

Related

Make VIM to consider current folder the root

I already know how to quit Vim, now I'm wondering is it possible anyhow to force Vim search '/somedir/file.js' in current directory when you press gf, as if it were './somedir/file.js'?
UPD: There's question how to set path in general, but it doesn't help to make /myfolder/ pointed to some certain folder I want. /myfolder/ is always absolute path to the root of current volume.
Vim counts filenames beginning with / as file system root always, as
you observed. If that wasn't the case, of if 'isf' (the option that
controls what is considered file name) accepted a regex, this would be
easier to solve. But if you remove / from 'isf' then no slashes are
considered part of a file name anymore.
The only solution to this I can think of is using the visual mode for
gf. As you may know, if you have text selected visually and use gf
then the visual selection will be considered, instead of the 'isf'
match. Then all we need to do is to visually select the file name under
cursor excluding a possible leading /. This can be solved in a map, if
you don't mind messing your previous search:
nnoremap <silent> gf :let #/ = substitute(expand('<cfile>'), '^/', '', '')
\ <bar>normal gngf<cr>
This overwrites your gf to set the search to the filename under cursor
(expand()), minus leading slash if any (substitute()) and then run
the normal commands gn which selects the match and finally the
original gf.
If you want to save your previous search and restore, you can easily
create a function to wrap this all. Note that I also wrote this is two
lines just because I'm a declared enemy of long lines. But if you just
want to test it remove the \ and write in a single line.
Now your gf will interpret /file as file. Thus if you're on the
correcty directory this will work. If you need to search in a different
directory, the option you're looking for is 'path', or 'pa' for
short. You can give a list of directories to search. Much like Unix
shell's $PATH. Separated by commas. From the help (be sure to read the
rest yourself, with :h 'pa):
This is a list of directories which will be searched when using the
gf, [f, ]f, ^Wf, :find, :sfind, :tabfind and other
commands, provided that the file being searched for has a relative
path (not starting with "/", "./" or "../"). The directories in the
'path' option may be relative or absolute.
In conclusion, to use this in your project, set your 'path' if needed
as you wish and enable this map. Or run it all automatically in a
:autocmd or something similar. You aren't changing the root of the
project as you initially suggested, but you're kind of emulating this by
including the desired directory in 'path' and then forcing gf to
ignore the leading /.

How to easily delete swap file placed in another directory (vim)?

I had a session with 7 files opened in vim. After accidental crash and reloading the session each file gives E325: ATTENTION explaining that the files are newer than swap ones! I don't remember how these files become newer that the original swap ones, but for now it doesn't matter, because I want to learn how to handle this case.
I think, the solution would be simple if swap files was placed along the files itself (eg .filename.swp next to filename). Because I could remove it just by :!rm .%.swp.
However I changed the default directory of swap files, which is now set to directory=~/.vim/tmp/swp//. So the question is how can I get the full pathname to the swap file. For example:
vim /home/timur/code/src/project/main.go
E325: ATTENTION
...
Swap file "~/.vim/tmp/swp//%home%timur%code%src%project%main.go.swp" already exists!
[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort
E or R
After I opened the buffer I want to type something like this:
:remove *swapname*
or using a shortcut:
<leader>rw
I've read the docs and found the command to show current swap file name: :swapname. But it seems the output name isn't fit to passing it into rm command, because there is additional slash before the swap name. For example:
Actual file:
/home/timur/.vim/tmp/swp/%home%timur%code%own%src%file
The output of :swapname (adds odd slash before swap name)
/home/timur/.vim/tmp/swp//%home%timur%code%own%src%file.swp
^ ???
To put it simple: how to get direct/explicit path to swap file of current buffer?
Inspired by issue 355, here is your mapping
nnoremap <silent> <Leader>rw :call DeleteSwapFile()<CR>
function! DeleteSwapFile()
redir => s:a
exe ':sil sw'
redir end
let b:swapname = s:a[1:]
call delete(b:swapname)
endfunction
:h redir
If you don't mind solving the problem using a vim plugin try Recover.vim plugin.
When opening a new file, it checks if a swapfile is already present.
If so gives two additionals options:
[D]elete: delete the swapfile (i use this option very rarely)
D(i)ff: compare the recover version of the file and the current version. If they are the same it asks you if you want to delete the swap file. If they are not the same open a vimdiff session between to visually compare the differences.
Really a must have.

How to get the value of the current swap directory in vimscript?

You can set a list of directories for vim to use for the swapfile (with it defaulting to the first one it can find) with:
set directory=~/tmp,~/var/tmp,/var/tmp,/tmp
I want to know which directory vim has chosen for its swapfile so I can stick some temp data in there.
Parsing &directory and looping through the values seems like a waste when vim should have already figured that out.
The :swapname command will tell you which swapfile is used for the current buffer. You need to use :redir => varname to capture the output and store it in a variable.
I think the "used" directory is not saved somewhere by vim, like a variable or something. It could be different from buffer to buffer. (from file to file).
e.g.
you have a non-root user. say kent, his directory setting is:
set directory=.,~/tmp,/var/tmp,/tmp
now kent opens /etc/host.conf in his vim, and editing. the first .(dot) means current dir. obviously kent cannot write file to /etc, so take the 2nd ~/tmp, but kent doesn't have tmp under his home, so next, /var/tmp is used.
if kent opens a file under his HOME, or under /tmp, for example, the .(dot) would be used. And note that the dot for different files are different.
kent can open many files in buffers, so it is hard to say, which dir would be used for swap files.
so the swapfile - dir is not fixed to a directory. you should check it based on the buffer/file.
If you do this often, I suggest to write a function:
function! SwapDirectoryForCurrentFile()
redir => filename
silent! swapname
redir end
return fnamemodify(filename, ":h")
endfunction

Supply a path for file editing in VIM?

Is there a way to set a PATH-like sequence of directories to search for files in vim? My project has C files split across many directories, and it would be nice to jump back and forth without remembering the full path each time.
For instance, if I have:
platform/drivers/uart.c
ui/display/menu.c
cpu/registers/regs.h
I would like to be able to set PATH to "platform/drivers:ui/display:cpu/registers". Then when I want to switch to a file, I can just type:
:e uart.c
instead of
:e platform/drivers/uart.c
I understand that I can change the working directory, but then I have to type
:e ../../ui/display/menu.c
to get to another directory.
Alternatively, is there a better way to navigate a project like this than using :edit?
There is, and it's called path. The way you use path is with the :find command: :find menu.c would search for menu.c in the directories in path and edit it. There are other commands that use path, like :sfind that opens the found file in a new split. See the documentation of path for details and other commands that use it.
Another thing that may help you find your files is the **-wildcard that can expand to any directory path. For example :edit **/menu.c will look for menu.c in subdirectories, so you don't have remember and type the full path.

In Vim, what is the "alternate file"?

I just ran :help registers in Vim and noticed that # 'contains the name of the alternate file'.
I have seen an example for renaming files that goes like this:
" Save the current file, foo.txt, as bar.txt
:w bar.txt
" Start editing bar.txt
:e#
So apparently in that case, the file you just saved out is the "alternate file."
Can someone give me a more general definition for the "alternate file" and what else you might use it for?
The alternate file is the file that was last edited in the current window. Actually when you use some command to open a new buffer, if the buffer that was displayed had a filename associated with it, that filename is recorded as alternate file name.
See :help alternate-file.
Very useful for...
Pasting in the name of a file I've just been looking at into the current file.
You can use <C-R># for this in insert mode or "#p in normal mode.
Not that useful for...
Jumping back and forth between two files. It does the job very well, but this is just something I don't generally need to do.
Even in the example given, I'd probably use:saveas bar.txt instead.
An Example:
Say if you're doing a bit of C programming and want to call some function. You can't remember the name of the function, so you place a mark on your current location mA and jump into several different files using tags or grep to find out where the function is declared and what it's actually called.
Ah - found it. You can copy the name and return to the mark yiw'A
Uh-oh - we also need to #include the file! Easy - just use the alternate file name register to paste the file name in... Gi#include"<C-R>#"
Be pleased that you've avoided the distraction of having to go back to the function's declaration and copy out the file name via :let #"=#% or something similar.
What I'd rather do when jumping between files:
When editing two files, it's probably easier to split them, so you can keep both on screen at the same time. If I'm editing 2 files I'll usually be comparing them in some way.
Usually I'm interested in 1-3 files (any more and I get confused). I'll often jump into or directly open many other files. Marking the interesting files, or traversing the jump list is usually the way to get around in this case.
If you're editing C/C++ where you're switching between a file and it's header, use a plugin! It will be much more convenient.
I use it in the buffer context to return to the last buffer that I was editing
vim foo bar
:n
:e#
will take you back to foo in that case
I 've always interpreted the "alternate file" as being the "previous file", so it is an handy way to jump back to the buffer you were editing.

Resources