Vim Tips Wiki
(merge material and reword bits)
Line 11: Line 11:
 
|category2=
 
|category2=
 
}}
 
}}
  +
Often a file contains the name of a second file, and you would like to open the second file. Do that by putting the cursor on the file name and typing <tt>gf</tt>. This tip explains the details of <tt>gf</tt>.
  +
  +
==Go to file==
 
The following commands open the file name under the cursor:
 
The following commands open the file name under the cursor:
 
{| class="cleartable"
 
{| class="cleartable"
Line 19: Line 22:
 
|<tt><c-w>gf</tt> || open in a new tab (Ctrl-w <tt>gf</tt>)
 
|<tt><c-w>gf</tt> || open in a new tab (Ctrl-w <tt>gf</tt>)
 
|}
 
|}
  +
  +
We usually type <tt>gf</tt> in normal mode in which case Vim has to determine where the file name starts and ends. It does that by taking all characters matching the <tt>'isfname'</tt> option. Alternatively, you can visually select the file name, then type <tt>gf</tt> in which case Vim will use the selected text.
  +
  +
With the cursor on a file name, pressing Ctrl-w then <tt>f</tt> (or Ctrl-f) will open the file in a new window (after a horizontal split). If you want a vertical split, you could next type Ctrl-w <tt>L</tt> to move the window to the right. Or, you could map a key to perform a vertical "go to file" split (<tt>:vertical</tt> makes what follows split vertically; <tt>:wincmd</tt> is a command that is equivalent to pressing Ctrl-w):
 
<pre>
  +
:map <F8> :vertical wincmd f<CR>
 
</pre>
   
 
When writing a program, it is helpful to set the <tt>'path'</tt> option to list the directories with your include files. Then you can easily open an include file.
 
When writing a program, it is helpful to set the <tt>'path'</tt> option to list the directories with your include files. Then you can easily open an include file.
Line 26: Line 36:
 
You can return to the previous buffer using Ctrl-^ or Ctrl-o.
 
You can return to the previous buffer using Ctrl-^ or Ctrl-o.
   
==Rough merge in from 487==
+
===File name and line number===
  +
Instead of just a file name, you may have a name followed by a line number. For example, <tt>global.h:123</tt> indicates line 123 in file <tt>global.h</tt>. Instead of a colon, any whitespace and another delimiter character can separate the name and number; the delimiter must not be a character expected in a file name (the <tt>'isfname'</tt> option must not include the delimiter).
Often when editing a file in Vim, you may have a filename/line number pair such as "vim.h:1506" indicating a file you wish to open at the line number listed.
 
   
  +
On Windows, the default <tt>'isfname'</tt> includes a colon. If you do not use drive letters to identify files, you could remove the colon with the command:
The '''<tt>gF</tt>''' command will do this for you, although ':' is included in 'isfname' under Windows, so you'll need to get rid of it first with '''<tt>set isfname-=:</tt>'''
 
 
<pre>
*{{help|gF}}
 
 
set isfname-=:
*{{help|CTRL-W_F}} (same thing, but split the window for the new file)
 
 
</pre>
*{{help|CTRL-W_gF}} (same thing, but open a new tab for the new file)
 
  +
  +
The following commands open the file with the cursor on the specified line number:
  +
{| class="cleartable"
  +
|<tt>gF</tt> || open in the same window
  +
|-
  +
|<tt><c-w>F</tt> || open in a new window (Ctrl-w <tt>F</tt>)
  +
|-
  +
|<tt><c-w>gF</tt> || open in a new tab (Ctrl-w <tt>gF</tt>)
  +
|}
   
 
When such file-name/line number pairs are the result of compiling code, the following commands are also useful:
 
When such file-name/line number pairs are the result of compiling code, the following commands are also useful:
Line 39: Line 58:
 
*{{help|:cfile}}
 
*{{help|:cfile}}
   
 
The {{script|id=2184|text=file:line plugin}} allows you to use combinations of file name and line number, like <tt>global.h:123</tt>, as an argument to Vim. When you open ''file:line'', the script checks if ''file'' exists and ''line'' is a number. If so, Vim opens ''file'' at the correct ''line'' line number.
;Plugin
 
The {{script|id=2184|text=file:line plugin}} allows you to use combinations of file name and line number, like "vim.h:1506", as an argument to Vim.
 
   
 
==Names containing spaces==
When you open ''file:line'', the script checks if ''file'' exists and ''line'' is a number. If so, Vim opens ''file'' at the correct ''line'' line number.
 
 
With default settings, Vim regards spaces as delimiters (not part of a file name). That means you cannot type <tt>gf</tt> to open a file if the name contains a space character. However, you can visually select the name (including the spaces), then type <tt>gf</tt> to open the file. For example, you could position the cursor on the first character of the file name, then press <tt>v</tt> to start visual selection, then repeatedly press <tt>E</tt> to move to the end of the next WORD until the whole name is selected, then type <tt>gf</tt>.
   
  +
As an example on a Windows system, the following line may identify a file:
==Rough merge in from 226==
 
I use the command '<tt>gf</tt>' quite often. But with this command the current buffer is hidden. To avoid that I use the following mapping :
 
 
<pre>
 
<pre>
 
C:\Documents and Settings\My Name\My Documents\My file.txt
map gw <Esc>:sp %<CR> gf
 
 
</pre>
 
</pre>
   
  +
With the default settings, if you put the cursor on the "and" word then type <tt>gf</tt>, Vim will try to open a file called <tt>and</tt>. However, you can open the required file by selecting the whole name then typing <tt>gf</tt>. For example, type <tt>^v$be</tt> to select the name, then <tt>gf</tt> to open the file (<tt>^</tt> jumps to the first nonblank character; <tt>v</tt> enters visual mode; <tt>$</tt> jumps to end, which may include the end-of-line; <tt>b</tt> goes to beginning of word; <tt>e</tt> goes to end of word, which does not include the end-of-line).
With this mapping the file under the cursor is opened after a horizontal split.
 
   
  +
If you prefer the mouse, depending on your settings, you may be able to select the name with the mouse, then type <tt>gf</tt>. Before typing <tt>gf</tt>, check that you are in visual mode (if the status line shows <tt>--SELECT--</tt>, switch to visual mode by pressing Ctrl-g).
;Comments
 
The same operation can be done more reliably by
 
<pre>
 
function! SplitOpen()
 
let v:errmsg = ""
 
normal gf
 
if v:errmsg == ""
 
sbp
 
endif
 
endf
 
map gw <Esc>:call SplitOpen()<CR>
 
</pre>
 
   
  +
===Adjusting <tt>isfname</tt>===
----
 
 
To have a space (ASCII 32) considered as a valid character for a file name, add the following to your [[vimrc]]:
Or even more simply by "<tt>CTRL-W f</tt>".
 
 
----
 
Yes, <tt>CTRL-W f</tt> does this, but with the original idea you have a chance to make a little change, for example I prefer vertical split very often, but there is no hotkey for it in vim, so I use this idea and map:
 
 
<pre>
 
<pre>
  +
:set isfname+=32
:nn ^W^F :vsplit<CR>gf
 
 
</pre>
 
</pre>
   
  +
On Windows, another approach is to use the 8.3 short path name to avoid spaces. For example, the following tells Vim to look for files in the <tt>C:\Documents and Settings\My User Name\My Documents</tt> directory:
==Names containing spaces==
 
===Rough merge in from 985===
 
What are some quick ways to access files? Environment variables and the <tt>gf</tt> command.
 
 
Using the mouse to navigate to a directory, then clicking-on an icon or shortcut is too laborious and time consuming. Vim is designed to minimize mouse usage.
 
 
Instead of a directory, one could open a file which contains filenames to edit. Once your cursor is placed within a filename, the command "gf" will magically open it. (I memorize that by 'get file'.)
 
 
Some operating systems allow the use of the space character in specifying directories and files. Bad idea, for that practically breaks the use of gf.
 
 
Assuming that your username is "amen" and that you adhere to the convention of no-spaces in names, we will proceed with some examples, in your directory called "theory_e" and a file called "godel-relativity.txt".
 
 
In Windows XP, the full path would look something like this:<br>
 
<tt>C:/Documents and Settings/amen/My Documents/theory_e/godel-relativity.txt</tt>
 
 
Doing a <tt>gf</tt> on this mess will bring unpredictable results depending on where your cursor was placed on that line -- because it is not continguous. Now luckily that actually fit on one line. If there were subdirectories, that line will break past the edge, and again gf will malfunction.
 
 
Now gf is not buggy, but rather, the file specification is ugly. So a solution might be to create an environment variable (preferably in your _vimrc):
 
 
<pre>
 
<pre>
 
:set path+=C:\\DOCUME~1\\MYUSER~1\\MYDOCU~1
let $amen = 'C:/Documents and Settings/amen/My Documents'
 
 
</pre>
 
</pre>
   
 
Double backslashes are required in the <tt>:set</tt> command to get single backslashes in the value. Alternately, use forward slashes:
Note that the offending spaces are contained within quotes -- which is the saving grace. Now let's read our notes, somewhere say from drive D:
 
 
<pre>
 
<pre>
  +
:set path+=C:/DOCUME~1/MYUSER~1/MYDOCU~1
Kurt Godel constructed a model which was consistent with Einstein's
 
general theory of relativity in which the direction of time was not
 
unidirectional, but rather, circular. Einstein's critique is found in
 
$amen/theory_e/godel-relativity.txt (section 43 needs editing).
 
 
</pre>
 
</pre>
   
  +
===Using an environment variable===
Now doing a gf on that filename will open it. And notice the economy in style. If you move to another system where your user path is different, just change the assignment of $amen. Your text files need not be revised. For example, on your Unix machine, .vimrc might include this sane version:
 
  +
If you commonly use names with no spaces, but the files are in a directory with spaces, you may like to use the following approach. First, you can use Vim to define an environment variable to identify the directory that you will use, for example (for Windows):
 
<pre>
 
<pre>
 
:let $mydir = 'C:/Documents and Settings/My Name/My Documents'
let $amen = '/home/amen'
 
 
</pre>
 
</pre>
   
  +
Suppose you have a file containing a line like the following:
Generally, I prefer forward slashes when writing paths, to preserve multi-platform compatibility. So on a Windows machine which insists on back slashes, I use this conversion command often:
 
 
<pre>
 
<pre>
  +
My notes are in file $mydir/abc.txt which you can open with gf.
" Substitute back slash to forward SLASH.
 
command! -range Sslash <line1>,<line2>s;\\;/;g
 
 
</pre>
 
</pre>
   
  +
Assuming the file <tt>abc.txt</tt> exists in the <tt>$mydir</tt> directory, you can put the cursor on the name then type <tt>gf</tt> to open the file.
Thus :Sslash will work on a single line, or a specified range, e.g. :7,14Sslash for lines 7 through 14. Or better yet, just visualize an area, and then execute the command via ":" which brings up the implied range :'<,'> -- which can be automated by the following visual mapping,
 
<pre>
 
" Visualize the desired area, then hit ",s".
 
vmap ,s :Sslash<CR>
 
</pre>
 
   
  +
If you copy your files to another system using different directories, you can alter the definition of <tt>$mydir</tt>, for example:
;Comments
 
Or visual select filename and <tt>gf</tt>
 
 
===From original 299===
 
You may need to open a file that has a space in its name. One approach is to visually select the name (including its embedded spaces), then type <tt>gf</tt>. For example, you could position the cursor on the first character of the file name, then press <tt>v</tt> to start visual selection, then repeatedly press <tt>E</tt> to move to the end of the next WORD until the whole name is selected, then type <tt>gf</tt> to go to the file.
 
 
Another approach is to adjust the <tt>isfname</tt> option.
 
 
To have a space (ASCII 32) considered as a valid character for a file name, add the following to your [[vimrc]]:
 
 
<pre>
 
<pre>
 
let $mydir = '/home/myname'
:set isfname+=32
 
 
</pre>
 
</pre>
   
  +
The above used forward slashes for the path delimiter; that should work on all systems. On Windows, you could use backslashes instead, and you can mix back and forward slashes (for example, using backslashes in <tt>$mydir</tt> and forward slashes in <tt>$mydir/abc.txt</tt>).
On Dos/Windows (only), a further approach is to use the 8.3 form of the path to avoid spaces:
 
<pre>
 
:set path+=C:\\DOCUME~1\\MYUSER~1\\MYDOCU~1
 
</pre>
 
(or similar) in order to access <tt>C:\Documents and Settings\My User Name\My Documents</tt>. (Note that double backslashes are used here in the <tt>:set</tt> command to get single backslashes in the value. Alternately, ''forward'' slashes could have been used inside Vim.
 
   
 
==See also==
 
==See also==
Line 155: Line 123:
   
 
==Comments==
 
==Comments==
  +
{{todo}}
  +
*Need brief explanation <tt>'isfname'</tt>.
  +
*Need brief explanation of <tt>'path'</tt>: meanings of <tt>.</tt> and <tt>,,</tt>; how to include space in path.
  +
 
----
 
You can list the files in 'path' that match the name under the cursor with:
 
You can list the files in 'path' that match the name under the cursor with:
 
<pre>
 
<pre>
Line 171: Line 144:
 
--[[User:Fritzophrenic|Fritzophrenic]] 16:15, January 6, 2010 (UTC)
 
--[[User:Fritzophrenic|Fritzophrenic]] 16:15, January 6, 2010 (UTC)
 
:Thanks. I'm pretty ruthless these days and I have just done a "rough merge" in from the three you chose as duplicates (226, 487, 985), and I have replaced each of the merged-in tips with a redirect to here. I do it like that because it's easy, but also because it puts the whole tips (lightly massaged, but no content change) in the history on this page which sometimes helps in the future when checking what's happened. [[User:JohnBeckett|JohnBeckett]] 04:04, January 7, 2010 (UTC)
 
:Thanks. I'm pretty ruthless these days and I have just done a "rough merge" in from the three you chose as duplicates (226, 487, 985), and I have replaced each of the merged-in tips with a redirect to here. I do it like that because it's easy, but also because it puts the whole tips (lightly massaged, but no content change) in the history on this page which sometimes helps in the future when checking what's happened. [[User:JohnBeckett|JohnBeckett]] 04:04, January 7, 2010 (UTC)
  +
::I have now done some merging and have added some new bits. The pieces can be tweaked and moved to a better order in due course. [[User:JohnBeckett|JohnBeckett]] 09:38, January 7, 2010 (UTC)
  +
  +
===Removed===
  +
I have removed the following from the merged tip. This note is to explain my reasoning and invite correction if I've missed something. In a couple of days, all the comments can be removed. [[User:JohnBeckett|JohnBeckett]] 09:38, January 7, 2010 (UTC)
  +
  +
====SplitOpen====
 
The same operation can be done more reliably by
 
<pre>
 
function! SplitOpen()
 
let v:errmsg = ""
 
normal gf
 
if v:errmsg == ""
 
sbp
 
endif
 
endf
 
map gw <Esc>:call SplitOpen()<CR>
 
</pre>
  +
  +
::The above seems unwarranted: if the file exists, it works but leaves the cursor in the old window; if the file does not exist, the script bombs. Either way, it needs fixing to be bearable and I think that layering stuff on top of how Vim works is not helpful. [[User:JohnBeckett|JohnBeckett]] 09:38, January 7, 2010 (UTC)
  +
  +
====Using forward slashes====
 
Generally, I prefer forward slashes when writing paths, to preserve multi-platform compatibility. So on a Windows machine which insists on back slashes, I use this conversion command often:
  +
<pre>
 
" Substitute back slash to forward SLASH.
 
command! -range Sslash <line1>,<line2>s;\\;/;g
  +
</pre>
  +
 
Thus :Sslash will work on a single line, or a specified range, e.g. :7,14Sslash for lines 7 through 14. Or better yet, just visualize an area, and then execute the command via ":" which brings up the implied range :'<,'> -- which can be automated by the following visual mapping,
  +
<pre>
 
" Visualize the desired area, then hit ",s".
 
vmap ,s :Sslash<CR>
  +
</pre>
  +
  +
::The above is fine but it just clutters this tip. It might be somewhere else with a see also from here. [[User:JohnBeckett|JohnBeckett]] 09:38, January 7, 2010 (UTC)

Revision as of 09:38, 7 January 2010

Tip 299 Printable Monobook Previous Next

created 2002 · complexity basic · version 7.0


Often a file contains the name of a second file, and you would like to open the second file. Do that by putting the cursor on the file name and typing gf. This tip explains the details of gf.

Go to file

The following commands open the file name under the cursor:

gf open in the same window ("goto file")
<c-w>f open in a new window (Ctrl-w f)
<c-w>gf open in a new tab (Ctrl-w gf)

We usually type gf in normal mode in which case Vim has to determine where the file name starts and ends. It does that by taking all characters matching the 'isfname' option. Alternatively, you can visually select the file name, then type gf in which case Vim will use the selected text.

With the cursor on a file name, pressing Ctrl-w then f (or Ctrl-f) will open the file in a new window (after a horizontal split). If you want a vertical split, you could next type Ctrl-w L to move the window to the right. Or, you could map a key to perform a vertical "go to file" split (:vertical makes what follows split vertically; :wincmd is a command that is equivalent to pressing Ctrl-w):

:map <F8> :vertical wincmd f<CR>

When writing a program, it is helpful to set the 'path' option to list the directories with your include files. Then you can easily open an include file.

If there are several files in your 'path' that match the name under the cursor, gf opens the first, while 2gf opens the second, and 3gf opens the third, etc.

You can return to the previous buffer using Ctrl-^ or Ctrl-o.

File name and line number

Instead of just a file name, you may have a name followed by a line number. For example, global.h:123 indicates line 123 in file global.h. Instead of a colon, any whitespace and another delimiter character can separate the name and number; the delimiter must not be a character expected in a file name (the 'isfname' option must not include the delimiter).

On Windows, the default 'isfname' includes a colon. If you do not use drive letters to identify files, you could remove the colon with the command:

set isfname-=:

The following commands open the file with the cursor on the specified line number:

gF open in the same window
<c-w>F open in a new window (Ctrl-w F)
<c-w>gF open in a new tab (Ctrl-w gF)

When such file-name/line number pairs are the result of compiling code, the following commands are also useful:

The file:line plugin allows you to use combinations of file name and line number, like global.h:123, as an argument to Vim. When you open file:line, the script checks if file exists and line is a number. If so, Vim opens file at the correct line line number.

Names containing spaces

With default settings, Vim regards spaces as delimiters (not part of a file name). That means you cannot type gf to open a file if the name contains a space character. However, you can visually select the name (including the spaces), then type gf to open the file. For example, you could position the cursor on the first character of the file name, then press v to start visual selection, then repeatedly press E to move to the end of the next WORD until the whole name is selected, then type gf.

As an example on a Windows system, the following line may identify a file:

    C:\Documents and Settings\My Name\My Documents\My file.txt

With the default settings, if you put the cursor on the "and" word then type gf, Vim will try to open a file called and. However, you can open the required file by selecting the whole name then typing gf. For example, type ^v$be to select the name, then gf to open the file (^ jumps to the first nonblank character; v enters visual mode; $ jumps to end, which may include the end-of-line; b goes to beginning of word; e goes to end of word, which does not include the end-of-line).

If you prefer the mouse, depending on your settings, you may be able to select the name with the mouse, then type gf. Before typing gf, check that you are in visual mode (if the status line shows --SELECT--, switch to visual mode by pressing Ctrl-g).

Adjusting isfname

To have a space (ASCII 32) considered as a valid character for a file name, add the following to your vimrc:

:set isfname+=32

On Windows, another approach is to use the 8.3 short path name to avoid spaces. For example, the following tells Vim to look for files in the C:\Documents and Settings\My User Name\My Documents directory:

:set path+=C:\\DOCUME~1\\MYUSER~1\\MYDOCU~1

Double backslashes are required in the :set command to get single backslashes in the value. Alternately, use forward slashes:

:set path+=C:/DOCUME~1/MYUSER~1/MYDOCU~1

Using an environment variable

If you commonly use names with no spaces, but the files are in a directory with spaces, you may like to use the following approach. First, you can use Vim to define an environment variable to identify the directory that you will use, for example (for Windows):

:let $mydir = 'C:/Documents and Settings/My Name/My Documents'

Suppose you have a file containing a line like the following:

My notes are in file $mydir/abc.txt which you can open with gf.

Assuming the file abc.txt exists in the $mydir directory, you can put the cursor on the name then type gf to open the file.

If you copy your files to another system using different directories, you can alter the definition of $mydir, for example:

let $mydir = '/home/myname'

The above used forward slashes for the path delimiter; that should work on all systems. On Windows, you could use backslashes instead, and you can mix back and forward slashes (for example, using backslashes in $mydir and forward slashes in $mydir/abc.txt).

See also

References

Comments

 TO DO 

  • Need brief explanation 'isfname'.
  • Need brief explanation of 'path': meanings of . and ,,; how to include space in path.

You can list the files in 'path' that match the name under the cursor with:

:echo globpath(&path, expand('<cfile>'))

The plugin searchInRuntime overrides gf and CTRL-W_f to ask which file must be opened if several match. Alternatives for :sp and :vsp are also provided.

Note that if your path contains many directories or recursive searches, it can take a very long time to find all matches, and it might be better for you to just stop at the first file found.


I've made my opinion known regarding the "related tips" that John has linked to by being bold and just marking them for merge or moving them to "see also", but I don't know what to do with this one:

First, it needs a little work to handle escaped characters like %20 for spaces, etc. After this is done, I'm not sure whether it is separate enough of a concept for a new tip, or whether it should be merged as well. I'm leaning toward leaving it separate, but if not, we could add another section just below the one about paths with spaces. --Fritzophrenic 16:15, January 6, 2010 (UTC)

Thanks. I'm pretty ruthless these days and I have just done a "rough merge" in from the three you chose as duplicates (226, 487, 985), and I have replaced each of the merged-in tips with a redirect to here. I do it like that because it's easy, but also because it puts the whole tips (lightly massaged, but no content change) in the history on this page which sometimes helps in the future when checking what's happened. JohnBeckett 04:04, January 7, 2010 (UTC)
I have now done some merging and have added some new bits. The pieces can be tweaked and moved to a better order in due course. JohnBeckett 09:38, January 7, 2010 (UTC)

Removed

I have removed the following from the merged tip. This note is to explain my reasoning and invite correction if I've missed something. In a couple of days, all the comments can be removed. JohnBeckett 09:38, January 7, 2010 (UTC)

SplitOpen

The same operation can be done more reliably by

function! SplitOpen()
  let v:errmsg = ""
  normal gf
  if v:errmsg == ""
    sbp
  endif
endf
map gw <Esc>:call SplitOpen()<CR>
The above seems unwarranted: if the file exists, it works but leaves the cursor in the old window; if the file does not exist, the script bombs. Either way, it needs fixing to be bearable and I think that layering stuff on top of how Vim works is not helpful. JohnBeckett 09:38, January 7, 2010 (UTC)

Using forward slashes

Generally, I prefer forward slashes when writing paths, to preserve multi-platform compatibility. So on a Windows machine which insists on back slashes, I use this conversion command often:

" Substitute back slash to forward SLASH.
command! -range Sslash <line1>,<line2>s;\\;/;g

Thus :Sslash will work on a single line, or a specified range, e.g. :7,14Sslash for lines 7 through 14. Or better yet, just visualize an area, and then execute the command via ":" which brings up the implied range :'<,'> -- which can be automated by the following visual mapping,

" Visualize the desired area, then hit ",s".
vmap ,s :Sslash<CR>
The above is fine but it just clutters this tip. It might be somewhere else with a see also from here. JohnBeckett 09:38, January 7, 2010 (UTC)