6

I'm aiming to make scripts I write in a certain directory (or of a certain extension) automatically executable on creation. I can do this whenever a file is written to, using the following autocmd:

autocmd BufWritePost *.py silent execute "! chmod +x %"

What I don't like is that this runs every time the file is written. If I had decided to reset the permissions of a particular script, I wouldn't want it to be set again, for example. And if the command is expensive, or is not idempotent, it would be undesirable to run it again and again. While this particular example uses chmod, please consider a more general case.

There is an event for when a buffer is created for a new file (BufNewFile), but is there some way to do this when such a buffer is written the first time?

  • This is hackish, but perhaps you could use BufNewFile to trigger the creation of an autocommand with a BufWritePost. After the event for BufWritePost finishes, delete the BufWritePost autocommand. – void-pointer Feb 4 '15 at 8:11
  • @void-pointer I considered doing that, then I stopped to wonder if there's a more elegant way - perhaps I had misunderstood the meaning of some event or something like that. – muru Feb 4 '15 at 8:14
  • I'm not an expert on Vimscript, but after going through help au, it doesn't seem like there's a mechanism in place to fire an autocommand on the first write only. – void-pointer Feb 4 '15 at 8:23
  • I wonder if this problem should be handled by the OS, not by Vim. This question might be more appropriate. – tommcdo Feb 25 '15 at 10:49
  • Set a cookie (some b: variable with an unique name) from a BufNewFile, check for the same cookie from a BufWritePost, then delete it after you write the file. – lcd047 Mar 15 '16 at 10:46
4

This would set the file to be executable after writing to the file if it's not already executable

autocmd BufWritePost *.py
    \  if getfperm(expand('%')) !~# 'x'
    \|   silent execute "! chmod +x %"
    \| endif

I think this should be the better approach.

To make only a new file executable:

autocmd BufWritePre *.py
    \  if !filereadable(expand('%'))
    \|   let b:is_new = 1
    \| endif
autocmd BufWritePost *.py
    \  if get(b:, 'is_new', 0)
    \|   silent execute '!chmod +x %'
    \|   let b:is_new = 0
    \| endif
2

I use a different solution for this, with a script I called xvim:

#!/bin/sh

vim -p "$@"
for f in "$@"; do
    [ -f "$f" ] && chmod a+x "$f"
done

I put this in my ~/bin (make sure this is in your PATH), and also linked xvi to it.

The advantage of this, is that I explicitly control which files are executable, rather than just assuming that all .*.py files should be executable (files in modules usually aren't). You also don't need to set it up for all filetypes (*.rb, *.sh, etc.).

If you don't want xvim to overwrite existing permissions, you can use:

#!/bin/sh

for f in "$@"; do
    [ -f "$f" ] && continue
    touch "$f"
    chmod a+x "$f"
done
vim -p "$@"

Note that this will create the files immediately when you run xvim file (this is different from vim).

  • I suppose for my case it would be: [ -f "$f" ] || {touch "$f" && chmod +x "$f"} before vim. But yes, combined with vim -p this would be very useful for me. – muru Feb 4 '15 at 9:52
  • @muru Normally, when you do vim newfile, it doesn't make the file until you write it for the first time. So this works better the same as the default vim behaviour... And because you run this command explicitly (and not on every :w), running the chmod on existing files as well can be considered a feature, and not a bug :-) – Martin Tournoij Feb 4 '15 at 9:54
  • This does suffer from the same flaw is Dhruva's original answer - I don't want the action run on an existing file or repeatedly over the same file. In my case, solidly a bug. – muru Feb 4 '15 at 9:56
  • @muru But you only run this when you create the file (once). Then when you edit it the next time, you just use vim and none of this gets run (that's how I use it, anyway). – Martin Tournoij Feb 4 '15 at 10:02
  • Remembering that sort of stuff (use x for this and y for that) is what I have vim and zsh for. :P – muru Feb 4 '15 at 10:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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