กลุ่ม: การสร้างไดเร็กทอรีหลักเมื่อบันทึก


122

หากฉันวิงวอนvim foo/bar/somefileแต่foo/barไม่มีอยู่ Vim ก็ปฏิเสธที่จะบันทึก

ฉันรู้ว่าฉันสามารถเปลี่ยนเป็นเชลล์หรือทำ:!mkdir foo/barจาก Vim ได้ แต่ฉันขี้เกียจ :) มีวิธีทำให้ Vim ทำโดยอัตโนมัติเมื่อมันบันทึกบัฟเฟอร์หรือไม่?


13
mkdir -p %:hจะดีกว่าเนื่องจากใช้งานได้กับพา ธ ที่ไม่มีอยู่ที่ซ้อนกันไม่เพิ่มข้อผิดพลาดเมื่อมีพา ธ อยู่แล้วและ%:hเป็นพา ธ แบบเต็มของไฟล์ปัจจุบัน อย่างไรก็ตามฉันไม่รู้วิธีเรียกสิ่งนี้โดยอัตโนมัติ โดยปกติสิ่งนี้จะทำด้วยคำสั่งอัตโนมัติ แต่BufWritePreเหตุการณ์ดูเหมือนจะไม่ทำงานที่นี่
Konrad Rudolph

กำหนดฟังก์ชั่นที่ตรวจสอบว่ามีไฟล์อยู่หรือไม่และเรียกบิวอินwriteและเรียกระบบไปmkdir -pที่dirnameอย่างอื่นแมปกับW... ฉันขี้เกียจค้นหาไวยากรณ์และโพสต์เป็นคำตอบ ... ขออภัย
khachik

1
ฉันเดาว่าฉันสามารถรวมทั้งคำแนะนำและนามแฝงของคุณ:wเพื่อmkdir -p %:hตามด้วยการสร้าง:write
Damien Pollet

คำตอบ:


91
augroup BWCCreateDir
    autocmd!
    autocmd BufWritePre * if expand("<afile>")!~#'^\w\+:/' && !isdirectory(expand("%:h")) | execute "silent! !mkdir -p ".shellescape(expand('%:h'), 1) | redraw! | endif
augroup END

สังเกตเงื่อนไข: expand("<afile>")!~#'^\w\+:/'จะป้องกันไม่ให้กลุ่มสร้างไดเร็กทอรีสำหรับไฟล์เช่นftp://*และ!isdirectoryจะป้องกันการโทร mkdir ที่มีราคาแพง

อัปเดต : โซลูชันที่ดีกว่าอย่างเนียน ๆ ที่ตรวจสอบ buftype ที่ไม่ว่างเปล่าและการใช้งานmkdir():

function s:MkNonExDir(file, buf)
    if empty(getbufvar(a:buf, '&buftype')) && a:file!~#'\v^\w+\:\/'
        let dir=fnamemodify(a:file, ':h')
        if !isdirectory(dir)
            call mkdir(dir, 'p')
        endif
    endif
endfunction
augroup BWCCreateDir
    autocmd!
    autocmd BufWritePre * :call s:MkNonExDir(expand('<afile>'), +expand('<abuf>'))
augroup END

1
ขอบคุณดูเหมือนจะสะอาดกว่าที่ฉันเดาไว้มาก :)
Damien Pollet

11
call mkdir(expand('%:h'), 'p')อาจพกพาได้มากกว่า
Marius Gedminas

1
@MariusGedminas ฉันต้องการเห็นรหัสที่สมบูรณ์พร้อมกับการเปลี่ยนแปลงนั้น คุณช่วยโพสต์เป็นคำตอบ / อัปโหลดที่ใดที่หนึ่งได้ไหม
kikito

@kikito ดูคำตอบของฉัน มีการแก้ไขไม่กี่ชั่วโมงหลังจากความคิดเห็นนั้น
ZyX

@Zyx ขอบคุณ! ฉันลงเอยด้วยการทำบางสิ่งที่สั้นลงเล็กน้อย (คำตอบของฉันคือคำตอบสุดท้าย) แต่ดูเหมือนว่าจะทำเคล็ดลับได้ดี
kikito

20

ตามข้อเสนอแนะสำหรับคำถามของฉันนี่คือสิ่งที่ฉันลงเอยด้วย:

function WriteCreatingDirs()
    execute ':silent !mkdir -p %:h'
    write
endfunction
command W call WriteCreatingDirs()

สิ่งนี้กำหนด:Wคำสั่ง จะเป็นการดีที่ฉันต้องการที่จะมีทั้งหมดของ:w!, :wq, :wq!, :wallฯลฯ ทำงานเหมือนกัน แต่ผมไม่แน่ใจว่าถ้าเป็นไปได้โดยไม่ต้องพื้น reimplementing พวกเขาทั้งหมดที่มีฟังก์ชั่นที่กำหนดเอง


2
ฉันได้ลองใช้คำสั่งเดียวกันนี้และทุกครั้งที่ใช้:Wหน้าจอของฉันแทบจะว่างเปล่า ฉันจะพยายามลบตัวเลือกก่อนหน้านี้และแสดงความคิดเห็น
moebius_eye

6

ฉันเพิ่มสิ่งนี้ใน ~ / .vimrc ของฉัน

cnoremap mk. !mkdir -p <c-r>=expand("%:h")<cr>/

ถ้าฉันต้องการสร้างไดเร็กทอรีที่ฉันกำลังพิมพ์อยู่:mk.และมันจะแทนที่ด้วย "! mkdir -p / path / to / my / file /" และอนุญาตให้ฉันตรวจสอบคำสั่งก่อนที่จะเรียกใช้



3

รหัสนี้จะแจ้งให้คุณสร้างไดเร็กทอรีด้วย:wหรือทำด้วย:w!:

augroup vimrc-auto-mkdir
  autocmd!
  autocmd BufWritePre * call s:auto_mkdir(expand('<afile>:p:h'), v:cmdbang)
  function! s:auto_mkdir(dir, force)
    if !isdirectory(a:dir)
          \   && (a:force
          \       || input("'" . a:dir . "' does not exist. Create? [y/N]") =~? '^y\%[es]$')
      call mkdir(iconv(a:dir, &encoding, &termencoding), 'p')
    endif
  endfunction
augroup END

1

ฉันคิดว่าฉันสามารถทำได้ในสามบรรทัดโดยรวมสิ่งที่คนอื่นพูดกับคำตอบนี้

ดูเหมือนจะทำเคล็ดลับ:

if has("autocmd")
  autocmd BufWritePre * :silent !mkdir -p %:p:h
end

พยายามสร้างโฟลเดอร์โดยอัตโนมัติเมื่อบันทึกบัฟเฟอร์ หากมีสิ่งไม่ดีเกิดขึ้น (เช่นปัญหาการอนุญาต) มันก็จะปิดและปล่อยให้เขียนไฟล์ล้มเหลว

หากใครเห็นข้อบกพร่องที่ชัดเจนโปรดแสดงความคิดเห็น ฉันไม่ค่อยเชี่ยวชาญใน vimscript

แก้ไข: หมายเหตุขอบคุณ ZyX

  • สิ่งนี้จะใช้ไม่ได้หากโฟลเดอร์ของคุณมีช่องว่าง (ดูเหมือนว่าจะไม่ถูกหลีกเลี่ยงอย่างถูกต้องหรือมีบางอย่าง)
  • หรือหากคุณกำลังทำไฟล์หลอก
  • หรือถ้าคุณกำลังจัดหา vimrc ของคุณ
  • แต่ลูกชายมันสั้น

1
ห้ามใช้%ในสคริปต์ดังกล่าว เป็นกลุ่มจะไม่หลบหนีสัญลักษณ์พิเศษใด ๆ ตัวอย่างเช่นถ้าคุณกำลังแก้ไขไฟล์ชื่อ/mnt/windows/Documents and Settings/User/_vimrcคุณจะจบลงด้วยการมีสี่ไดเรกทอรีใหม่: /mnt/windows/Documents, ./and, และ./Settings ./Settings/Userและอย่างไรก็ตามคุณไม่ต้องการ:executeที่นี่
ZyX

1
มีsystem()ฟังก์ชั่นสำหรับการโทรเปลือกเงียบสนิท แต่คุณไม่จำเป็นต้องใช้ทั้ง:executeและ%:p:h: :silent !mkdir -p %:p:hทำงานตรงตามสิ่งที่คุณได้เขียน (แม้ว่าคุณอาจต้องการ:redraw!ที่สิ้นสุดในกรณีนี้:executeมามีประโยชน์) call system('mkdir -p '.shellescape(expand('%:p:h')))แต่มันจะดีกว่าที่จะใช้ จะใช้:execute '!command' shellescape(arg, 1)(มีอาร์กิวเมนต์ที่สองที่จะ shellescape) system()ถ้าคุณมีการใช้เรียบแทน ใช้การเรียบหากอาร์กิวเมนต์ที่ใช้ Escape มีการขึ้นบรรทัดใหม่
ZyX

และคุณไม่หลีกเลี่ยงปัญหาอื่น ๆ ที่ฉันกำลังหลีกเลี่ยงในโค้ดครั้งแรกของฉัน: เปิดตัวเชลล์เวลาเพิ่มเติมหนึ่งหลังจากที่ทุกจัดหา vimrc (เผื่อว่าคุณดึงใน vimrc การปรับปรุงโดยการทำ:source ~/.vimrc) (นี่คือสิ่งที่augroupและautocmd!มีการ) ทิ้งมุมมองหลังจากการเปิดตัวเชลล์ คำสั่ง (นั่นคือสิ่งที่redraw!มีไว้สำหรับ) การสร้างไดเร็กทอรีขยะในกรณีที่ใช้ไฟล์หลอก (ในโค้ดแรกจะถูกตรวจสอบโดยการจับคู่ชื่อไฟล์กับรูปแบบเท่านั้น แต่ในอันที่สองฉันตรวจสอบด้วย&buftype) และการเรียกเชลล์ที่ไร้ประโยชน์ในไดเร็กทอรีเคส มีอยู่ ( isdirectory()เงื่อนไข)
ZyX

1
@ZyX ขอบคุณสำหรับคำติชม ฉันไม่ต้องการแก้ปัญหาที่ฉันไม่มี ฉันไม่เคยใช้ตัวอักษรพิเศษ (เช่นช่องว่าง) ในโฟลเดอร์ของฉันดังนั้น%: p: h จึงใช้ได้ดีสำหรับฉัน ฉันไม่เคยหาแหล่ง vimrc (ฉันฆ่าและเปิด vim ใหม่แทน) และฉันไม่รู้ด้วยซ้ำว่า pseudofiles คืออะไร วาด! ดูเหมือนจะไม่ทำอะไรฉันเลย แต่ฉันชอบคำแนะนำของคุณในการลบ execute เพื่อให้ทุกอย่างสั้นลง ไชโย!
kikito

1
ไม่สำคัญว่าคุณจะมีอักขระพิเศษหรือไม่ก็ตามเป็นสิ่งที่คุณควรใส่ใจ มีปัญหาใน%การขยายตัวมากเกินไปที่จะแนะนำให้ใช้กับใครก็ได้ ไฟล์ Pseudo ใช้ในปลั๊กอินจำนวนมาก (เช่น fugitive หรือ my aurum) ดังนั้นจึงควรค่าแก่การดูแล การจัดหา vimrc ยังเป็นแนวทางปฏิบัติทั่วไป คุณสามารถมีอะไรก็ได้ที่คุณต้องการใน vimrc อย่าแนะนำเป็นคำตอบ การใช้:silent! call mkdir(expand('%:p:h'), 'p')ตัวแปรแก้ปัญหาสองจุดที่ฉันพูดถึงและประการที่สามที่ฉันไม่ได้พูดถึง: !mkdirจะไม่ทำงานบน windows
ZyX
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.