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 /.
Related
I move a lot between files from within Vim by highlighting a path and pressing the keys gf. I'm creating a makeshift Vim wiki for note-taking purposes, and I wanted to write only the beginning of a filename to be used as a link, because the way I have it, each filename begins with a unique identifier and so there would be no other matches, like so:
/notes/20190712*
I'm wondering if a simple asterisk wildcard could suffice for Vim to properly follow the incomplete filename, like how it autocompletes when :edit,:find or similar commands.
Vim's help alludes to some sort of expansion that takes place if it can't find a file, using something called includeexpr:
...used for the gf command if an unmodified file name can't be found.
Allows doing "gf" on the name after an 'include' statement.
Any help is appreciated. Thank you.
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
I'm trying to add an autocmd to vim that will execute whenever I open a file in a certain subdirectory and that sets the search path. Unfortunately path name expansion doesn't seem to work inside a set command.
Specifically I'd like to have a line like this in my vimrc:
setlocal path+=**;%:p:h
But this will just give me the literal value. Just calling expand() doesn't work either. Is there a way to get variable expansion to work here?
What about:
execute 'setlocal path +=**;' . fnameescape(expand('%:p:h'))
There's no need for the expansion of the current file's directory; just adding . to path will do. From the help:
To search relative to the directory of the current file, use:
:set path=.
Use
let &l:path.=(empty(&l:path)?(''):(',')).'**;'.escape(expand('%:p:h'), ',\*; ')
. This is much cleaner then using :execute 'setlocal path', especially knowing that fnameescape() was designed to escape paths for commands, not for options and I can say it is not really safe to use it here: it definitely is not going to escape comma and semicolon and add additional escape for space (one for escaping for :set, one for the option itself). (empty(&l:path)?(''):(',')) is here to imitate the behavior of set+=.
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.
Say, I have files foo.js and bar.css in my project. There is a ":find" command in vim, which find files, matching string. But this command, alas, has some limitations. For example, if I launch this way - "vim", or even this way - "vim ." - there's nothing to be find in js subdirectory. But if I launch vim this way - "vim js/any_file_other_than_foo.js", then calling ":find foo.js" works pretty well.
Since it is not intuitive (i'm working in the same directory, "pwd" returns the same path), my first question is - can anybody explain how to circumvent this issue? And, even broader, is there any way to type something like find foo - and open first file, which name matches pattern foo.
thanks in advance.
You could try
:e[dit] **/*foo* and then press 'tab' to move to the first match.
the ** is a directory globbing pattern, while * is character matching.
If you were so inclined, you could write a simple fuzzy finder command, for more information you can check out the vim tips wiki: http://vim.wikia.com/wiki/Find_files_in_subdirectories
Vim's :find works by searching each directory in the path variable (and ignores pwd). By default, it does not search recursively. That's why find is only working for you when you open a js file. The '.' in path refers to the directory for the current file -- not pwd.
You can change path to include your desired directories:
set path+=$PROJECT/js
See :help path.
One of the magic bits to use is to add ** to a path to search that path recursively:
" search recursively in my project
set path+=$PROJECT/**
" search recursively from the current file's directory
set path+=./**
See :help file-searching for more magic.
A nice plugin that accomplishes a similar effect is Command-T.
The Command-T plug-in provides an
extremely fast, intuitive mechanism
for opening files with a minimal
number of keystrokes. It's named
"Command-T" because it is inspired by
the "Go to File" window bound to
Command-T in TextMate.
Files are selected by typing
characters that appear in their paths,
and are ordered by an algorithm which
knows that characters that appear in
certain locations (for example,
immediately after a path separator)
should be given more weight.should be given more weight.
Here is a screencast of Command-T in action.