diff --git a/autoload/slumlord.vim b/autoload/slumlord.vim index ac6ca25..8eb0843 100644 --- a/autoload/slumlord.vim +++ b/autoload/slumlord.vim @@ -2,11 +2,13 @@ " @Author: Martin Grenfell " @Date: 2018-12-07 13:00:22 " @Last Modified by: Tsuyoshi CHO -" @Last Modified time: 2018-12-08 00:02:38 +" @Last Modified time: 2018-12-08 13:15:46 " @License: WTFPL " PlantUML preview plugin core " Intro {{{1 +scriptencoding utf-8 + if exists("g:autoloaded_slumlord") finish endif @@ -21,7 +23,7 @@ let g:slumlord_asciiart_utf = get(g:, 'slumlord_asciiart_utf', 1) " function {{{1 function! slumlord#updatePreview(args) abort - if !s:shouldInsertPreview() + if !slumlord#util#shouldInsertPreview() return end @@ -35,7 +37,7 @@ function! slumlord#updatePreview(args) abort endif let tmpfname = tempname() - call s:mungeDiagramInTmpFile(tmpfname) + call slumlord#util#mungeDiagramInTmpFile(tmpfname) let b:slumlord_preview_fname = fnamemodify(tmpfname, ':r') . '.' . ext let cmd = "java -Dapple.awt.UIElement=true -splash: -jar ". g:slumlord_plantuml_jar_path ." -charset ". charset ." -t" . type ." ". tmpfname @@ -53,35 +55,6 @@ function! slumlord#updatePreview(args) abort endif endfunction -function! s:shouldInsertPreview() abort - "check for 'no-preview flag - if search('^\s*''no-preview', 'wn') > 0 - return - endif - - "check for state diagram - if search('^\s*\[\*\]', 'wn') > 0 - return - endif - - "check for use cases - if search('^\s*\%((.*)\|:.*:\)', 'wn') > 0 - return - endif - - "check for class diagrams - if search('^\s*class\>', 'wn') > 0 - return - endif - - "check for activity diagrams - if search('^\s*:.*;', 'wn') > 0 - return - endif - - return 1 -endfunction - function! s:asyncHandlerAdapter(job_id, data, event) abort dict if a:data != 0 return 0 @@ -94,170 +67,11 @@ function! s:asyncHandlerAdapter(job_id, data, event) abort dict call s:updater.update(self) endfunction -function! s:readWithoutStoringAsAltFile(fname) abort - let oldcpoptions = &cpoptions - set cpoptions-=a - exec 'read' a:fname - let &cpoptions = oldcpoptions -endfunction - -function! s:mungeDiagramInTmpFile(fname) abort - call writefile(getline(1, '$'), a:fname) - call s:convertNonAsciiSupportedSyntax(a:fname) -endfunction - -function! s:convertNonAsciiSupportedSyntax(fname) abort - exec 'sp' a:fname - - /@startuml/,/@enduml/s/^\s*\(boundary\|database\|entity\|control\)/participant/e - /@startuml/,/@enduml/s/^\s*\(end \)\?\zsref\>/note/e - /@startuml/,/@enduml/s/^\s*ref\>/note/e - /@startuml/,/@enduml/s/|||/||4||/e - /@startuml/,/@enduml/s/\.\.\.\([^.]*\)\.\.\./==\1==/e - write - - bwipe! -endfunction - -function! s:removeLeadingWhitespace(...) abort - let opts = a:0 ? a:1 : {} - - let diagramEnd = get(opts, 'diagramEnd', line('$')) - - let smallestLead = 100 - - for i in range(1, diagramEnd-1) - let lead = match(getline(i), '\S') - if lead >= 0 && lead < smallestLead - let smallestLead = lead - endif - endfor - - exec '1,' . diagramEnd . 's/^ \{'.smallestLead.'}//e' -endfunction - -function! s:addTitle() abort - let lnum = search('^title ', 'n') - if !lnum - return - endif - - let title = substitute(getline(lnum), '^title \(.*\)', '\1', '') - - call append(0, "") - call append(0, repeat("^", strdisplaywidth(title)+6)) - call append(0, " " . title) -endfunction - -" InPlaceUpdater object {{{1 -let s:InPlaceUpdater = {} -let s:InPlaceUpdater.divider = "@startuml" - -function! s:InPlaceUpdater.update(args) abort - let startLine = line(".") - let lastLine = line("$") - let startCol = col(".") - - call self.__deletePreviousDiagram() - call self.__insertDiagram(b:slumlord_preview_fname) - call s:addTitle() - - call cursor(line("$") - (lastLine - startLine), startCol) - - if a:args['write'] - noautocmd write - endif -endfunction - -function! s:InPlaceUpdater.__deletePreviousDiagram() abort - if self.__dividerLnum() > 1 - exec '0,' . (self.__dividerLnum() - 1) . 'delete _' - endif -endfunction - -function! s:InPlaceUpdater.__insertDiagram(fname) abort - call append(0, "") - call append(0, "") - 0 - - call s:readWithoutStoringAsAltFile(a:fname) - - "fix trailing whitespace - exec '1,' . self.__dividerLnum() . 's/\s\+$//e' - - call s:removeLeadingWhitespace() -endfunction - -function! s:InPlaceUpdater.__dividerLnum() abort - return search(self.divider, 'wn') -endfunction - -" WinUpdater object {{{1 -let s:WinUpdater = {} -function! s:WinUpdater.update(args) abort - let fname = b:slumlord_preview_fname - call self.__moveToWin() - %d - - call append(0, "") - call append(0, "") - 0 - - call s:readWithoutStoringAsAltFile(fname) - - "fix trailing whitespace - %s/\s\+$//e - - call s:removeLeadingWhitespace() - call s:addTitle() - wincmd p -endfunction - -function s:WinUpdater.__moveToWin() abort - if exists("b:slumlord_bnum") - if bufwinnr(b:slumlord_bnum) != -1 - exec bufwinnr(b:slumlord_bnum) . "wincmd w" - else - exec b:slumlord_bnum . "sb" - endif - else - let prev_bnum = bufnr("") - new - call setbufvar(prev_bnum, "slumlord_bnum", bufnr("")) - call self.__setupWinOpts() - endif -endfunction - -function s:WinUpdater.__setupWinOpts() abort - setl nowrap - setl buftype=nofile - syn match plantumlPreviewBoxParts #[┌┐└┘┬─│┴<>╚═╪╝╔═╤╪╗║╧╟╠╣]# - syn match plantumlPreviewCtrlFlow #\(LOOP\|ALT\|OPT\)[^│]*│\s*[a-zA-Z0-9?! ]*# - syn match plantumlPreviewCtrlFlow #║ \[[^]]*\]#hs=s+3,he=e-1 - syn match plantumlPreviewEntity #│\w*│#hs=s+1,he=e-1 - syn match plantumlPreviewTitleUnderline #\^\+# - syn match plantumlPreviewNoteText #║[^┌┐└┘┬─│┴<>╚═╪╝╔═╤╪╗║╧╟╠╣]*[░ ]║#hs=s+1,he=e-2 - syn match plantumlPreviewDividerText #╣[^┌┐└┘┬─│┴<>╚═╪╝╔═╤╪╗║╧╟╣]*╠#hs=s+1,he=e-1 - syn match plantumlPreviewMethodCall #\(\(│\|^\)\s*\)\@<=[a-zA-Z_]*([[:alnum:],_ ]*)# - syn match plantumlPreviewMethodCallParen #[()]# containedin=plantumlPreviewMethodCall contained - - hi def link plantumlPreviewBoxParts normal - hi def link plantumlPreviewCtrlFlow Keyword - hi def link plantumlPreviewLoopName Statement - hi def link plantumlPreviewEntity Statement - hi def link plantumlPreviewTitleUnderline Statement - hi def link plantumlPreviewNoteText Constant - hi def link plantumlPreviewDividerText Constant - hi def link plantumlPreviewMethodCall plantumlText - hi def link plantumlPreviewMethodCallParen plantumlColonLine -endfunction - - " other shit {{{1 if exists("g:slumlord_separate_win") && g:slumlord_separate_win - let s:updater = s:WinUpdater + let s:updater = slumlord#WinUpdater#getInstance() else - let s:updater = s:InPlaceUpdater + let s:updater = slumlord#InPlaceUpdater#getInstance() endif " Outro {{{1 diff --git a/autoload/slumlord/InPlaceUpdater.vim b/autoload/slumlord/InPlaceUpdater.vim new file mode 100644 index 0000000..2c1f0a9 --- /dev/null +++ b/autoload/slumlord/InPlaceUpdater.vim @@ -0,0 +1,59 @@ +" PlantUML Live Preview for ascii/unicode art +" @Author: Martin Grenfell +" @Date: 2018-12-07 13:00:22 +" @Last Modified by: Tsuyoshi CHO +" @Last Modified time: 2018-12-08 00:11:32 +" @License: WTFPL +" PlantUML preview plugin InPlace Updater + +" Intro {{{1 +scriptencoding utf-8 + +" InPlaceUpdater object {{{1 +let s:InPlaceUpdater = {} +let s:InPlaceUpdater.divider = "@startuml" + +function! slumlord#InPlaceUpdater#getInstance() abort + return deepcopy(s:InPlaceUpdater) +endfunction + +function! s:InPlaceUpdater.update(args) abort dict + let startLine = line(".") + let lastLine = line("$") + let startCol = col(".") + + call self.__deletePreviousDiagram() + call self.__insertDiagram(b:slumlord_preview_fname) + call slumlord#util#addTitle() + + call cursor(line("$") - (lastLine - startLine), startCol) + + if a:args['write'] + noautocmd write + endif +endfunction + +function! s:InPlaceUpdater.__deletePreviousDiagram() abort dict + if self.__dividerLnum() > 1 + exec '0,' . (self.__dividerLnum() - 1) . 'delete _' + endif +endfunction + +function! s:InPlaceUpdater.__insertDiagram(fname) abor dictt + call append(0, "") + call append(0, "") + 0 + + call slumlord#util#readWithoutStoringAsAltFile(a:fname) + + "fix trailing whitespace + exec '1,' . self.__dividerLnum() . 's/\s\+$//e' + + call slumlord#util#removeLeadingWhitespace() +endfunction + +function! s:InPlaceUpdater.__dividerLnum() abor dictt + return search(self.divider, 'wn') +endfunction + +" vim:set fdm=marker: diff --git a/autoload/slumlord/WinUpdater.vim b/autoload/slumlord/WinUpdater.vim new file mode 100644 index 0000000..d5b1faa --- /dev/null +++ b/autoload/slumlord/WinUpdater.vim @@ -0,0 +1,77 @@ +" PlantUML Live Preview for ascii/unicode art +" @Author: Martin Grenfell +" @Date: 2018-12-07 13:00:22 +" @Last Modified by: Tsuyoshi CHO +" @Last Modified time: 2018-12-08 00:11:42 +" @License: WTFPL +" PlantUML preview plugin Window Updater + +" Intro {{{1 +scriptencoding utf-8 + +" WinUpdater object {{{1 +let s:WinUpdater = {} + +function! slumlord#WinUpdater#getInstance() abort + return deepcopy(s:WinUpdater) +endfunction + +function! s:WinUpdater.update(args) abort dict + let fname = b:slumlord_preview_fname + call self.__moveToWin() + %d + + call append(0, "") + call append(0, "") + 0 + + call slumlord#util#readWithoutStoringAsAltFile(fname) + + "fix trailing whitespace + %s/\s\+$//e + + call slumlord#util#removeLeadingWhitespace() + call slumlord#util#addTitle() + wincmd p +endfunction + +function s:WinUpdater.__moveToWin() abort dict + if exists("b:slumlord_bnum") + if bufwinnr(b:slumlord_bnum) != -1 + exec bufwinnr(b:slumlord_bnum) . "wincmd w" + else + exec b:slumlord_bnum . "sb" + endif + else + let prev_bnum = bufnr("") + new + call setbufvar(prev_bnum, "slumlord_bnum", bufnr("")) + call self.__setupWinOpts() + endif +endfunction + +function s:WinUpdater.__setupWinOpts() abort dict + setl nowrap + setl buftype=nofile + syn match plantumlPreviewBoxParts #[┌┐└┘┬─│┴<>╚═╪╝╔═╤╪╗║╧╟╠╣]# + syn match plantumlPreviewCtrlFlow #\(LOOP\|ALT\|OPT\)[^│]*│\s*[a-zA-Z0-9?! ]*# + syn match plantumlPreviewCtrlFlow #║ \[[^]]*\]#hs=s+3,he=e-1 + syn match plantumlPreviewEntity #│\w*│#hs=s+1,he=e-1 + syn match plantumlPreviewTitleUnderline #\^\+# + syn match plantumlPreviewNoteText #║[^┌┐└┘┬─│┴<>╚═╪╝╔═╤╪╗║╧╟╠╣]*[░ ]║#hs=s+1,he=e-2 + syn match plantumlPreviewDividerText #╣[^┌┐└┘┬─│┴<>╚═╪╝╔═╤╪╗║╧╟╣]*╠#hs=s+1,he=e-1 + syn match plantumlPreviewMethodCall #\(\(│\|^\)\s*\)\@<=[a-zA-Z_]*([[:alnum:],_ ]*)# + syn match plantumlPreviewMethodCallParen #[()]# containedin=plantumlPreviewMethodCall contained + + hi def link plantumlPreviewBoxParts normal + hi def link plantumlPreviewCtrlFlow Keyword + hi def link plantumlPreviewLoopName Statement + hi def link plantumlPreviewEntity Statement + hi def link plantumlPreviewTitleUnderline Statement + hi def link plantumlPreviewNoteText Constant + hi def link plantumlPreviewDividerText Constant + hi def link plantumlPreviewMethodCall plantumlText + hi def link plantumlPreviewMethodCallParen plantumlColonLine +endfunction + +" vim:set fdm=marker: diff --git a/autoload/slumlord/util.vim b/autoload/slumlord/util.vim new file mode 100644 index 0000000..286e71f --- /dev/null +++ b/autoload/slumlord/util.vim @@ -0,0 +1,98 @@ +" PlantUML Live Preview for ascii/unicode art +" @Author: Martin Grenfell +" @Date: 2018-12-07 13:00:22 +" @Last Modified by: Tsuyoshi CHO +" @Last Modified time: 2018-12-08 00:11:36 +" @License: WTFPL +" PlantUML preview plugin util + +" Intro {{{1 +scriptencoding utf-8 + +" function {{{1 + +function! slumlord#util#shouldInsertPreview() abort + "check for 'no-preview flag + if search('^\s*''no-preview', 'wn') > 0 + return + endif + + "check for state diagram + if search('^\s*\[\*\]', 'wn') > 0 + return + endif + + "check for use cases + if search('^\s*\%((.*)\|:.*:\)', 'wn') > 0 + return + endif + + "check for class diagrams + if search('^\s*class\>', 'wn') > 0 + return + endif + + "check for activity diagrams + if search('^\s*:.*;', 'wn') > 0 + return + endif + + return 1 +endfunction + +function! slumlord#util#readWithoutStoringAsAltFile(fname) abort + let oldcpoptions = &cpoptions + set cpoptions-=a + exec 'read' a:fname + let &cpoptions = oldcpoptions +endfunction + +function! slumlord#util#mungeDiagramInTmpFile(fname) abort + call writefile(getline(1, '$'), a:fname) + call slumlord#util#convertNonAsciiSupportedSyntax(a:fname) +endfunction + +function! slumlord#util#convertNonAsciiSupportedSyntax(fname) abort + exec 'sp' a:fname + + /@startuml/,/@enduml/s/^\s*\(boundary\|database\|entity\|control\)/participant/e + /@startuml/,/@enduml/s/^\s*\(end \)\?\zsref\>/note/e + /@startuml/,/@enduml/s/^\s*ref\>/note/e + /@startuml/,/@enduml/s/|||/||4||/e + /@startuml/,/@enduml/s/\.\.\.\([^.]*\)\.\.\./==\1==/e + write + + bwipe! +endfunction + +function! slumlord#util#removeLeadingWhitespace(...) abort + let opts = a:0 ? a:1 : {} + + let diagramEnd = get(opts, 'diagramEnd', line('$')) + + let smallestLead = 100 + + for i in range(1, diagramEnd-1) + let lead = match(getline(i), '\S') + if lead >= 0 && lead < smallestLead + let smallestLead = lead + endif + endfor + + exec '1,' . diagramEnd . 's/^ \{'.smallestLead.'}//e' +endfunction + +function! slumlord#util#addTitle() abort + let lnum = search('^title ', 'n') + if !lnum + return + endif + + let title = substitute(getline(lnum), '^title \(.*\)', '\1', '') + + call append(0, "") + call append(0, repeat("^", strdisplaywidth(title)+6)) + call append(0, " " . title) +endfunction + +" vim:set fdm=marker: diff --git a/ftplugin/plantuml.vim b/ftplugin/plantuml.vim index 20ad18d..0f9d76d 100644 --- a/ftplugin/plantuml.vim +++ b/ftplugin/plantuml.vim @@ -2,11 +2,13 @@ " @Author: Martin Grenfell " @Date: 2018-12-07 13:00:22 " @Last Modified by: Tsuyoshi CHO -" @Last Modified time: 2018-12-08 00:02:43 +" @Last Modified time: 2018-12-08 13:15:40 " @License: WTFPL " PlantUML Filetype preview kick " Intro {{{1 +scriptencoding utf-8 + if exists("b:loaded_slumlord") finish endif diff --git a/syntax/plantuml.vim b/syntax/plantuml.vim index e820427..f441d91 100644 --- a/syntax/plantuml.vim +++ b/syntax/plantuml.vim @@ -2,10 +2,14 @@ " @Author: Martin Grenfell " @Date: 2018-12-07 13:00:22 " @Last Modified by: Tsuyoshi CHO -" @Last Modified time: 2018-12-08 00:02:47 +" @Last Modified time: 2018-12-08 13:15:31 " @License: WTFPL " PlantUML Filetype preview syntax +" Intro {{{1 +scriptencoding utf-8 + +" syntax {{{1 syn region plantumlPreview start=#\%^\ze\_.*\n@startuml# end=#\ze@startuml# syn match plantumlPreviewBoxParts #[┌┐└┘┬─│┴<>╚═╪╝╔═╤╪╗║╧╟╠╣]# containedin=plantumlPreview contained syn match plantumlPreviewCtrlFlow #\(LOOP\|ALT\|OPT\)[^│]*│\s*[a-zA-Z0-9?! ]*# containedin=plantumlPreview contains=plantumlPreviewBoxParts contained @@ -17,6 +21,7 @@ syn match plantumlPreviewDividerText #╣[^┌┐└┘┬─│┴<>╚═╪ syn match plantumlPreviewMethodCall #\(\(│\|^\)\s*\)\@<=[a-zA-Z_]*([[:alnum:],_ ]*)# containedin=plantumlPreview contained syn match plantumlPreviewMethodCallParen #[()]# containedin=plantumlPreviewMethodCall contained +" highlight {{{1 hi def link plantumlPreview Normal hi def link plantumlPreviewBoxParts normal hi def link plantumlPreviewCtrlFlow Keyword @@ -28,4 +33,4 @@ hi def link plantumlPreviewDividerText Constant hi def link plantumlPreviewMethodCall plantumlText hi def link plantumlPreviewMethodCallParen plantumlColonLine -" vim: ft=vim +" vim:set ft=vim fdm=marker: