1

I have a function that renames a file by saving it to the new location then deleting the old:

execute "saveas" fnameescape(l:new_path)
call delete(l:old_path)

I ran into a problem with this today. l:new_path already existed on disk, and I didn't want to overwrite it, so I answered "No" when prompted, but the function proceeded to delete l:old_path anyways.

How can I test the execute "saveas" command and prevent the delete in this case? I want to say something like:

execute "saveas" fnameescape(l:new_path) || return

But this throws an error: E121: Undefined variable: return.

In the shell I could test $?. Does VimL have something similar?

4
  • Are you calling that from within a Vim function? If so you can add an abort tag to the function definition: function MyFunction() abort, so it exits as soon as it detects an error
    – filbranden
    Commented Nov 15 at 19:45
  • Check if the file already exists before doing :saveas. See :help file-functions.
    – romainl
    Commented Nov 18 at 7:44
  • Do you have something open in your question? How can we help you further? Otherwise maybe could you accept one of the solutions using the v button next to the arrow voting buttons. It allow the question to rest :-) Commented Nov 21 at 15:46
  • 1
    @VivianDeSmedt I appreciate the suggestions below but the question remains: how do you test the result of execute "saveas" when set confirm is enabled, you're prompted to overwrite an existing file and answer "No"? It seems like it may not be possible, in which case I may need an alternative to set confirm, maybe using confirm() in combination with the glob() test suggested by @romainl. Commented Nov 22 at 15:55

2 Answers 2

0

Following the suggestion of @filbranden you could do:

function! Rename(old_path, new_path) abort
  let c=&confirm
  set noconfirm
  try
    execute "saveas" fnameescape(a:new_path)
  catch /File exists/
    echo 'fail to rename to: ' . fnameescape(a:new_path)
    return
  finally
    let &confirm = c
  endtry
  call delete(a:old_path)
endfunction

Remark: I propose to temporarily disable the noconfirm option such that the exception is raised.

7
  • Doesn't seem to work. I think if the file exists, and :saveas prompts you to overwrite, and you answer "No", there's no error. Commented Nov 15 at 23:13
  • It works on my end :-/ Could you tell me which version of Vim you are using? Commented Nov 16 at 4:23
  • I have corrected small errors. I have tested the code on Vim 7.0 and on Neovim 0.10 and it seems to work fine. In particular I'm not prompted to override the file. Commented Nov 16 at 7:08
  • 1
    I'm using Neovim v0.10.1. Steps to repro: 1. echo a > a.txt 2. echo b > b.txt 3. nvim b.txt 4. :call Rename('b.txt', 'a.txt') 5. When prompted to overwrite a.txt, answer "No" 6. b.txt is deleted anyways. Commented Nov 17 at 16:08
  • 1
    You're right! Nice deduction. I forgot that wasn't the default behavior. Commented Nov 22 at 15:38
0

Here is a simple implementation:

function! Rename(old_path, new_path)
    let old_filename = fnameescape(a:old_path)
    let new_filename = fnameescape(a:new_path)

    if glob(new_filename)->empty()
        execute "saveas " .. new_filename
        call delete(old_filename)
    else
        echohl WarningMsg
        echo new_filename .. " already exists"
        echohl None
    endif
endfunction

Where we use :help glob() to determine if new_filename exists:

  • If it does,
    • glob() returns its full path,
      • empty() is false,
        • we can't proceed.
  • If it doesn't,
    • glob() returns an empty string,
      • empty() is true,
        • we can proceed.

But that is all just a fancy way to reinvent :help rename().

3
  • This is very similar to the function in my vimrc. The question remains: how do you test the result of execute "saveas" when set confirm is enabled, you're prompted to overwrite an existing file and answer "No"? Anyways, I might just use rename() instead like you suggested. Commented Nov 22 at 15:37
  • Actually, rename() overwrites without warning so is a no-go for me. Commented Nov 22 at 15:45
  • You don't test execute "saveas", that's the whole point. Instead of doing something that may or may not fail and then handling eventual failure, you do something only it it can't fail.
    – romainl
    Commented Nov 22 at 16:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.