neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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