aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Ryder <tom@sanctum.geek.nz>2019-05-31 22:02:49 +1200
committerTom Ryder <tom@sanctum.geek.nz>2019-05-31 22:34:37 +1200
commit2c20e459fafbf7f571833ce9a26143878c4f5902 (patch)
tree2e90aa8eaa51b42fb1ea3ee80348f08ab42bcb77
parentRemove unneeded variable scoping (diff)
downloadvim-write-mkpath-2c20e459fafbf7f571833ce9a26143878c4f5902.tar.gz
vim-write-mkpath-2c20e459fafbf7f571833ce9a26143878c4f5902.zip
Handle :cd then buffer write of non-existent path
-rw-r--r--autoload/write_mkpath.vim52
-rw-r--r--plugin/write_mkpath.vim4
2 files changed, 49 insertions, 7 deletions
diff --git a/autoload/write_mkpath.vim b/autoload/write_mkpath.vim
index 0d3e357..aca49f1 100644
--- a/autoload/write_mkpath.vim
+++ b/autoload/write_mkpath.vim
@@ -1,13 +1,42 @@
-function! write_mkpath#(path) abort
+" Handle a buffer created for a new file; anchor its filename to be absolute
+" if it's relative and the directory path doesn't yet exist; this stops Vim
+" trying to save in the wrong place if the user changes directory before
+" writing the buffer
+function! write_mkpath#New(path) abort
- " Path exists, we don't need to do anything
- if isdirectory(a:path)
+ " We don't have fnameescape(); this old Vim < v7.1.299 is likely too buggy
+ " to handle the buffer renaming for paths safely, so better not to mess with
+ " it and instead to stick with suboptimal but consistent behaviour
+ if !exists('*fnameescape')
return
endif
- " If :write! was issued, we'll try to create the path; failing that, if
- " 'confirm' is enabled, and the user responds affirmatively to the prompt,
- " that will do, too. Otherwise, we will allow the write to fail.
+ " Path exists, or is absolute; we don't need to do anything
+ if isdirectory(fnamemodify(a:path, ':h'))
+ \ || s:Absolute(a:path)
+ return
+ endif
+
+ " Set filename to absolute path using :file {name}
+ execute 'file '.fnameescape(getcwd().'/'.a:path)
+
+endfunction
+
+" Handle a :write operation; prompt for directory creation if needed with
+" 'confirm', force it with :write!
+function! write_mkpath#Write(path) abort
+
+ " Get all directory elements leading up to directory
+ let dir = fnamemodify(a:path, ':h')
+
+ " Directory exists, we don't need to do anything
+ if isdirectory(dir)
+ return
+ endif
+
+ " If :write! was issued, we'll try to create the missing path; failing that,
+ " if 'confirm' is enabled, and the user responds affirmatively to the
+ " prompt, that will do, too. Otherwise, we will allow the write to fail.
if v:cmdbang
let mkpath = 1
elseif &confirm
@@ -22,3 +51,14 @@ function! write_mkpath#(path) abort
endif
endfunction
+
+" Clumsy and probably wrong helper function to check if a path is absolute
+function! s:Absolute(path) abort
+ if has('unix')
+ return a:path =~# '^/' " Leading slash on Unix
+ elseif has('win32') || has('win64')
+ return a:path =~# '^\u:' " e.g. C: -- I'm not sure this is right
+ else
+ echoerr 'Unrecognised operating system'
+ endif
+endfunction
diff --git a/plugin/write_mkpath.vim b/plugin/write_mkpath.vim
index 334f24e..c7c9543 100644
--- a/plugin/write_mkpath.vim
+++ b/plugin/write_mkpath.vim
@@ -12,6 +12,8 @@ endif
" Check path to every file before it's saved
augroup write_mkpath
autocmd!
+ autocmd BufNewFile *
+ \ call write_mkpath#New(expand('<afile>'))
autocmd BufWritePre *
- \ call write_mkpath#(expand('<afile>:p:h'))
+ \ call write_mkpath#Write(expand('<afile>'))
augroup END