24

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?

ib.
  • 27,830
  • 11
  • 80
  • 100
demental
  • 1,444
  • 13
  • 25

3 Answers3

24

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”.

ib.
  • 27,830
  • 11
  • 80
  • 100
  • 7
    `:e ` is enough for occasional usage, since `` grabs the same filename that would be chosen by `gf` – jpaugh Jul 14 '18 at 02:27
  • Doesnt work for me - I do have my files nested in subfolders. And sometimes I want to create a file in a subfolder from a file that is already in a subfolder. Is that a limitation? I typed that exact command (both the solution and the comment, I tried), and I also sourced my vimrc. It just says "Can't find file foo/bar.txt in path" – muuh Dec 24 '19 at 09:43
  • Is there anything to be said against skipping the ``? I.e.: `:map gf :e `? – Bernhard Wagner Apr 22 '20 at 10:19
  • 1
    @BernhardWagner: Just that it will shadow the original `gf` mapping. Prefixing mappings with a non-conflicting leader key (see `:help mapleader`) is one of the recommended ways to avoid conflicts with existing mappings. However, if shadowing the built-in mapping is what you want, then, of course, your mapping should not use the leader. – ib. Apr 23 '20 at 06:25
2

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
alnavegante
  • 21
  • 1
  • 2
1
nnoremap <silent> gf :call JumpOrCreateFile()<CR>


function! JumpOrCreateFile()
 " Get the filename under the cursor
 let filename = expand("<cfile>")

 " Expand the tilde in the file path
 let expanded_filename = expand(filename)

 " Check if the file path starts with "./"
 if expanded_filename =~# '^\.\/'
   " Get the current directory of the editing file
   let current_directory = expand('%:p:h')

   " Create the full path by appending the relative file path
   let expanded_filename = current_directory . '/' . expanded_filename
 endif

 " Check if the file exists
 if !filereadable(expanded_filename)
   " Prompt the user for file creation with the full path
   let choice = confirm('File does not exist. Create "' . expanded_filename . '"?', "&Yes\n&No", 1)

   " Handle the user's choice
   if choice == 1
     " Create the file and open it
     execute 'edit ' . expanded_filename
   endif
 else
   " File exists, perform normal gf behavior
   execute 'normal! gf'
 endif
endfunction
ZK_
  • 494
  • 5
  • 14