Vim Tips Wiki

Simple creation of scripts

1,624pages on
this wiki
Add New Page
Talk0 Share
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
autocmd BufWritePost * call MySetExecutableIfScript(getline(1), expand("%:p"))


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
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
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
" 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

Ad blocker interference detected!

Wikia is a free-to-use site that makes money from advertising. We have a modified experience for viewers using ad blockers

Wikia is not accessible if you’ve made further modifications. Remove the custom ad blocker rule(s) and the page will load as expected.

Also on Fandom

Random Wiki