Prevent write to overrite existing file by default

Yesterday I was editing some code while I tried to open a new file. Unfortunately, I typed ‘w’ instead of ‘e’, ultimately leading to my file being erased. Long story short, I lost the last hour of work because of this typo. Coming from vim, it never happens then because vim has an option that prevent write to override an already existing file without confirmation (if this file is not the current buffer already). Would this be possible to have this kind of security in kakoune ?

I am not sure I understand the situation. Do you mean that while you were editing file_one, you decided to also edit file_two, but that instead of typing :e file_two you wrote :w file_two by mistake, leading the content of the file_one buffer to overwrite file_two on your hard drive?

If this is what happened, then I do not think Kakoune has any relevant option to the write command. One way out would be to write you own secure_write command (with a bit of shell testing, [ -a … ] before writing the buffer to the filesystem) and alias it to ‘w’. For this to work, however, you will need first to unalias ‘w’ in your kakrc. That is, you should have:

unalias global w write

before:

alias global w secure_write

Hope this helps.

Yes that is the situation.

Thank for your help, I will do that. I will post the corresponding shell script here after.

define-command -params 0..1 secure_write %{ evaluate-commands %sh{
  if [ -z ${1+x} ]; then
    # no param given: usual write
    echo "write"
  else
    bufname=$1
    if [[ -a ${bufname} && "${bufname}" != "${current_bufname}" ]]; then
      # file already exists and is not the current one
      echo "echo 'Use w! to override existing file'"
    else
      echo "write $1"
    fi
  fi
}}

this piece of code seems to do the trick

1 Like

I am not sure this works. On this line:

if [[ -a ${bufname} && "${bufname}" != "${current_bufname}" ]]; then

the double brackets, although valid in Bash, won’t be accepted by a POSIX shell. Single brackets are preferred, and the && operator should probably be moved outside of the tests:

if [ -a "${bufname}" ] && [ "${bufname}" != "${current_bufname}" ]; then

Also, I am unsure about the origin of current_bufname. Did you write an assignment such as:

current_bufname=$kak_buffile

?

You are right for the brackets, and -e should be preferred as I just saw that -a is deprecated.

current_bufname is the option I use to retrieve the name of the current buffer usually, I don’t know about $kak_buffile. Is it more robust ?

Judging from :doc expansions, one advantage of buffile over bufname is that the former includes the full path of your file.