" Language: ConTeXt typesetting engine " Maintainer: Nicola Vitacolonna " Latest Revision: 2016 Oct 21 let s:keepcpo= &cpo set cpo&vim " Helper functions {{{ function! s:context_echo(message, mode) redraw echo "\r" execute 'echohl' a:mode echomsg '[ConTeXt]' a:message echohl None endf function! s:sh() return has('win32') || has('win64') || has('win16') || has('win95') \ ? ['cmd.exe', '/C'] \ : ['/bin/sh', '-c'] endfunction " For backward compatibility if exists('*win_getid') function! s:win_getid() return win_getid() endf function! s:win_id2win(winid) return win_id2win(a:winid) endf else function! s:win_getid() return winnr() endf function! s:win_id2win(winnr) return a:winnr endf endif " }}} " ConTeXt jobs {{{ if has('job') let g:context_jobs = [] " Print the status of ConTeXt jobs function! context#job_status() let l:jobs = filter(g:context_jobs, 'job_status(v:val) == "run"') let l:n = len(l:jobs) call s:context_echo( \ 'There '.(l:n == 1 ? 'is' : 'are').' '.(l:n == 0 ? 'no' : l:n) \ .' job'.(l:n == 1 ? '' : 's').' running' \ .(l:n == 0 ? '.' : ' (' . join(l:jobs, ', ').').'), \ 'ModeMsg') endfunction " Stop all ConTeXt jobs function! context#stop_jobs() let l:jobs = filter(g:context_jobs, 'job_status(v:val) == "run"') for job in l:jobs call job_stop(job) endfor sleep 1 let l:tmp = [] for job in l:jobs if job_status(job) == "run" call add(l:tmp, job) endif endfor let g:context_jobs = l:tmp if empty(g:context_jobs) call s:context_echo('Done. No jobs running.', 'ModeMsg') else call s:context_echo('There are still some jobs running. Please try again.', 'WarningMsg') endif endfunction function! context#callback(path, job, status) if index(g:context_jobs, a:job) != -1 && job_status(a:job) != 'run' " just in case call remove(g:context_jobs, index(g:context_jobs, a:job)) endif call s:callback(a:path, a:job, a:status) endfunction function! context#close_cb(channel) call job_status(ch_getjob(a:channel)) " Trigger exit_cb's callback for faster feedback endfunction function! s:typeset(path) call add(g:context_jobs, \ job_start(add(s:sh(), context#command() . ' ' . shellescape(fnamemodify(a:path, ":t"))), { \ 'close_cb' : 'context#close_cb', \ 'exit_cb' : function(get(b:, 'context_callback', get(g:, 'context_callback', 'context#callback')), \ [a:path]), \ 'in_io' : 'null' \ })) endfunction else " No jobs function! context#job_status() call s:context_echo('Not implemented', 'WarningMsg') endfunction! function! context#stop_jobs() call s:context_echo('Not implemented', 'WarningMsg') endfunction function! context#callback(path, job, status) call s:callback(a:path, a:job, a:status) endfunction function! s:typeset(path) execute '!' . context#command() . ' ' . shellescape(fnamemodify(a:path, ":t")) call call(get(b:, 'context_callback', get(g:, 'context_callback', 'context#callback')), \ [a:path, 0, v:shell_error]) endfunction endif " has('job') function! s:callback(path, job, status) abort if a:status < 0 " Assume the job was terminated return endif " Get info about the current window let l:winid = s:win_getid() " Save window id let l:efm = &l:errorformat " Save local errorformat let l:cwd = fnamemodify(getcwd(), ":p") " Save local working directory " Set errorformat to parse ConTeXt errors execute 'setl efm=' . escape(b:context_errorformat, ' ') try " Set cwd to expand error file correctly execute 'lcd' fnameescape(fnamemodify(a:path, ':h')) catch /.*/ execute 'setl efm=' . escape(l:efm, ' ') throw v:exception endtry try execute 'cgetfile' fnameescape(fnamemodify(a:path, ':r') . '.log') botright cwindow finally " Restore cwd and errorformat execute s:win_id2win(l:winid) . 'wincmd w' execute 'lcd ' . fnameescape(l:cwd) execute 'setl efm=' . escape(l:efm, ' ') endtry if a:status == 0 call s:context_echo('Success!', 'ModeMsg') else call s:context_echo('There are errors. ', 'ErrorMsg') endif endfunction function! context#command() return get(b:, 'context_mtxrun', get(g:, 'context_mtxrun', 'mtxrun')) \ . ' --script context --autogenerate --nonstopmode' \ . ' --synctex=' . (get(b:, 'context_synctex', get(g:, 'context_synctex', 0)) ? '1' : '0') \ . ' ' . get(b:, 'context_extra_options', get(g:, 'context_extra_options', '')) endfunction " Accepts an optional path (useful for big projects, when the file you are " editing is not the project's root document). If no argument is given, uses " the path of the current buffer. function! context#typeset(...) abort let l:path = fnamemodify(strlen(a:000[0]) > 0 ? a:1 : expand("%"), ":p") let l:cwd = fnamemodify(getcwd(), ":p") " Save local working directory call s:context_echo('Typesetting...', 'ModeMsg') execute 'lcd' fnameescape(fnamemodify(l:path, ":h")) try call s:typeset(l:path) finally " Restore local working directory execute 'lcd ' . fnameescape(l:cwd) endtry endfunction! "}}} let &cpo = s:keepcpo unlet s:keepcpo " vim: sw=2 fdm=marker