context.vim (5462B)
1 " Language: ConTeXt typesetting engine 2 " Maintainer: Nicola Vitacolonna <nvitacolonna@gmail.com> 3 " Latest Revision: 2016 Oct 21 4 5 let s:keepcpo= &cpo 6 set cpo&vim 7 8 " Helper functions {{{ 9 function! s:context_echo(message, mode) 10 redraw 11 echo "\r" 12 execute 'echohl' a:mode 13 echomsg '[ConTeXt]' a:message 14 echohl None 15 endf 16 17 function! s:sh() 18 return has('win32') || has('win64') || has('win16') || has('win95') 19 \ ? ['cmd.exe', '/C'] 20 \ : ['/bin/sh', '-c'] 21 endfunction 22 23 " For backward compatibility 24 if exists('*win_getid') 25 26 function! s:win_getid() 27 return win_getid() 28 endf 29 30 function! s:win_id2win(winid) 31 return win_id2win(a:winid) 32 endf 33 34 else 35 36 function! s:win_getid() 37 return winnr() 38 endf 39 40 function! s:win_id2win(winnr) 41 return a:winnr 42 endf 43 44 endif 45 " }}} 46 47 " ConTeXt jobs {{{ 48 if has('job') 49 50 let g:context_jobs = [] 51 52 " Print the status of ConTeXt jobs 53 function! context#job_status() 54 let l:jobs = filter(g:context_jobs, 'job_status(v:val) == "run"') 55 let l:n = len(l:jobs) 56 call s:context_echo( 57 \ 'There '.(l:n == 1 ? 'is' : 'are').' '.(l:n == 0 ? 'no' : l:n) 58 \ .' job'.(l:n == 1 ? '' : 's').' running' 59 \ .(l:n == 0 ? '.' : ' (' . join(l:jobs, ', ').').'), 60 \ 'ModeMsg') 61 endfunction 62 63 " Stop all ConTeXt jobs 64 function! context#stop_jobs() 65 let l:jobs = filter(g:context_jobs, 'job_status(v:val) == "run"') 66 for job in l:jobs 67 call job_stop(job) 68 endfor 69 sleep 1 70 let l:tmp = [] 71 for job in l:jobs 72 if job_status(job) == "run" 73 call add(l:tmp, job) 74 endif 75 endfor 76 let g:context_jobs = l:tmp 77 if empty(g:context_jobs) 78 call s:context_echo('Done. No jobs running.', 'ModeMsg') 79 else 80 call s:context_echo('There are still some jobs running. Please try again.', 'WarningMsg') 81 endif 82 endfunction 83 84 function! context#callback(path, job, status) 85 if index(g:context_jobs, a:job) != -1 && job_status(a:job) != 'run' " just in case 86 call remove(g:context_jobs, index(g:context_jobs, a:job)) 87 endif 88 call s:callback(a:path, a:job, a:status) 89 endfunction 90 91 function! context#close_cb(channel) 92 call job_status(ch_getjob(a:channel)) " Trigger exit_cb's callback for faster feedback 93 endfunction 94 95 function! s:typeset(path) 96 call add(g:context_jobs, 97 \ job_start(add(s:sh(), context#command() . ' ' . shellescape(fnamemodify(a:path, ":t"))), { 98 \ 'close_cb' : 'context#close_cb', 99 \ 'exit_cb' : function(get(b:, 'context_callback', get(g:, 'context_callback', 'context#callback')), 100 \ [a:path]), 101 \ 'in_io' : 'null' 102 \ })) 103 endfunction 104 105 else " No jobs 106 107 function! context#job_status() 108 call s:context_echo('Not implemented', 'WarningMsg') 109 endfunction! 110 111 function! context#stop_jobs() 112 call s:context_echo('Not implemented', 'WarningMsg') 113 endfunction 114 115 function! context#callback(path, job, status) 116 call s:callback(a:path, a:job, a:status) 117 endfunction 118 119 function! s:typeset(path) 120 execute '!' . context#command() . ' ' . shellescape(fnamemodify(a:path, ":t")) 121 call call(get(b:, 'context_callback', get(g:, 'context_callback', 'context#callback')), 122 \ [a:path, 0, v:shell_error]) 123 endfunction 124 125 endif " has('job') 126 127 function! s:callback(path, job, status) abort 128 if a:status < 0 " Assume the job was terminated 129 return 130 endif 131 " Get info about the current window 132 let l:winid = s:win_getid() " Save window id 133 let l:efm = &l:errorformat " Save local errorformat 134 let l:cwd = fnamemodify(getcwd(), ":p") " Save local working directory 135 " Set errorformat to parse ConTeXt errors 136 execute 'setl efm=' . escape(b:context_errorformat, ' ') 137 try " Set cwd to expand error file correctly 138 execute 'lcd' fnameescape(fnamemodify(a:path, ':h')) 139 catch /.*/ 140 execute 'setl efm=' . escape(l:efm, ' ') 141 throw v:exception 142 endtry 143 try 144 execute 'cgetfile' fnameescape(fnamemodify(a:path, ':r') . '.log') 145 botright cwindow 146 finally " Restore cwd and errorformat 147 execute s:win_id2win(l:winid) . 'wincmd w' 148 execute 'lcd ' . fnameescape(l:cwd) 149 execute 'setl efm=' . escape(l:efm, ' ') 150 endtry 151 if a:status == 0 152 call s:context_echo('Success!', 'ModeMsg') 153 else 154 call s:context_echo('There are errors. ', 'ErrorMsg') 155 endif 156 endfunction 157 158 function! context#command() 159 return get(b:, 'context_mtxrun', get(g:, 'context_mtxrun', 'mtxrun')) 160 \ . ' --script context --autogenerate --nonstopmode' 161 \ . ' --synctex=' . (get(b:, 'context_synctex', get(g:, 'context_synctex', 0)) ? '1' : '0') 162 \ . ' ' . get(b:, 'context_extra_options', get(g:, 'context_extra_options', '')) 163 endfunction 164 165 " Accepts an optional path (useful for big projects, when the file you are 166 " editing is not the project's root document). If no argument is given, uses 167 " the path of the current buffer. 168 function! context#typeset(...) abort 169 let l:path = fnamemodify(strlen(a:000[0]) > 0 ? a:1 : expand("%"), ":p") 170 let l:cwd = fnamemodify(getcwd(), ":p") " Save local working directory 171 call s:context_echo('Typesetting...', 'ModeMsg') 172 execute 'lcd' fnameescape(fnamemodify(l:path, ":h")) 173 try 174 call s:typeset(l:path) 175 finally " Restore local working directory 176 execute 'lcd ' . fnameescape(l:cwd) 177 endtry 178 endfunction! 179 "}}} 180 181 let &cpo = s:keepcpo 182 unlet s:keepcpo 183 184 " vim: sw=2 fdm=marker