xref: /vim-8.2.3635/runtime/autoload/context.vim (revision 46fceaaa)
1" Language:           ConTeXt typesetting engine
2" Maintainer:         Nicola Vitacolonna <[email protected]>
3" Latest Revision:    2016 Oct 21
4
5let s:keepcpo= &cpo
6set cpo&vim
7
8" Helper functions {{{
9function! s:context_echo(message, mode)
10  redraw
11  echo "\r"
12  execute 'echohl' a:mode
13  echomsg '[ConTeXt]' a:message
14  echohl None
15endf
16
17function! s:sh()
18  return has('win32') || has('win64') || has('win16') || has('win95')
19        \ ? ['cmd.exe', '/C']
20        \ : ['/bin/sh', '-c']
21endfunction
22
23" For backward compatibility
24if 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
34else
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
44endif
45" }}}
46
47" ConTeXt jobs {{{
48if 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
105else " 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
125endif " has('job')
126
127function! 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
156endfunction
157
158function! 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', ''))
163endfunction
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.
168function! 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
178endfunction!
179"}}}
180
181let &cpo = s:keepcpo
182unlet s:keepcpo
183
184" vim: sw=2 fdm=marker
185