Как я могу остановить Vim от записи файла без выдачи ошибки?

10

Я пытаюсь улучшить код из этого ответа, чтобы запросить подтверждение перед созданием отсутствующего каталога, вот что я пишу:

function! CreateDirectoryAskConfirmation(path)
    if !isdirectory(a:path)
        echohl Question
        echo "Create directory " . a:path . "?"
        echohl None

        let response = nr2char(getchar())
        if response ==? "y"
            call mkdir(a:path, "p")
        endif
    endif
endfunction

autocmd BufWritePre * call CreateDirectoryAskConfirmation(expand("<afile>:p:h"))

Я упускаю одну вещь: когда я не нажимаю yна подсказку, я бы хотел, чтобы Vim прервал запись, чтобы я не получил ошибку E212: Can't open file for writingи мне не нужно нажимать другую клавишу, чтобы сообщение об ошибке исчезло. Есть способ добиться этого?

toro2k
источник

Ответы:

9

Вместо использования BufWritePreautocmd вы можете использовать BufWriteCmd autocmd из :help BufWriteCmd:

Должен выполнить запись файла и сбросить «измененный» в случае успеха, если «+» не находится в «cpo» и запись в другой файл cpo- +.

Мы можем просто позвонить :writeиз autocmd. Это позаботится о настройке modified.

Таким образом, логика будет модифицирована для вызова, :writeкогда каталог уже существует, и вызова :writeпосле создания каталога, если он еще не существует. Если вы нажмете n, мы ничего не делаем. Это оставит буфер как есть и не будет переустанавливаться modified, поэтому :qвсе равно выдаст E37: No write since last changeошибку.

function! CreateDirectoryAskConfirmation(path, dir)
    silent doautocmd BufWritePre

    " Directory exists, :write and return
    if isdirectory(a:dir)
        execute 'write ' . a:path
        silent doautocmd BufWritePost
        return
    endif

    " Ask for confirmation to create this directory
    echohl Question
    echo "Create directory `" . a:dir . "' [y/N]?"
    echohl None

    let response = nr2char(getchar())
    " mkdir() and :write if we want to make a directory
    if response ==? "y"
        call mkdir(a:dir, "p")
        execute 'write ' . a:path
        silent doautocmd BufWritePost
    endif
endfunction

autocmd BufWriteCmd * call CreateDirectoryAskConfirmation(expand("<amatch>:p"), expand("<amatch>:p:h"))
Мартин Турной
источник
2
В файлах VimScript ведение :никогда не требуется для команд.
tommcdo
@ tommcdo Спасибо. Почему-то мой мозг иногда забывает об этом> _ <
Мартин Турной
2
@ toro2k Спасибо. Я не знал об этом. Я отредактировал свой ответ, я также добавил, silentчтобы вы не получили сообщение, если вы не используете это autogroup. Я также исправил еще одну проблему, которую заметил: :w another_nameне работал (не работает).
Мартин Турной
2
@ toro2k Потому что в противном случае writeбудет просто записывать текущее имя файла (как при вводе :write) и :write another_filenameне будет работать (оно все равно будет использовать исходное имя файла).
Мартин Турной
1
@whitesiroi Вы можете использовать bufypeнастройку, чтобы получить тип буфера. Не стесняйтесь редактировать пост с исправлением (или, если вы этого не сделаете, я буду на следующей неделе).
Мартин Турной