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
 |