forked from aniani/vim
		
	
		
			
	
	
		
			185 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
		
		
			
		
	
	
			185 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			VimL
		
	
	
	
	
	
|   | " Language:           ConTeXt typesetting engine | ||
|  | " Maintainer:         Nicola Vitacolonna <nvitacolonna@gmail.com> | ||
|  | " 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 |