diff options
author | Tom Ryder <tom@sanctum.geek.nz> | 2019-05-29 01:12:00 +1200 |
---|---|---|
committer | Tom Ryder <tom@sanctum.geek.nz> | 2019-05-29 01:12:00 +1200 |
commit | 2e6b0b13b652bf7e5187c7964abbb5506ac18944 (patch) | |
tree | 6cc80863b71e5ef559732232c803525e15b093f2 /autoload/shebang_create_exec.vim | |
parent | Merge branch 'release/v0.3.0' (diff) | |
parent | Bump VERSION (diff) | |
download | vim-shebang-create-exec-2e6b0b13b652bf7e5187c7964abbb5506ac18944.tar.gz vim-shebang-create-exec-2e6b0b13b652bf7e5187c7964abbb5506ac18944.zip |
Merge branch 'release/v1.0.0'v1.0.0
* release/v1.0.0:
Overhaul completely
Diffstat (limited to 'autoload/shebang_create_exec.vim')
-rw-r--r-- | autoload/shebang_create_exec.vim | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/autoload/shebang_create_exec.vim b/autoload/shebang_create_exec.vim index b01cf58..1ce68e3 100644 --- a/autoload/shebang_create_exec.vim +++ b/autoload/shebang_create_exec.vim @@ -1,14 +1,83 @@ -" If the buffer starts with a shebang and the file being saved to doesn't -" exist yet, set up a hook to make it executable after the write is done -function! shebang_create_exec#Check(filename) abort - if stridx(getline(1), '#!') == 0 && !filereadable(a:filename) - autocmd shebang_create_exec BufWritePost <buffer> - \ call shebang_create_exec#Chmod(expand('<afile>:p')) +" Pattern to detect real-looking shebang to an absolute path +let s:shebang = '^#!\s*/[^/]\+' + +" If the buffer looks shebanged, and the file being saved to doesn't exist +" yet, set up a hook to make it executable after the write is done done +function! shebang_create_exec#(filename) abort + + " If the first line isn't a shebang, or the file exists, do nothing + if getline(1) !~# s:shebang || filereadable(a:filename) + return endif + + " Set a buffer variable to the target filename + let b:shebang_create_exec_filename = a:filename + + " Set up a hook to run and clean up after the write + autocmd shebang_create_exec BufWritePost <buffer> + \ call s:Run(expand('<afile>:p')) + endfunction -" Make the file executable and clear away the hook that called us -function! shebang_create_exec#Chmod(filename) abort +" Clear away the hook that called us and make the file executable +function! s:Run(filename) abort + + " Clear away the hook that called us autocmd! shebang_create_exec BufWritePost <buffer> - call system('chmod +x '.shellescape(a:filename)) + + " Check that the save filename was set by BufWritePre + if !exists('b:shebang_create_exec_filename') + return + endif + + " Check that it matches the file we just saved, and if so, make that file + " executable + if a:filename ==# b:shebang_create_exec_filename + call s:MakeExecutable(b:shebang_create_exec_filename) + endif + + " Clear away the save filename, even if we didn't change any permissions + unlet b:shebang_create_exec_filename + +endfunction + +" Make a given filename executable +function! s:MakeExecutable(filename) abort + + " Get filename into local variable + let filename = a:filename + + " How we do this depends on whether we have native file permissions + " functions (Vim >=8.0) + if exists('*setfperm') + + " We have setfperm(), so we can make the file executable without a fork to + " chmod(1), which should be quick and safe + let cperm = getfperm(filename) + + " Replace every third character of the permissions string with an 'x' + let nperm + \ = strpart(cperm, 0, 2).'x' + \ . strpart(cperm, 3, 2).'x' + \ . strpart(cperm, 6, 2).'x' + + " If our new permissions string differs from the current one, apply it to + " the file + if nperm !=# cperm + call setfperm(filename, nperm) + endif + + else + + " We'll need to fork to chmod(1); escape the filename safely, using + " shellescape() if we've got it + let l:filename_escaped = exists('*shellescape') + \ ? shellescape(filename) + \ : '''' . escape(filename, '''') . '''' + + " Try to make the file executable with a fork to chmod(1) + call system('chmod +x '.filename_escaped) + + endif + endfunction |