Vim Tips Wiki
(Change to TipImported template + severe manual clean)
(Change <tt> to <code>, perhaps also minor tweak.)
 
(11 intermediate revisions by 4 users not shown)
Line 1: Line 1:
{{review}}
 
 
{{TipImported
 
{{TipImported
 
|id=709
 
|id=709
 
|previous=708
 
|previous=708
 
|next=710
 
|next=710
|created=May 2, 2004
+
|created=2004
 
|complexity=basic
 
|complexity=basic
 
|author=Yakov Lerner
 
|author=Yakov Lerner
 
|version=6.0
 
|version=6.0
 
|rating=53/26
 
|rating=53/26
 
|category1=Automated Text Insertion
 
|category2=LanguageSpecific
 
}}
 
}}
  +
If you create lots of scripts, you can arrange for the executable bit to be automagically set on save if the file begins with '<code>#!/usr/bin/</code>' or '<code>#!/bin</code>'.
If you create lots of shell scripts, then you'll find this useful:
 
   
 
<pre>
 
<pre>
  +
function! MySetExecutableIfScript(line1, current_file)
" automatically give executable permissions if filename is *.sh
 
  +
if a:line1 =~ '^#!\(/usr\)*/bin/'
au BufWritePost *.sh :!chmod a+x &lt;afile&gt;
 
  +
let chmod_command = "silent !chmod ugo+x " . a:current_file
" automatically insert "#!/bin/sh" line for *.sh files
 
  +
execute chmod_command
au BufEnter *.sh if getline(1) == "" | :call setline(1, "#!/bin/sh") | endif
 
  +
endif
" automatically give executable permissions if file begins with #!/bin/sh
 
  +
endfunction
au BufWritePost * if getline(1) =~ "^#!/bin/[a-z]*sh" | silent !chmod a+x &lt;afile&gt; | endif
 
  +
autocmd BufWritePost * call MySetExecutableIfScript(getline(1), expand("%:p"))
 
</pre>
 
</pre>
   
 
==Comments==
 
==Comments==
  +
WARNING: autocommands with constructs like '<code>if condition | clause | endif</code>' are problematic for me, and apparently for others given the comments below. They seem to have the potential to make other autocommands declared later not happen. I recommend having you autocommand call a function and doing your ifing in there as above.
I adopted it for python files:
 
au BufEnter *.py if getline(1) == "" | :call setline(1, "#!/usr/bin/env python") | endif
 
 
Might be useful for other languages as well, maybe an idea for a plugin for multiple languages.
 
 
 
----
 
----
Here's something a little better for python:
+
Here's something a little better for Python:
 
 
<pre>
 
<pre>
 
" Python header
 
" Python header
function! &lt;SID&gt;PythonHeader()
+
function! <SID>PythonHeader()
:call setline(1, "#! /bin/sh")
+
call setline(1, "#! /bin/sh")
:call append(1, "# vim: filetype=python")
+
call append(1, "# vim: filetype=python")
:call append(2, "\"\"\":\"")
+
call append(2, "\"\"\":\"")
:call append(3, "exec python $0 ${1+\"$@\"}")
+
call append(3, "exec python $0 ${1+\"$@\"}")
:call append(4, "\"\"\"")
+
call append(4, "\"\"\"")
:call append(5, "")
+
call append(5, "")
 
exe 6
 
exe 6
 
endfunction
 
endfunction
Line 47: Line 44:
 
<pre>
 
<pre>
 
" Shell header
 
" Shell header
function! &lt;SID&gt;ShellHeader()
+
function! <SID>ShellHeader()
:call setline(1, "#! /bin/sh")
+
call setline(1, "#! /bin/sh")
:call append(1, "")
+
call append(1, "")
 
exe 2
 
exe 2
 
endfunction
 
endfunction
Line 74: Line 71:
   
 
<pre>
 
<pre>
au BufWritePost * if getline(1) =~ "^#! ?/bin/[a-z]*sh" | silent !chmod a+x &lt;afile&gt; | endif
+
au BufWritePost * if getline(1) =~ "^#! ?/bin/[a-z]*sh" | silent !chmod a+x <afile> | endif
 
</pre>
 
</pre>
   
Line 80: Line 77:
   
 
<pre>
 
<pre>
au BufWritePost * if getline(1) =~ "^#! ?/bin/[a-z]*sh" | silent !chmod a+x &lt;afile&gt;
+
au BufWritePost * if getline(1) =~ "^#! ?/bin/[a-z]*sh" | silent !chmod a+x <afile>
 
au BufWritePost * | endif
 
au BufWritePost * | endif
 
</pre>
 
</pre>
   
 
----
 
----
[[Category:Automated Text Insertion]]
 
[[Category:LanguageSpecific]]
 

Latest revision as of 05:44, 13 July 2012

Tip 709 Printable Monobook Previous Next

created 2004 · complexity basic · author Yakov Lerner · version 6.0


If you create lots of scripts, you can arrange for the executable bit to be automagically set on save if the file begins with '#!/usr/bin/' or '#!/bin'.

function! MySetExecutableIfScript(line1, current_file)
  if a:line1 =~ '^#!\(/usr\)*/bin/'
    let chmod_command = "silent !chmod ugo+x " . a:current_file
    execute chmod_command
  endif
endfunction
autocmd BufWritePost * call MySetExecutableIfScript(getline(1), expand("%:p"))

Comments[]

WARNING: autocommands with constructs like 'if condition | clause | endif' are problematic for me, and apparently for others given the comments below. They seem to have the potential to make other autocommands declared later not happen. I recommend having you autocommand call a function and doing your ifing in there as above.


Here's something a little better for Python:

" Python header
function! <SID>PythonHeader()
  call setline(1, "#! /bin/sh")
  call append(1, "# vim: filetype=python")
  call append(2, "\"\"\":\"")
  call append(3, "exec python $0 ${1+\"$@\"}")
  call append(4, "\"\"\"")
  call append(5, "")
  exe 6
endfunction
au BufEnter *.py if getline(1) == "" | call s:PythonHeader() | endif

Or for shell:

" Shell header
function! <SID>ShellHeader()
  call setline(1, "#! /bin/sh")
  call append(1, "")
  exe 2
endfunction
au BufEnter *.sh if getline(1) == "" | call s:ShellHeader() | endif

I did not want the script to keep doing the chmod even when the file is already excutable, so this is what I have in my vimrc:

" Define a function that can tell me if a file is executable
function! FileExecutable (fname)
  execute "silent! ! test -x" a:fname
  return v:shell_error
endfunction
" Automatically make Perl and Shell scripts executable if they aren't already
au BufWritePost *.sh,*.pl,*.cgi if FileExecutable("%:p") | :!chmod a+x % ^@ endif

Note that the ^@ is actually Ctrl-V Ctrl-J (an embedded new line), because you cannot use | as a separator after an external command.


For the problem with " | endif" after a shell command - e.g.:

au BufWritePost * if getline(1) =~ "^#! ?/bin/[a-z]*sh" | silent !chmod a+x <afile> | endif

I noticed that the above works fine for csh / tcsh, but not in a bash shell. I got this to work fine for a bash shell:

au BufWritePost * if getline(1) =~ "^#! ?/bin/[a-z]*sh" | silent !chmod a+x <afile>
au BufWritePost * | endif