Browse Source

Initial commit

Emmanuel Bouthenot 9 years ago
commit
6c70e4a47c
1 changed files with 128 additions and 0 deletions
  1. 128 0
      plugin/bindzone.vim

+ 128 - 0
plugin/bindzone.vim

@@ -0,0 +1,128 @@
+" File: bindzone.vim
+" Description: Edit Bind zones safely
+" Author: Emmanuel Bouthenot <kolter@openics.org>
+" Version: 0.2
+" Last Modified: November 30, 2014
+" License: WTFPLv2 (see http://sam.zoy.org/wtfpl/)
+" Changelog:
+"  0.1: Initial Release
+"  0.2: Make it compatible vim plugins managers
+
+if exists("loadedBindZone")
+    finish
+endif
+
+if !executable('named-checkzone')
+    echo "Error while loading bindzone.vim: unable to find 'named-checkzone' executable"
+    finish
+endif
+
+let loadedBindZone = 1
+
+autocmd FileType bindzone execute('call BindZoneApply()')
+
+function BindZoneApply()
+    autocmd BufWriteCmd <buffer> execute('call BindZoneChecker()')
+endfunction
+
+function BindUpdateSerial()
+    let s:bufferLines = getbufline(bufnr("%"), 1, "$")
+    let s:lineNumber = 0
+    for s:line in s:bufferLines
+        let s:lineNumber += 1
+        let s:serial = matchlist(s:line, '^\(\s*\)\(2\d\{7\}\)\(\d\{2\}\)\(\s*;\s*Serial.*\)$')
+        if s:serial != []
+            if (strftime("%Y%m%d") == s:serial[2])
+                let s:newserial = s:serial[2] . s:serial[3]+1
+            else
+                let s:newserial = strftime("%Y%m%d") . '01'
+            endif
+            call setline(s:lineNumber, s:serial[1] . s:newserial . s:serial[4])
+            call cursor(s:lineNumber, strlen(s:serial[1] . s:newserial)+1)
+            execute('highlight BindSerial ctermbg=red guibg=red ctermfg=white guifg=white')
+            call matchadd("BindSerial", s:newserial)
+            break
+        endif
+    endfor
+endfunction
+
+nmap <C-_> :call BindUpdateSerial()<CR>
+
+function BindZoneChecker()
+    let s:currentFile = expand("%")
+    let s:bufferContents = getbufline(bufnr("%"), 1, "$")
+    let s:domain = matchlist(s:bufferContents, '^\$ORIGIN\s\+\(\S\+\)')
+    if s:domain != []
+
+        " If the file isn't writable don't do anything (as it could lock it up)
+        if filewritable(s:currentFile)
+            let s:zoneFile = tempname()
+            exe writefile(s:bufferContents, s:zoneFile)
+
+            " Check if the zone file got written (prevent disk space full)
+            if filereadable(s:zoneFile)
+                let s:output = system('named-checkzone ' . s:domain[1] . ' ' . s:zoneFile)
+                let s:output = substitute(s:output, s:zoneFile, s:currentFile, 'g')
+                call delete(s:zoneFile)
+
+                " Check if the zone is correct
+                let s:okMatch = matchstr(s:output, '\nOK\n')
+                if s:okMatch != ''
+                    cclose
+                    " Avoids the annoying “Press ENTER to …” message
+                    if &modified
+                        call BindUpdateSerial()
+                    endif
+                    " Finally, we have to write the file
+                    noautocmd w
+                    " Avoids the annoying “Press ENTER to …” message
+                    redraw
+                else
+                    let s:outputLines = split(s:output, "\n")
+                    let s:errorLines = []
+                    for s:line in s:outputLines
+                        let s:errorLine = matchlist(s:line, '^\(.\+\):\(\d\+\):\s\+\(.*\)$')
+                        if s:errorLine != []
+                            call add(s:errorLines, s:currentFile . ':' . s:errorLine[2] . ':' . s:errorLine[3])
+                        endif
+                    endfor
+
+                    " if it was impossible to detect errors properly, we still
+                    " had them to the error console in a “raw” way
+                    if s:errorLines == []
+                        for s:line in s:outputLines
+                            call add(s:errorLines, s:currentFile . ':0:' . s:line)
+                        endfor
+                    endif
+
+                    let s:cFile = tempname()
+                    exe writefile(s:errorLines, s:cFile)
+                    let s:errorWindowHeight = len(s:errorLines)+2
+                    " Limiting the error window rows
+                    if s:errorWindowHeight >= 15
+                        let s:errorWindowHeight = 15
+                    endif
+
+                    let s:oldCpoptions = &cpoptions
+                    let s:oldErrorFormat = &errorformat
+
+                    set cpoptions-=F
+                    set errorformat=%f:%l:%m
+
+                    execute('cfile ' . s:cFile)
+                    execute('botright cwindow ' . s:errorWindowHeight)
+                    call delete(s:cFile)
+
+                    let &cpoptions = s:oldCpoptions
+                    let &errorformat = s:oldErrorFormat
+
+                    redraw
+                    return
+                endif
+            endif
+        endif
+    endif
+    if s:currentFile != ''
+    endif
+endfunction
+