" Vimball Archiver by Charles E. Campbell, Jr., Ph.D. UseVimball finish autoload/atplib.vim [[[1 601 " Title: Vim library for ATP filetype plugin. " Author: Marcin Szamotulski " Email: mszamot [AT] gmail [DOT] com " Note: This file is a part of Automatic Tex Plugin for Vim. " URL: https://launchpad.net/automatictexplugin " Language: tex " Source ATPRC File: function! atplib#ReadATPRC() "{{{ if ( has("unix") || has("max") || has("macunix") ) " Note: in $HOME/.atprc file the user can set all the local buffer " variables without using autocommands " " Note: it must be sourced at the begining because some options handle " how atp will load (for example if we load history or not) " It also should be run at the end if the user defines mapping that " should be overwrite the ATP settings (this is done via " autocommand). let atprc_file=get(split(globpath($HOME, '.atprc.vim', 1), "\n"), 0, "") if !filereadable(atprc_file) let atprc_file = get(split(globpath(&rtp, "**/ftplugin/ATP_files/atprc.vim"), '\n'), 0, "") endif if filereadable(atprc_file) execute 'source ' . fnameescape(atprc_file) endif else let atprc_file = get(split(globpath(&rtp, "**/ftplugin/ATP_files/atprc.vim"), '\n'), 0, "") if filereadable(atprc_file) execute 'source ' . fnameescape(atprc_file) endif endif endfunction "}}} " Kill: function! atplib#KillPIDs(pids,...) "{{{ if len(a:pids) == 0 && a:0 == 0 return endif python << END import os, signal from signal import SIGKILL pids=vim.eval("a:pids") for pid in pids: try: os.kill(int(pid),SIGKILL) except OSError: pass END endfunction "}}} " Write: function! atplib#write(...) "{{{ let backup = &backup let writebackup = &writebackup let project = b:atp_ProjectScript " In this way lastchange plugin will work better (?): " let eventignore = &eventignore " setl eventigonre +=BufWritePre " Disable WriteProjectScript let b:atp_ProjectScript = 0 set nobackup set nowritebackup if a:0 > 0 && a:1 == "silent" silent! update else update endif let b:atp_ProjectScript = project let &backup = backup let &writebackup = writebackup " let &eventignore = eventignore endfunction "}}} " Log: function! atplib#Log(file, string, ...) "{{{1 if finddir(g:atp_TempDir, "/") == "" call mkdir(g:atp_TempDir, "p", 0700) endif if a:0 >= 1 call delete(g:atp_TempDir."/".a:file) else exe "redir >> ".g:atp_TempDir."/".a:file silent echo a:string redir END endif endfunction "}}}1 "Make g:atp_TempDir, where log files are stored. "{{{1 function! atplib#TempDir() " Return temporary directory, unique for each user. if has("python") function! ATP_SetTempDir(tmp) let g:atp_TempDir=a:tmp endfunction python << END import vim, tempfile, os USER=os.getenv("USER") tmp=tempfile.mkdtemp(suffix="", prefix="atp_") vim.eval("ATP_SetTempDir('"+tmp+"')") END delfunction ATP_SetTempDir else let g:atp_TempDir=substitute(tempname(), '\d\+$', "atp_debug", '') call mkdir(g:atp_TempDir, "p", 0700) endif endfunction "}}}1 " Outdir: append to '/' to b:atp_OutDir if it is not present. function! atplib#outdir() "{{{1 if has("win16") || has("win32") || has("win64") || has("win95") if b:atp_OutDir !~ "\/$" let b:atp_OutDir=b:atp_OutDir . "\\" endif else if b:atp_OutDir !~ "\/$" let b:atp_OutDir=b:atp_OutDir . "/" endif endif return b:atp_OutDir endfunction "}}}1 " Return {path} relative to {rel}, if not under {rel} return {path} function! atplib#RelativePath(path, rel) "{{{1 let current_dir = getcwd() exe "lcd " . fnameescape(a:rel) let rel_path = fnamemodify(a:path, ':.') exe "lcd " . fnameescape(current_dir) return rel_path endfunction "}}}1 " Return fullpath function! atplib#FullPath(file_name) "{{{1 let cwd = getcwd() if a:file_name =~ '^\s*\/' let file_path = a:file_name elseif exists("b:atp_ProjectDir") try exe "lcd " . fnameescape(b:atp_ProjectDir) let file_path = fnamemodify(a:file_name, ":p") exe "lcd " . fnameescape(cwd) catch /E344:/ let file_path = fnamemodify(a:file_name, ":p") endtry else let file_path = fnamemodify(a:file_name, ":p") endif return file_path endfunction "}}}1 " Table: "{{{ atplibTable, atplib#FormatListinColumns, atplib#PrintTable function! atplib#Table(list, spaces) " take a list of lists and make a list which is nicely formated (to echo it) " spaces = list of spaces between columns. "maximal length of columns: let max_list=[] let new_list=[] for i in range(len(a:list[0])) let max=max(map(deepcopy(a:list), "len(v:val[i])")) call add(max_list, max) endfor for row in a:list let new_row=[] let i=0 for el in row let new_el=el.join(map(range(max([0,max_list[i]-len(el)+get(a:spaces,i,0)])), "' '"), "") call add(new_row, new_el) let i+=1 endfor call add(new_list, new_row) endfor return map(new_list, "join(v:val, '')") endfunction function! atplib#FormatListinColumns(list,s) " take a list and reformat it into many columns " a:s is the number of spaces between columns " for example of usage see atplib#PrintTable let max_len=max(map(copy(a:list), 'len(v:val)')) let new_list=[] let k=&l:columns/(max_len+a:s) let len=len(a:list) let column_len=len/k for i in range(0, column_len) let entry=[] for j in range(0,k) call add(entry, get(a:list, i+j*(column_len+1), "")) endfor call add(new_list,entry) endfor return new_list endfunction " Take list format it with atplib#FormatListinColumns and then with " atplib#Table (which makes columns of equal width) function! atplib#PrintTable(list, spaces) " a:list - list to print " a:spaces - nr of spaces between columns let list = atplib#FormatListinColumns(a:list, a:spaces) let nr_of_columns = max(map(copy(list), 'len(v:val)')) let spaces_list = ( nr_of_columns == 1 ? [0] : map(range(1,nr_of_columns-1), 'a:spaces') ) return atplib#Table(list, spaces_list) endfunction "}}} " QFLength "{{{ function! atplib#qflength() let lines = 1 " i.e. open with one more line than needed. for qf in getqflist() let text=substitute(qf['text'], '\_s\+', ' ', 'g') let lines+=(len(text))/&l:columns+1 endfor return lines endfunction "}}} function! atplib#Let(varname, varvalue) exe "let ".substitute(string(a:varname), "'", "", "g")."=".substitute(string(a:varvalue), "''\\@!", "", "g") endfunction " IMap Functions: " {{{ " These maps extend ideas from TeX_9 plugin: " With a:1 = "!" (bang) remove texMathZoneT (tikzpicture from MathZones). function! atplib#IsInMath(...) let line = a:0 >= 2 ? a:2 : line(".") let col = a:0 >= 3 ? a:3 : col(".")-1 if a:0 > 0 && a:1 == "!" let atp_MathZones=filter(copy(g:atp_MathZones), "v:val != 'texMathZoneT'") else let atp_MathZones=copy(g:atp_MathZones) endif call filter(atp_MathZones, 'v:val !~ ''\''') if atplib#complete#CheckSyntaxGroups(['texMathZoneV', 'texMathZoneW', 'texMathZoneX', 'texMathZoneY']) return 1 else return atplib#complete#CheckSyntaxGroups(atp_MathZones, line, col) && \ !atplib#complete#CheckSyntaxGroups(['texMathText'], line, col) endif endfunction function! atplib#MakeMaps(maps, ...) let aucmd = ( a:0 >= 1 ? a:1 : '' ) for map in a:maps if map[3] != "" && ( !exists(map[5]) || {map[5]} > 0 || \ exists(map[5]) && {map[5]} == 0 && aucmd == 'InsertEnter' ) if exists(map[5]) && {map[5]} == 0 && aucmd == 'InsertEnter' exe "let ".map[5]." =1" endif exe map[0]." ".map[1]." ".map[2].map[3]." ".map[4] endif endfor endfunction function! atplib#DelMaps(maps) for map in a:maps let cmd = matchstr(map[0], '[^m]\ze\%(nore\)\=map') . "unmap" let arg = ( map[1] =~ '' ? '' : '' ) try exe cmd." ".arg." ".map[2].map[3] catch /E31:/ endtry endfor endfunction " From TeX_nine plugin: function! atplib#IsLeft(lchar,...) let nr = ( a:0 >= 1 ? a:1 : 0 ) let left = getline('.')[col('.')-2-nr] if left ==# a:lchar return 1 else return 0 endif endfunction " try function! atplib#ToggleIMaps(var, augroup, ...) if exists("s:isinmath") && \ ( atplib#IsInMath() == s:isinmath ) && \ ( a:0 >= 2 && a:2 ) && \ a:augroup == 'CursorMovedI' return endif call SetMathVimOptions() if atplib#IsInMath() call atplib#MakeMaps(a:var, a:augroup) else call atplib#DelMaps(a:var) if a:0 >= 1 && len(a:1) call atplib#MakeMaps(a:1) endif endif let s:isinmath = atplib#IsInMath() endfunction " catch E127 " endtry "}}} " Toggle On/Off Completion " {{{1 atplib#OnOffComp function! atplib#OnOffComp(ArgLead, CmdLine, CursorPos) return filter(['on', 'off'], 'v:val =~ "^" . a:ArgLead') endfunction "}}}1 " Find Vim Server: find server 'hosting' a file and move to the line. " {{{1 atplib#FindAndOpen " Can be used to sync gvim with okular. " just set in okular: " settings>okular settings>Editor " Editor Custom Text Editor " Command gvim --servername GVIM --remote-expr "atplib#FindAndOpen('%f','%l', '%c')" " You can also use this with vim but you should start vim with " vim --servername VIM " and use servername VIM in the Command above. function! atplib#ServerListOfFiles() exe "redir! > " . g:atp_TempDir."/ServerListOfFiles.log" let file_list = [] for nr in range(1, bufnr('$')-1) " map fnamemodify(v:val, ":p") is not working if we are in another " window with file in another dir. So we are not using this (it might " happen that we end up in a wrong server though). let files = getbufvar(nr, "ListOfFiles") let main_file = getbufvar(nr, "atp_MainFile") if string(files) != "" call add(file_list, main_file) endif if string(main_file) != "" call extend(file_list, files) endif endfor call filter(file_list, 'v:val != ""') redir end return file_list endfunction function! atplib#FindAndOpen(file, line, ...) let col = ( a:0 >= 1 && a:1 > 0 ? a:1 : 1 ) let file = ( fnamemodify(a:file, ":e") == "tex" ? a:file : fnamemodify(a:file, ":p:r") . ".tex" ) let file_t = fnamemodify(file, ":t") let server_list = split(serverlist(), "\n") exe "redir! > /tmp/FindAndOpen.log" if len(server_list) == 0 return 1 endif let use_server = "" let use_servers = [] for server in server_list let file_list=split(remote_expr(server, 'atplib#ServerListOfFiles()'), "\n") let cond_1 = (index(file_list, file) != "-1") let cond_2 = (index(file_list, file_t) != "-1") if cond_1 let use_server = server break elseif cond_2 call add(use_servers, server) endif endfor " If we could not find file name with full path in server list use the " first server where is fnamemodify(file, ":t"). if use_server == "" let use_server=get(use_servers, 0, "") endif if use_server != "" call system(v:progname." --servername ".use_server." --remote-wait +".a:line." ".fnameescape(file) . " &") " Test this for file names with spaces let bufwinnr = remote_expr(use_server, 'bufwinnr("'.file.'")') if bufwinnr == "-1" " " The buffer is in a different tab page. let tabpage = 1 " " Find the correct tabpage: for tabnr in range(1, remote_expr(use_server, 'tabpagenr("$")')) let tabbuflist = split(remote_expr(use_server, 'tabpagebuflist("'.tabnr.'")'), "\n") let tabbuflist_names = split(remote_expr(use_server, 'map(tabpagebuflist("'.tabnr.'"), "bufname(v:val)")'), "\n") if count(tabbuflist_names, file) || count(tabfublist_names, file_t) let tabpage = tabnr break endif endfor " Goto to the tabpage: if remote_expr(use_server, 'tabpagenr()') != tabpage call remote_send(use_server, ':tabnext '.tabpage.'') endif " Check the bufwinnr once again: let bufwinnr = remote_expr(use_server, 'bufwinnr("'.file.'")') endif " winnr() doesn't work remotely, this is a substitute: let remote_file = remote_expr(use_server, 'expand("%:t")') if remote_file != file_t call remote_send(use_server, ":".bufwinnr."wincmd w") else " Set the ' mark, cursor position and redraw: call remote_send(use_server, ":normal! 'm `':call cursor(".a:line.",".a:col."):redraw") endif return use_server endfunction "}}}1 " Various Comparing Functions: "{{{1 atplib#CompareNumbers function! atplib#CompareNumbers(i1, i2) return ( str2nr(a:i1) == str2nr(a:i2) ? 0 : ( str2nr(a:i1) > str2nr(a:i2) ? 1 : -1 ) ) endfunction "}}}1 " {{{1 atplib#CompareCoordinates " Each list is an argument with two values: " listA=[ line_nrA, col_nrA] usually given by searchpos() function " listB=[ line_nrB, col_nrB] " returns 1 iff A is before B fun! atplib#CompareCoordinates(listA,listB) if a:listA[0] < a:listB[0] || \ a:listA[0] == a:listB[0] && a:listA[1] < a:listB[1] || \ a:listA == [0,0] " the meaning of the last is that if the searchpos() has not found the " beginning (a:listA) then it should return 1 : the env is not started. return 1 else return 0 endif endfun "}}}1 " {{{1 atplib#CompareCoordinates_leq " Each list is an argument with two values! " listA=[ line_nrA, col_nrA] usually given by searchpos() function " listB=[ line_nrB, col_nrB] " returns 1 iff A is smaller or equal to B function! atplib#CompareCoordinates_leq(listA,listB) if a:listA[0] < a:listB[0] || \ a:listA[0] == a:listB[0] && a:listA[1] <= a:listB[1] || \ a:listA == [0,0] " the meaning of the last is that if the searchpos() has not found the " beginning (a:listA) then it should return 1 : the env is not started. return 1 else return 0 endif endfunction "}}}1 " {{{1 atplib#CompareStarAfter " This is used by atplib#complete#TabCompletion to put abbreviations of starred environment after not starred version function! atplib#CompareStarAfter(i1, i2) if a:i1 !~ '\*' && a:i2 !~ '\*' if a:i1 == a:i2 return 0 elseif a:i1 < a:i2 return -1 else return 1 endif else let i1 = substitute(a:i1, '\*', '', 'g') let i2 = substitute(a:i2, '\*', '', 'g') if i1 == i2 if a:i1 =~ '\*' && a:i2 !~ '\*' return 1 else return -1 endif return 0 elseif i1 < i2 return -1 else return 1 endif endif endfunction " }}}1 " ReadInputFile function reads finds a file in tex style and returns the list " of its lines. " {{{1 atplib#ReadInputFile " this function looks for an input file: in the list of buffers, under a path if " it is given, then in the b:atp_OutDir. " directory. The last argument if equal to 1, then look also " under g:texmf. function! atplib#ReadInputFile(ifile,check_texmf) let l:input_file = [] " read the buffer or read file if the buffer is not listed. if buflisted(fnamemodify(a:ifile,":t")) let l:input_file=getbufline(fnamemodify(a:ifile,":t"),1,'$') " if the ifile is given with a path it should be tried to read from there elseif filereadable(a:ifile) let l:input_file=readfile(a:ifile) " if not then try to read it from b:atp_OutDir elseif filereadable(b:atp_OutDir . fnamemodify(a:ifile,":t")) let l:input_file=readfile(filereadable(b:atp_OutDir . fnamemodify(a:ifile,":t"))) " the last chance is to look for it in the g:texmf directory elseif a:check_texmf && filereadable(findfile(a:ifile,g:texmf . '**')) let l:input_file=readfile(findfile(a:ifile,g:texmf . '**')) endif return l:input_file endfunction "}}}1 " URL query: (by some strange reason this is not working moved to url_query.py) " function! atplib#URLquery(url) "{{{ " python << EOF " import urllib2, tempfile, vim " url = vim.eval("a:url") " print(url) " temp = tempfile.mkstemp("", "atp_ams_") " " f = open(temp[1], "w+") " data = urllib2.urlopen(url) " f.write(data.read()) " vim.command("return '"+temp[1]+"'") " EOF " endfunction "}}} " This function sets the window options common for toc and bibsearch windows. "{{{1 atplib#setwindow " this function sets the options of BibSearch, ToC and Labels windows. function! atplib#setwindow() " These options are set in the command line " +setl\\ buftype=nofile\\ filetype=bibsearch_atp " +setl\\ buftype=nofile\\ filetype=toc_atp\\ nowrap " +setl\\ buftype=nofile\\ filetype=toc_atp\\ syntax=labels_atp setlocal nonumber setlocal norelativenumber setlocal winfixwidth setlocal noswapfile setlocal nobuflisted if &filetype == "bibsearch_atp" " setlocal winwidth=30 setlocal nospell elseif &filetype == "toc_atp" " setlocal winwidth=20 setlocal nospell setlocal cursorline endif " nnoremap l "keepalt normal l" " nnoremap h "keepalt normal h" endfunction " }}}1 " {{{1 atplib#count function! atplib#count(line, keyword,...) let method = ( a:0 == 0 || a:1 == 0 ) ? 0 : 1 let line=a:line let i=0 if method==0 while stridx(line, a:keyword) != '-1' let line = strpart(line, stridx(line, a:keyword)+1) let i +=1 endwhile elseif method==1 let pat = a:keyword.'\zs' while line =~ pat let line = strpart(line, match(line, pat)) let i +=1 endwhile endif return i endfunction " }}}1 " Used to append / at the end of a directory name " {{{1 atplib#append fun! atplib#append(where, what) return substitute(a:where, a:what . '\s*$', '', '') . a:what endfun " }}}1 " Used to append extension to a file name (if there is no extension). " {{{1 atplib#append_ext " extension has to be with a dot. fun! atplib#append_ext(fname, ext) return substitute(a:fname, a:ext . '\s*$', '', '') . a:ext endfun " }}}1 " List Functions: " atplib#Extend {{{1 " arguments are the same as for extend(), but it adds only the entries which " are not present. function! atplib#Extend(list_a,list_b,...) let list_a=deepcopy(a:list_a) let list_b=deepcopy(a:list_b) let diff=filter(list_b,'count(l:list_a,v:val) == 0') if a:0 == 0 return extend(list_a,diff) else return extend(list_a,diff, a:1) endif endfunction " }}}1 " {{{1 atplib#Add function! atplib#Add(list,what) let new=[] for element in a:list call add(new,element . a:what) endfor return new endfunction "}}}1 " vim:fdm=marker:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/bibsearch.vim [[[1 844 " Title: Vim library for ATP filetype plugin. " Author: Marcin Szamotulski " Email: mszamot [AT] gmail [DOT] com " Note: This file is a part of Automatic Tex Plugin for Vim. " URL: https://launchpad.net/automatictexplugin " Language: tex " Last Modified: " BIB SEARCH: " These are all bibsearch related variables and functions. "{{{ atplib#bibsearch#variables let atplib#bibsearch#bibflagsdict={ \ 't' : ['title', 'title '], 'a' : ['author', 'author '], \ 'b' : ['booktitle', 'booktitle '], 'c' : ['mrclass', 'mrclass '], \ 'e' : ['editor', 'editor '], 'j' : ['journal', 'journal '], \ 'f' : ['fjournal', 'fjournal '], 'y' : ['year', 'year '], \ 'n' : ['number', 'number '], 'v' : ['volume', 'volume '], \ 's' : ['series', 'series '], 'p' : ['pages', 'pages '], \ 'P' : ['publisher', 'publisher '], 'N' : ['note', 'note '], \ 'S' : ['school', 'school '], 'h' : ['howpublished', 'howpublished '], \ 'o' : ['organization', 'organization '], 'I' : ['institution' , 'institution '], \ 'u' : ['url', 'url '], \ 'H' : ['homepage', 'homepage '], 'i' : ['issn', 'issn '], \ 'k' : ['key', 'key '], 'R' : ['mrreviewer', 'mrreviewer ']} " they do not work in the library script :( " using g:bibflags... . " let atplib#bibflagslist=keys(atplib#bibsearch#bibflagsdict) " let atplib#bibflagsstring=join(atplib#bibflagslist,'') "}}} "{{{ atplib#bibsearch#searchbib " This is the main search engine. " ToDo should not search in comment lines. " To make it work after kpsewhich is searching for bib path. " let s:bibfiles=FindBibFiles(bufname('%')) function! atplib#bibsearch#searchbib(pattern, bibdict, ...) call atplib#outdir() " for tex files this should be a flat search. let flat = &filetype == "plaintex" ? 1 : 0 let bang = a:0 >=1 ? a:1 : "" let atp_MainFile = atplib#FullPath(b:atp_MainFile) " Make a pattern which will match for the elements of the list g:bibentries let pattern = '^\s*@\%(\<'.g:bibentries[0].'\>' for bibentry in g:bibentries['1':len(g:bibentries)] let pattern = pattern . '\|\<' . bibentry . '\>' endfor let pattern = pattern . '\)' " This pattern matches all entry lines: author = \| title = \| ... let pattern_b = '^\s*\%(' for bibentry in keys(g:bibflagsdict) let pattern_b = pattern_b . '\|\<' . g:bibflagsdict[bibentry][0] . '\>' endfor let pattern_b.='\)\s*=' if g:atp_debugBS exe "redir! >>".g:atp_TempDir."/BibSearch.log" silent! echo "==========atplib#bibsearch#searchbib===================" silent! echo "atplib#bibsearch#searchbib_bibfiles=" . string(s:bibfiles) silent! echo "a:pattern=" . a:pattern silent! echo "pattern=" . pattern silent! echo "pattern_b=" . pattern_b silent! echo "bang=" . bang silent! echo "flat=" . flat endif unlet bibentry let b:bibentryline={} " READ EACH BIBFILE IN TO DICTIONARY s:bibdict, WITH KEY NAME BEING THE bibfilename let s:bibdict={} let l:bibdict={} for l:f in keys(a:bibdict) let s:bibdict[l:f]=[] " read the bibfile if it is in b:atp_OutDir or in g:atp_raw_bibinputs directory " ToDo: change this to look in directories under g:atp_raw_bibinputs. " (see also ToDo in FindBibFiles 284) " for l:path in split(g:atp_raw_bibinputs, ',') " " it might be problem when there are multiple libraries with the " " same name under different locations (only the last one will " " survive) " let s:bibdict[l:f]=readfile(fnameescape(findfile(atplib#append(l:f,'.bib'), atplib#append(l:path,"/") . "**"))) " endfor let l:bibdict[l:f]=copy(a:bibdict[l:f]) " clear the s:bibdict values from lines which begin with % call filter(l:bibdict[l:f], ' v:val !~ "^\\s*\\%(%\\|@\\cstring\\)"') endfor if g:atp_debugBS silent! echo "values(l:bibdict) len(l:bibdict[v:val]) = " . string(map(deepcopy(l:bibdict), "len(v:val)")) endif if a:pattern != "" for l:f in keys(a:bibdict) let l:list=[] let l:nr=1 for l:line in l:bibdict[l:f] " Match Pattern: " if the line matches find the beginning of this bib field and add its " line number to the list l:list " remove ligatures and brackets {,} from the line let line_without_ligatures = substitute(substitute(l:line,'\C{\|}\|\\\%("\|`\|\^\|=\|\.\|c\|\~\|v\|u\|d\|b\|H\|t\)\s*','','g'), "\\\\'\\s*", '', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\oe', 'oe', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\OE', 'OE', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\ae', 'ae', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\AE', 'AE', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\o', 'o', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\O', 'O', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\i', 'i', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\j', 'j', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\l', 'l', 'g') let line_without_ligatures = substitute(line_without_ligatures, '\C\\L', 'L', 'g') if line_without_ligatures =~? a:pattern if g:atp_debugBS silent! echo "line_without_ligatures that matches " . line_without_ligatures silent! echo "____________________________________" endif let l:true=1 let l:t=0 while l:true == 1 let l:tnr=l:nr-l:t if g:atp_debugBS silent! echo " l:tnr=" . string(l:tnr) . " l:bibdict[". string(l:f) . "][" . string(l:tnr-1) . "]=" . string(l:bibdict[l:f][l:tnr-1]) endif " go back until the line will match pattern (which " should be the beginning of the bib field. if l:bibdict[l:f][l:tnr-1] =~? pattern && l:tnr >= 0 let l:true=0 let l:list=add(l:list,l:tnr) elseif l:tnr <= 0 let l:true=0 endif let l:t+=1 endwhile endif let l:nr+=1 endfor if g:atp_debugBS silent! echo "A l:list=" . string(l:list) endif " CLEAR THE l:list FROM ENTRIES WHICH APPEAR TWICE OR MORE --> l:clist let l:pentry="A" " We want to ensure that l:entry (a number) and l:pentry are different for l:entry in l:list if l:entry != l:pentry if count(l:list,l:entry) > 1 while count(l:list,l:entry) > 1 let l:eind=index(l:list,l:entry) call remove(l:list,l:eind) endwhile endif let l:pentry=l:entry endif endfor " This is slower than the algorithm above! " call sort(filter(l:list, "count(l:list, v:val) == 1"), "atplib#CompareNumbers") if g:atp_debugBS silent! echo "B l:list=" . string(l:list) endif let b:bibentryline=extend(b:bibentryline,{ l:f : l:list }) if g:atp_debugBS silent! echo "atplib#bibsearch b:bibentryline= (pattern != '') " . string(b:bibentryline) endif endfor endif " CHECK EACH BIBFILE let l:bibresults={} " if the pattern was empty make it faster. if a:pattern == "" for l:bibfile in keys(l:bibdict) let l:bibfile_len=len(l:bibdict[l:bibfile]) let s:bibd={} let l:nr=0 while l:nr < l:bibfile_len let l:line=l:bibdict[l:bibfile][l:nr] if l:line =~ pattern let s:lbibd={} let s:lbibd["bibfield_key"]=l:line let l:beg_line=l:nr+1 let l:nr+=1 let l:line=l:bibdict[l:bibfile][l:nr] let l:y=1 while l:line !~ pattern && l:nr < l:bibfile_len let l:line=l:bibdict[l:bibfile][l:nr] let l:lkey=tolower( \ matchstr( \ strpart(l:line,0, \ stridx(l:line,"=") \ ),'\<\w*\>' \ )) " CONCATENATE LINES IF IT IS NOT ENDED let l:y=1 if l:lkey != "" let s:lbibd[l:lkey]=l:line " IF THE LINE IS SPLIT ATTACH NEXT LINE let l:nline=get(l:bibdict[l:bibfile],l:nr+l:y) while l:nline !~ '=' && \ l:nline !~ pattern && \ (l:nr+l:y) < l:bibfile_len let s:lbibd[l:lkey]=substitute(s:lbibd[l:lkey],'\s*$','','') . " ". substitute(get(l:bibdict[l:bibfile],l:nr+l:y),'^\s*','','') let l:line=get(l:bibdict[l:bibfile],l:nr+l:y) let l:y+=1 let l:nline=get(l:bibdict[l:bibfile],l:nr+l:y) if l:y > 30 echoerr "ATP-Error /see :h atp-errors-bibsearch/, missing '}', ')' or '\"' in bibentry (check line " . l:nr . ") in " . l:f . " line=".l:line break endif endwhile if l:nline =~ pattern let l:y=1 endif endif let l:nr+=l:y unlet l:y endwhile let l:nr-=1 call extend(s:bibd, { l:beg_line : s:lbibd }) else let l:nr+=1 endif endwhile let l:bibresults[l:bibfile]=s:bibd let g:bibresults=l:bibresults endfor let g:bibresults=l:bibresults if g:atp_debugBS silent! echo "atplib#bibsearch#searchbib_bibresults A =" . l:bibresults endif return l:bibresults endif " END OF NEW CODE: (up) for l:bibfile in keys(b:bibentryline) let l:f=l:bibfile . ".bib" "s:bibdict[l:f]) CHECK EVERY STARTING LINE (we are going to read bibfile from starting " line till the last matching } let s:bibd={} for l:linenr in b:bibentryline[l:bibfile] let l:nr=l:linenr-1 let l:i=atplib#count(get(l:bibdict[l:bibfile],l:linenr-1),"{")-atplib#count(get(l:bibdict[l:bibfile],l:linenr-1),"}") let l:j=atplib#count(get(l:bibdict[l:bibfile],l:linenr-1),"(")-atplib#count(get(l:bibdict[l:bibfile],l:linenr-1),")") let s:lbibd={} let s:lbibd["bibfield_key"]=get(l:bibdict[l:bibfile],l:linenr-1) if s:lbibd["bibfield_key"] !~ '@\w\+\s*{.\+' let l:l=0 while get(l:bibdict[l:bibfile],l:linenr-l:l) =~ '^\s*$' let l:l+=1 endwhile let s:lbibd["bibfield_key"] .= get(l:bibdict[l:bibfile],l:linenr+l:l) let s:lbibd["bibfield_key"] = substitute(s:lbibd["bibfield_key"], '\s', '', 'g') endif let l:x=1 " we go from the first line of bibentry, i.e. @article{ or @article(, until the { and ( " will close. In each line we count brackets. while l:i>0 || l:j>0 let l:tlnr=l:x+l:linenr let l:pos=atplib#count(get(l:bibdict[l:bibfile],l:tlnr-1),"{") let l:neg=atplib#count(get(l:bibdict[l:bibfile],l:tlnr-1),"}") let l:i+=l:pos-l:neg let l:pos=atplib#count(get(l:bibdict[l:bibfile],l:tlnr-1),"(") let l:neg=atplib#count(get(l:bibdict[l:bibfile],l:tlnr-1),")") let l:j+=l:pos-l:neg let l:lkey=tolower( \ matchstr( \ strpart(get(l:bibdict[l:bibfile],l:tlnr-1),0, \ stridx(get(l:bibdict[l:bibfile],l:tlnr-1),"=") \ ),'\<\w*\>' \ )) if l:lkey != "" let s:lbibd[l:lkey]=get(l:bibdict[l:bibfile],l:tlnr-1) let l:y=0 " IF THE LINE IS SPLIT ATTACH NEXT LINE if get(l:bibdict[l:bibfile],l:tlnr-1) !~ '\%()\|}\|"\)\s*,\s*\%(%.*\)\?$' " \ get(l:bibdict[l:bibfile],l:tlnr) !~ pattern_b let l:lline=substitute(get(l:bibdict[l:bibfile],l:tlnr+l:y-1),'\\"\|\\{\|\\}\|\\(\|\\)','','g') let l:pos=atplib#count(l:lline,"{") let l:neg=atplib#count(l:lline,"}") let l:m=l:pos-l:neg let l:pos=atplib#count(l:lline,"(") let l:neg=atplib#count(l:lline,")") let l:n=l:pos-l:neg let l:o=atplib#count(l:lline,"\"") " this checks if bracets {}, and () and "" appear in pairs in the current line: if l:m>0 || l:n>0 || l:o>l:o/2*2 while l:m>0 || l:n>0 || l:o>l:o/2*2 let l:pos=atplib#count(get(l:bibdict[l:bibfile],l:tlnr+l:y),"{") let l:neg=atplib#count(get(l:bibdict[l:bibfile],l:tlnr+l:y),"}") let l:m+=l:pos-l:neg let l:pos=atplib#count(get(l:bibdict[l:bibfile],l:tlnr+l:y),"(") let l:neg=atplib#count(get(l:bibdict[l:bibfile],l:tlnr+l:y),")") let l:n+=l:pos-l:neg let l:o+=atplib#count(get(l:bibdict[l:bibfile],l:tlnr+l:y),"\"") " Let's append the next line: let s:lbibd[l:lkey]=substitute(s:lbibd[l:lkey],'\s*$','','') . " ". substitute(get(l:bibdict[l:bibfile],l:tlnr+l:y),'^\s*','','') let l:y+=1 if l:y > 30 echoerr "ATP-Error /see :h atp-errors-bibsearch/, missing '}', ')' or '\"' in bibentry at line " . l:linenr . " (check line " . l:tlnr . ") in " . l:f) break endif endwhile endif endif endif " we have to go line by line and we could skip l:y+1 lines, but we have to " keep l:m, l:o values. It do not saves much. let l:x+=1 if l:x > 30 echoerr "ATP-Error /see :h atp-errors-bibsearch/, missing '}', ')' or '\"' in bibentry at line " . l:linenr . " in " . l:f break endif let b:x=l:x unlet l:tlnr endwhile let s:bibd[l:linenr]=s:lbibd unlet s:lbibd endfor let l:bibresults[l:bibfile]=s:bibd endfor let g:bibresults=l:bibresults if g:atp_debugBS silent! echo "atplib#bibsearch#searchbib_bibresults A =" . string(l:bibresults) redir END endif return l:bibresults endfunction "}}} " {{{ atplib#bibsearch#searchbib_py function! atplib#bibsearch#searchbib_py(pattern, bibfiles, ...) call atplib#outdir() " for tex files this should be a flat search. let flat = &filetype == "plaintex" ? 1 : 0 let bang = a:0 >=1 ? a:1 : "" let atp_MainFile = atplib#FullPath(b:atp_MainFile) let b:atp_BibFiles=a:bibfiles python << END import vim, re files=vim.eval("b:atp_BibFiles") def remove_ligatures(string): line_without_ligatures = re.sub( "\\\\'\s*", '', re.sub('{|}|\\\\(?:"|`|\^|=|\.|c|~|v|u|d|b|H|t)\s*', '', string)) line_without_ligatures = re.sub('\\\\oe', 'oe', line_without_ligatures) line_without_ligatures = re.sub('\\\\OE', 'OE', line_without_ligatures) line_without_ligatures = re.sub('\\\\ae', 'ae', line_without_ligatures) line_without_ligatures = re.sub('\\\\AE', 'AE', line_without_ligatures) line_without_ligatures = re.sub('\\\\o', 'o', line_without_ligatures) line_without_ligatures = re.sub('\\\\O', 'O', line_without_ligatures) line_without_ligatures = re.sub('\\\\i', 'i', line_without_ligatures) line_without_ligatures = re.sub('\\\\j', 'j', line_without_ligatures) line_without_ligatures = re.sub('\\\\l', 'l', line_without_ligatures) line_without_ligatures = re.sub('\\\\L', 'L', line_without_ligatures) return line_without_ligatures def remove_quotes(string): line=re.sub("'", "\"", string) line=re.sub('\\\\', '', line) return line type_pattern=re.compile('\s*@(article|book|mvbook|inbook|bookinbook|suppbook|booklet|collection|mvcollection|incollection|suppcollection|manual|misc|online|patent|periodical|supppertiodical|proceedings|mvproceedings|inproceedings|reference|mvreference|inreference|report|set|thesis|unpublished|custom[a-f]|conference|electronic|masterthesis|phdthesis|techreport|www)', re.I) # types=['abstract', 'addendum', 'afterword', 'annotation', 'author', 'authortype', 'bookauthor', 'bookpaginator', 'booksupbtitle', 'booktitle', 'booktitleaddon', 'chapter', 'commentator', 'date', 'doi', 'edition', 'editor', 'editora', 'editorb', 'editorc', 'editortype', 'editoratype', 'editorbtype', 'editorctype', 'eid', 'eprint', 'eprintclass', 'eprinttype', 'eventdate', 'eventtile', 'file', 'forword', 'holder', 'howpublished', 'indxtitle', 'institution', 'introduction', 'isan', 'isbn', 'ismn', 'isrn', 'issn', 'issue', 'issuesubtitle', 'issuetitle', 'iswc', 'journalsubtitle', 'journaltitle', 'label', 'language', 'library', 'location', 'mainsubtitle', 'maintitle', 'maintitleaddon', 'month', 'nameaddon', 'note', 'number', 'organization', 'origdate', 'origlanguage', 'origpublisher', 'origname', 'pages', 'pagetotal', 'pagination', 'part', 'publisher', 'pubstate', 'reprinttitle', 'series', 'shortauthor', 'shorteditor', 'shorthand', 'shorthandintro', 'shortjournal', 'shortseries', 'subtitle', 'title', 'titleaddon', 'translator', 'type', 'url', 'urldate', 'venue', 'version', 'volume', 'volumes', 'year', 'crossref', 'entryset', 'entrysubtype', 'execute', 'mrreviewer'] types=['author', 'bookauthor', 'booktitle', 'date', 'editor', 'eprint', 'eprintclass', 'eprinttype', 'howpublished', 'institution', 'journal', 'month', 'note', 'number', 'organization', 'pages', 'publisher', 'school', 'series', 'subtitle', 'title', 'url', 'year', 'mrreviewer', 'volume', 'pages'] def parse_bibentry(bib_entry): bib={} bib['bibfield_key']=re.sub('\\r$', '', bib_entry[0]) nr=1 while nr < len(bib_entry)-1: line=bib_entry[nr] if not re.match('\s*%', line): if not re.search('=', line): while not re.search('=', line) and nr < len(bib_entry)-1: val=re.sub('\s*$', '', bib[p_e_type])+" "+re.sub('^\s*', '', re.sub('\t', ' ', line)) val=re.sub('%.*', '', val) bib[p_e_type]=remove_quotes(re.sub('\\r$', '', val)) nr+=1 line=bib_entry[nr] else: v_break=False for e_type in types: if re.match('\s*'+e_type+'\s*=', line, re.I): # this is not working when title is two lines! line=re.sub('%.*', '', line) bib[e_type]=remove_quotes(re.sub('\\r$', '', re.sub('\t', ' ', line))) p_e_type=e_type nr+=1 v_break=True break if not v_break: nr+=1 # for key in bib.keys(): # print(key+"="+bib[key]) # print("\n") return bib pattern=vim.eval("a:pattern") if pattern == "": pat="" else: pat=pattern pattern=re.compile(pat, re.I) pattern_b=re.compile('\s*@\w+\s*{.+', re.I) bibresults={} for file in files: file_ob=open(file, 'r') file_l=file_ob.read().split("\n") file_ob.close() file_len=len(file_l) lnr=0 bibresults[file]={} # if pattern != "" while lnr < file_len: lnr+=1 line=file_l[lnr-1] if re.search('@string', line): continue line_without_ligatures=remove_ligatures(line) if re.search(pattern, line_without_ligatures): """find first line""" b_lnr=lnr # print("lnr="+str(lnr)) b_line=line while not re.match(pattern_b, b_line) and b_lnr >= 1: b_lnr-=1 b_line=file_l[b_lnr-1] """find last line""" # print("b_lnr="+str(b_lnr)) e_lnr=lnr e_line=line if re.match(pattern_b, e_line): lnr+=1 e_lnr=lnr line=file_l[lnr-1] e_line=file_l[lnr-1] # print("X "+line) while not re.match(pattern_b, e_line) and e_lnr <= file_len: e_lnr+=1 e_line=file_l[min(e_lnr-1, file_len-1)] e_lnr-=1 e_line=file_l[min(e_lnr-1, file_len-1)] while re.match('\s*$', e_line): e_lnr-=1 e_line=file_l[e_lnr-1] # e_lnr=min(e_lnr, file_len-1) bib_entry=file_l[b_lnr-1:e_lnr] # print("lnr="+str(lnr)) # print("b_lnr="+str(b_lnr)) # print("e_lnr="+str(e_lnr)) if bib_entry != [] and not re.search('@string', bib_entry[0]): entry_dict=parse_bibentry(bib_entry) bibresults[file][b_lnr]=entry_dict # else: # print("lnr="+str(lnr)) # print("b_lnr="+str(b_lnr)) # print("e_lnr="+str(e_lnr)) # print(entry_dict) # print("\n".join(bib_entry)) if lnr < e_lnr: lnr=e_lnr else: lnr+=1 #print(bibresults) # for key in bibresults.keys(): # for line in bibresults[key].keys(): # for bib in bibresults[key][line].keys(): # print(bib+"="+bibresults[key][line][bib]) # print("\n") vim.command("let bibresults="+str(bibresults)) END let g:bibresults=bibresults return bibresults endfunction "}}} " {{{ atplib#bibsearch#SearchBibItems " the argument should be b:atp_MainFile but in any case it is made in this way. " it specifies in which file to search for include files. function! atplib#bibsearch#SearchBibItems() let time=reltime() let atp_MainFile = atplib#FullPath(b:atp_MainFile) " we are going to make a dictionary { citekey : label } (see :h \bibitem) let l:citekey_label_dict={} " make a list of include files. let l:includefile_list=[] if !exists("b:ListOfFiles") || !exists("b:TypeDict") call TreeOfFiles(b:atp_MainFile) endif let i=1 for f in b:ListOfFiles let type = get(b:TypeDict, f, 'no_type') if type == 'no_type' && i call TreeOfFiles(b:atp_MainFile) let i=0 endif if b:TypeDict[f] == "input" call add(l:includefile_list, f) endif endfor call add(l:includefile_list, atp_MainFile) if has("python") python << PEND import vim, re files=vim.eval("l:includefile_list") citekey_label_dict={} for f in files: f_o=open(f, 'r') f_l=f_o.read().split("\n") f_o.close() for line in f_l: if re.match('[^%]*\\\\bibitem', line): match=re.search('\\\\bibitem\s*(?:\[([^\]]*)\])?\s*{([^}]*)}\s*(.*)', line) if match: label=match.group(1) if label == None: label = "" key=match.group(2) if key == None: key = "" rest=match.group(3) if rest == None: rest = "" if key != "": citekey_label_dict[key]={ 'label' : label, 'rest' : rest } vim.command("let l:citekey_label_dict="+str(citekey_label_dict)) PEND else " search for bibitems in all include files. for l:ifile in l:includefile_list let l:input_file = atplib#ReadInputFile(l:ifile,0) " search for bibitems and make a dictionary of labels and citekeys for l:line in l:input_file if l:line =~# '^[^%]*\\bibitem' let l:label=matchstr(l:line,'\\bibitem\s*\[\zs[^]]*\ze\]') let l:key=matchstr(l:line,'\\bibitem\s*\%(\[[^]]*\]\)\?\s*{\zs[^}]*\ze}') let l:rest=matchstr(l:line,'\\bibitem\s*\%(\[[^]]*\]\)\?\s*{[^}]*}\s*\zs') if l:key != "" call extend(l:citekey_label_dict, { l:key : { 'label' : l:label, 'rest' : l:rest } }, 'error') endif endif endfor endfor endif let g:time_SearchBibItems=reltimestr(reltime(time)) return l:citekey_label_dict endfunction " }}} "{{{ atplib#bibsearch#showresults " FLAGS: " for currently supported flags see ':h atp_bibflags' " All - all flags " L - last flag " a - author " e - editor " t - title " b - booktitle " j - journal " s - series " y - year " n - number " v - volume " p - pages " P - publisher " N - note " S - school " h - howpublished " o - organization " i - institution " R - mrreviewer function! atplib#bibsearch#showresults(bibresults, flags, pattern, bibdict) "if nothing was found inform the user and return: if len(a:bibresults) == count(a:bibresults, {}) echo "BibSearch: no bib fields matched." if g:atp_debugBS exe "redir! >> ".g:atp_TempDir."/BibSeach.log" silent! echo "==========atplib#bibsearch#showresults=================" silent! echo "atplib#bibsearch#showresults return A - no bib fields matched. " redir END endif return 0 elseif g:atp_debugBS exe "redir! >> ".g:atp_TempDir."/BibSearch.log" silent! echo "==========atplib#bibsearch#showresults=================" silent! echo "atplib#bibsearch#showresults return B - found something. " redir END endif function! s:showvalue(value) return substitute(strpart(a:value,stridx(a:value,"=")+1),'^\s*','','') endfunction let s:z=1 let l:ln=1 let l:listofkeys={} "--------------SET UP FLAGS-------------------------- let l:allflagon=0 let l:flagslist=[] let l:kwflagslist=[] " flags o and i are synonims: (but refer to different entry keys): if a:flags =~# 'i' && a:flags !~# 'o' let l:flags=substitute(a:flags,'i','io','') elseif a:flags !~# 'i' && a:flags =~# 'o' let l:flags=substitute(a:flags,'o','oi','') endif if a:flags !~# 'All' if a:flags =~# 'L' " if strpart(a:flags,0,1) != '+' " let l:flags=b:atp_LastBibFlags . substitute(a:flags, 'L', '', 'g') " else let l:flags=b:atp_LastBibFlags . substitute(a:flags, 'L', '', 'g') " endif let g:atp_LastBibFlags = deepcopy(b:atp_LastBibFlags) else if a:flags == "" let l:flags=g:defaultbibflags elseif strpart(a:flags,0,1) != '+' && a:flags !~ 'All' let l:flags=a:flags elseif strpart(a:flags,0,1) == '+' && a:flags !~ 'All' let l:flags=g:defaultbibflags . strpart(a:flags,1) endif endif let b:atp_LastBibFlags=substitute(l:flags,'+\|L','','g') if l:flags != "" let l:expr='\C[' . g:bibflagsstring . ']' while len(l:flags) >=1 let l:oneflag=strpart(l:flags,0,1) " if we get a flag from the variable g:bibflagsstring we copy it to the list l:flagslist if l:oneflag =~ l:expr let l:flagslist=add(l:flagslist, l:oneflag) let l:flags=strpart(l:flags,1) " if we get '@' we eat ;) two letters to the list l:kwflagslist elseif l:oneflag == '@' let l:oneflag=strpart(l:flags,0,2) if index(keys(g:kwflagsdict),l:oneflag) != -1 let l:kwflagslist=add(l:kwflagslist,l:oneflag) endif let l:flags=strpart(l:flags,2) " remove flags which are not defined elseif l:oneflag !~ l:expr && l:oneflag != '@' let l:flags=strpart(l:flags,1) endif endwhile endif else " if the flag 'All' was specified. let l:flagslist=split(g:defaultallbibflags, '\zs') let l:af=substitute(a:flags,'All','','g') for l:kwflag in keys(g:kwflagsdict) if a:flags =~ '\C' . l:kwflag call extend(l:kwflagslist,[l:kwflag]) endif endfor endif "NEW: if there are only keyword flags append default flags if len(l:kwflagslist) > 0 && len(l:flagslist) == 0 let l:flagslist=split(g:defaultbibflags,'\zs') endif " Open a new window. let l:bufnr=bufnr("___Bibsearch: " . a:pattern . "___" ) if l:bufnr != -1 let l:bdelete=l:bufnr . "bwipeout" exe l:bdelete endif unlet l:bufnr let l:openbuffer=" +setl\\ buftype=nofile\\ filetype=bibsearch_atp " . fnameescape("___Bibsearch: " . a:pattern . "___") if g:vertical ==1 let l:openbuffer="keepalt vsplit " . l:openbuffer let l:skip="" else let l:openbuffer="keepalt split " . l:openbuffer let l:skip=" " endif let BufNr = bufnr("%") let LineNr = line(".") let ColNr = col(".") silent exe l:openbuffer " set the window options silent call atplib#setwindow() " make a dictionary of clear values, which we will fill with found entries. " the default value is no, which after all is matched and not showed " SPEED UP: let l:values={'bibfield_key' : 'nokey'} for l:flag in g:bibflagslist let l:values_clear=extend(l:values,{ g:bibflagsdict[l:flag][0] : 'no' . g:bibflagsdict[l:flag][0] }) endfor " SPEED UP: let l:kwflag_pattern="\\C" let l:len_kwflgslist=len(l:kwflagslist) let l:kwflagslist_rev=reverse(deepcopy(l:kwflagslist)) for l:lkwflag in l:kwflagslist if index(l:kwflagslist_rev,l:lkwflag) == 0 let l:kwflag_pattern.=g:kwflagsdict[l:lkwflag] else let l:kwflag_pattern.=g:kwflagsdict[l:lkwflag].'\|' endif endfor " let b:kwflag_pattern=l:kwflag_pattern for l:bibfile in keys(a:bibresults) if a:bibresults[l:bibfile] != {} call setline(l:ln, "Found in " . l:bibfile ) let l:ln+=1 endif for l:linenr in copy(sort(keys(a:bibresults[l:bibfile]), "atplib#CompareNumbers")) let l:values=deepcopy(l:values_clear) let b:values=l:values " fill l:values with a:bibrsults let l:values["bibfield_key"]=a:bibresults[l:bibfile][l:linenr]["bibfield_key"] " for l:key in keys(l:values) " if l:key != 'key' && get(a:bibresults[l:bibfile][l:linenr],l:key,"no" . l:key) != "no" . l:key " let l:values[l:key]=a:bibresults[l:bibfile][l:linenr][l:key] " endif " SPEED UP: call extend(l:values,a:bibresults[l:bibfile][l:linenr],'force') " endfor " ----------------------------- SHOW ENTRIES ------------------------- " first we check the keyword flags, @a,@b,... it passes if at least one flag " is matched let l:check=0 " for l:lkwflag in l:kwflagslist " let l:kwflagpattern= '\C' . g:kwflagsdict[l:lkwflag] " if l:values['bibfield_key'] =~ l:kwflagpattern " let l:check=1 " endif " endfor if l:values['bibfield_key'] =~ l:kwflag_pattern let l:check=1 endif if l:check == 1 || len(l:kwflagslist) == 0 let l:linenumber=index(a:bibdict[l:bibfile],l:values["bibfield_key"])+1 call setline(l:ln,s:z . ". line " . l:linenumber . " " . l:values["bibfield_key"]) let l:ln+=1 let l:c0=atplib#count(l:values["bibfield_key"],'{')-atplib#count(l:values["bibfield_key"],'(') " this goes over the entry flags: for l:lflag in l:flagslist " we check if the entry was present in bibfile: if l:values[g:bibflagsdict[l:lflag][0]] != "no" . g:bibflagsdict[l:lflag][0] " if l:values[g:bibflagsdict[l:lflag][0]] =~ a:pattern call setline(l:ln, l:skip . g:bibflagsdict[l:lflag][1] . " = " . s:showvalue(l:values[g:bibflagsdict[l:lflag][0]])) let l:ln+=1 " else " call setline(l:ln, l:skip . g:bibflagsdict[l:lflag][1] . " = " . s:showvalue(l:values[g:bibflagsdict[l:lflag][0]])) " let l:ln+=1 " endif endif endfor let l:lastline=getline(line('$')) let l:c1=atplib#count(l:lastline,'{')-atplib#count(l:lastline,'}') let l:c2=atplib#count(l:lastline,'(')-atplib#count(l:lastline,')') let l:c3=atplib#count(l:lastline,'\"') if l:c0 == 1 && l:c1 == -1 call setline(line('$'),substitute(l:lastline,'}\s*$','','')) call setline(l:ln,'}') let l:ln+=1 elseif l:c0 == 1 && l:c1 == 0 call setline(l:ln,'}') let l:ln+=1 elseif l:c0 == -1 && l:c2 == -1 call setline(line('$'),substitute(l:lastline,')\s*$','','')) call setline(l:ln,')') let l:ln+=1 elseif l:c0 == -1 && l:c1 == 0 call setline(l:ln,')') let l:ln+=1 endif let l:listofkeys[s:z]=l:values["bibfield_key"] let s:z+=1 endif endfor endfor if g:atp_debugBS let g:pattern = a:pattern endif if has("python") || g:atp_bibsearch == "python" let pattern_tomatch = substitute(a:pattern, '(', '\\(', 'g') let pattern_tomatch = substitute(pattern_tomatch, ')', '\\)', 'g') let pattern_tomatch = substitute(pattern_tomatch, '|', '\\|', 'g') else let pattern_tomatch = a:pattern endif let pattern_tomatch = substitute(pattern_tomatch, '\Co', 'oe\\=', 'g') let pattern_tomatch = substitute(pattern_tomatch, '\CO', 'OE\\=', 'g') let pattern_tomatch = substitute(pattern_tomatch, '\Ca', 'ae\\=', 'g') let pattern_tomatch = substitute(pattern_tomatch, '\CA', 'AE\\=', 'g') if g:atp_debugBS let g:pm = pattern_tomatch endif let pattern_tomatch = join(split(pattern_tomatch, '\zs\\\@!\\\@= 1 ? a:1 : "" ) endfunction " }}} " atplib#callback#MakeidxReturnCode {{{ function! atplib#callback#MakeidxReturnCode(returncode,...) let b:atp_MakeidxReturnCode=a:returncode let b:atp_MakeidxOutput= ( a:0 >= 1 ? a:1 : "" ) endfunction " }}} " atplib#callback#Signs {{{ function! atplib#callback#Signs(bufnr) if has("signs") if a:bufnr != bufnr("%") if bufwinnr(str2nr(a:bufnr)) != -1 let cwinnr = bufwinnr(bufnr("%")) exe bufwinnr(str2nr(a:bufnr))."wincmd w" else return endif endif sign unplace * " This unplaces also signs not in the current buffer " This unplaces only signs in the current buffer, but uses " redir => var | signs place buffer=a:bufnr | redir END " construct which shows signs on the srceen for a second. " " There should be a function which lists signs. " " let more = &more " let lz = &lz " set nomore " setl lz " redir => unplace_signs " silent exe "sign place buffer=".a:bufnr " redir END " let &more = more " let &lz = lz " let signs = split(unplace_signs, "\n") " call map(signs, 'matchstr(v:val, ''\\zs\d\+\ze'')') " for sign in signs " exe "sign unplace ".sign." buffer=".a:bufnr " endfor " unlet sign " unlet signs " unlet unplace_signs " There is no way of getting list of defined signs in the current buffer. " Thus there is no proper way of deleting them. I overwrite them using " numbers as names. The vim help tells that there might be at most 120 " signs put. " But this is not undefineing signs. let qflist=getqflist() let i=1 for item in qflist if item['type'] == 'E' let hl = 'ErrorMsg' elseif item['type'] == 'W' let hl = 'WarningMsg' else let hl = 'Normal' endif exe 'sign define '.i.' text='.item['type'].': texthl='.hl exe 'sign place '.i.' line='.item['lnum'].' name='.i.' file='.expand('%:p') let i+=1 endfor if exists("cwinnr") exe cwinnr."wincmd w" unlet cwinnr endif endif endfunction "}}} " atplib#callback#CallBack {{{ " a:mode = a:verbose of s:compiler ( one of 'default', 'silent', " 'debug', 'verbose') " a:commnad = a:commmand of s:compiler " ( a:commnad = 'AU' if run from background) " " Uses b:atp_TexReturnCode which is equal to the value returned by tex " compiler. function! atplib#callback#CallBack(bufnr,mode,...) let g:bufnr = a:bufnr " If the compiler was called by autocommand. let AU = ( a:0 >= 1 ? a:1 : 'COM' ) " Was compiler called to make bibtex let BIBTEX = ( a:0 >= 2 ? a:2 : "False" ) let BIBTEX = ( BIBTEX == "True" || BIBTEX == 1 ? 1 : 0 ) let MAKEIDX = ( a:0 >= 3 ? a:3 : "False" ) let MAKEIDX = ( MAKEIDX == "TRUE" || MAKEIDX == 1 ? 1 : 0 ) if g:atp_debugCallBack exe "redir! > ".g:atp_TempDir."/CallBack.log" endif for cmd in keys(g:CompilerMsg_Dict) if b:atp_TexCompiler =~ '^\s*' . cmd . '\s*$' let Compiler = g:CompilerMsg_Dict[cmd] break else let Compiler = b:atp_TexCompiler endif endfor let b:atp_running = b:atp_running - 1 " Read the log file cgetfile " signs if g:atp_signs call atplib#callback#Signs(a:bufnr) endif if g:atp_debugCallBack silent echo "file=".expand("%:p") silent echo "g:atp_HighlightErrors=".g:atp_HighlightErrors endif if g:atp_HighlightErrors call atplib#callback#HighlightErrors() endif " /this cgetfile is not working (?)/ let error = len(getqflist()) + (BIBTEX ? b:atp_BibtexReturnCode : 0) " If the log file is open re read it / it has 'autoread' opion set / checktime " redraw the status line /for the notification to appear as fast as " possible/ if a:mode != 'verbose' redrawstatus endif " redraw has values -0,1 " 1 do not redraw " 0 redraw " i.e. redraw at the end of function (this is done to not redraw twice in " this function) let l:clist = 0 let atp_DebugMode = t:atp_DebugMode if b:atp_TexReturnCode == 0 && ( a:mode == 'silent' || atp_DebugMode == 'silent' ) && g:atp_DebugMode_AU_change_cmdheight let &l:cmdheight=g:atp_cmdheight endif if g:atp_debugCallBack let g:debugCB = 0 let g:debugCB_mode = a:mode let g:debugCB_error = error silent echo "mode=".a:mode."\nerror=".error endif let msg_list = [] let showed_message = 0 if a:mode == "silent" && !error if t:atp_QuickFixOpen if g:atp_debugCallBack let g:debugCB .= 7 endif cclose call add(msg_list, ["[ATP:] no errors, closing quick fix window.", "Normal"]) endif elseif a:mode == "silent" && AU == "COM" if b:atp_TexReturnCode let showed_message = 1 call add(msg_list, ["[ATP:] ".Compiler." returned with exit code ".b:atp_TexReturnCode.".", 'ErrorMsg', 'after']) endif if BIBTEX && b:atp_BibtexReturnCode let showed_message = 1 call add(msg_list, ["[ATP:] ".b:atp_BibCompiler." returned with exit code ".b:atp_BibtexReturnCode.".", 'ErrorMsg', 'after']) endif if MAKEIDX && b:atp_Makeindex let showed_message = 1 call add(msg_list, ["[ATP:] makeidx returned with exit code ".b:atp_MakeidxReturnCode.".", 'ErrorMsg', 'after']) endif endif if a:mode ==? 'debug' && !error if g:atp_debugCallBack let g:debugCB .= 3 endif cclose call add(msg_list,["[ATP:] ".b:atp_TexCompiler." returned without errors [b:atp_ErrorFormat=".b:atp_ErrorFormat."]".(g:atp_DefaultDebugMode=='silent'&&atp_DebugMode!='silent'?"\ngoing out of debuging mode.": "."), "Normal", "after"]) let showed_message = 1 let t:atp_DebugMode = g:atp_DefaultDebugMode if g:atp_DefaultDebugMode == "silent" && t:atp_QuickFixOpen cclose endif let &l:cmdheight = g:atp_cmdheight endif " debug mode with errors if a:mode ==? 'debug' && error if len(getqflist()) if g:atp_debugCallBack let g:debugCB .= 4 endif let &l:cmdheight = g:atp_DebugModeCmdHeight let showed_message = 1 if b:atp_ReloadOnError || b:atp_Viewer !~ '^\s*xpdf\>' call add(msg_list, ["[ATP:] ".Compiler." returned with exit code " . b:atp_TexReturnCode . ".", (b:atp_TexReturnCode ? "ErrorMsg" : "Normal"), "before"]) else call add(msg_list, ["[ATP:] ".Compiler." returned with exit code " . b:atp_TexReturnCode . " output file not reloaded.", (b:atp_TexReturnCode ? "ErrorMsg" : "Normal"), "before"]) endif if !t:atp_QuickFixOpen let l:clist = 1 endif endif if BIBTEX && b:atp_BibtexReturnCode let l:clist = 1 call add(msg_list, [ "[Bib:] ".b:atp_BibtexCompiler." returned with exit code ".b:atp_BibtexReturnCode .".", "ErrorMsg", "after"]) call add(msg_list, [ "BIBTEX_OUTPUT" , "Normal", "after"]) endif if MAKEIDX && b:atp_MakeidxReturnCode let l:clist = 1 call add(msg_list, [ "[Bib:] makeidx returned with exit code ".b:atp_MakeidxReturnCode .".", "ErrorMsg", "after"]) call add(msg_list, [ "MAKEIDX_OUTPUT" , "Normal", "after"]) endif " In debug mode, go to first error. if a:mode ==# "Debug" if g:atp_debugCallBack let g:debugCB .= 6 endif cc endif endif if msg_list == [] if g:atp_debugCallBack redir END endif return endif " Count length of the message: let msg_len = len(msg_list) if len(filter(copy(msg_list), "v:val[0] == 'BIBTEX_OUTPUT'")) let msg_len += (BIBTEX ? len(split(b:atp_BibtexOutput, "\\n")) - 1 : - 1 ) endif if len(filter(copy(msg_list), "v:val[0] == 'MAKEIDX_OUTPUT'")) let msg_len += (MAKEIDX ? len(split(b:atp_MakeidxOutput, "\\n")) - 1 : - 1 ) endif " We never show qflist: (that's why it is commented out) " let msg_len += ((len(getqflist()) <= 7 && !t:atp_QuickFixOpen) ? len(getqflist()) : 0 ) " Show messages/clist if g:atp_debugCallBack let g:msg_list = msg_list let g:clist = l:clist silent echo "msg_list=\n**************\n".join(msg_list, "\n")."\n**************" silent echo "l:clist=".l:clist endif let cmdheight = &l:cmdheight if msg_len <= 2 let add=0 elseif msg_len <= 7 let add=1 else let add=2 endif let &l:cmdheight = max([cmdheight, msg_len+add]) let g:msg_len=msg_len if l:clist && len(getqflist()) > 7 && !t:atp_QuickFixOpen let winnr = winnr() copen exe winnr."wincmd w" elseif (a:mode ==? "debug") && !t:atp_QuickFixOpen let l:clist = 1 endif redraw let before_msg = filter(copy(msg_list), "v:val[2] == 'before'") let after_msg = filter(copy(msg_list), "v:val[2] == 'after'") for msg in before_msg exe "echohl " . msg[1] echo msg[0] endfor let l:redraw = 1 if l:clist && len(getqflist()) <= 7 && !t:atp_QuickFixOpen if g:atp_debugCallBack let g:debugCB .= "clist" endif try clist catch E42: endtry let l:redraw = 0 endif for msg in after_msg exe "echohl " . msg[1] if msg[0] !=# "BIBTEX_OUTPUT" echo msg[0] else echo " ".substitute(b:atp_BibtexOutput, "\n", "\n ", "g") " let bib_output=split(b:atp_BibtexOutput, "\n") " let len=max([10,len(bib_output)]) " below split +setl\ buftype=nofile\ noswapfile Bibtex\ Output " setl nospell " setl nonumber " setl norelativenumber " call append(0,bib_output) " resize 10 " redraw! " normal gg " nmap q :bd let g:debugCB .=" BIBTEX_output " endif endfor echohl None if len(msg_list)==0 redraw endif let &l:cmdheight = cmdheight if g:atp_debugCallBack redir END endif endfunction "}}} "{{{ atplib#callback#LatexPID "Store LatexPIDs in a variable function! atplib#callback#LatexPID(pid) let g:bufnr = bufnr("%") call add(b:atp_LatexPIDs, a:pid) let b:atp_LastLatexPID=a:pid endfunction "}}} "{{{ atplib#callback#BibtexPID "Store BibtexPIDs in a variable function! atplib#callback#BibtexPID(pid) call add(b:atp_BibtexPIDs, a:pid) " call atplib#callback#PIDsRunning("b:atp_BibtexPIDs") endfunction "}}} "{{{ atplib#callback#MakeindexPID "Store MakeindexPIDs in a variable function! atplib#callback#MakeindexPID(pid) call add(b:atp_MakeindexPIDs, a:pid) let b:atp_LastMakeindexPID =a:pid endfunction "}}} "{{{ atplib#callback#PythonPID "Store PythonPIDs in a variable function! atplib#callback#PythonPID(pid) call add(b:atp_PythonPIDs, a:pid) " call atplib#callback#PIDsRunning("b:atp_PythonPIDs") endfunction "}}} "{{{ atplib#callback#MakeindexPID "Store MakeindexPIDs in a variable function! atplib#callback#PythonPIDs(pid) call add(b:atp_PythonPIDs, a:pid) let b:atp_LastPythonPID =a:pid endfunction "}}} "{{{ atplib#callback#PIDsRunning function! atplib#callback#PIDsRunning(var) " a:var is a string, and might be one of 'b:atp_LatexPIDs', 'b:atp_BibtexPIDs' or " 'b:atp_MakeindexPIDs' python << EOL import psutil, re, sys, vim var = vim.eval("a:var") pids = vim.eval(var) if len(pids) > 0: ps_list=psutil.get_pid_list() rmpids=[] for lp in pids: run=False for p in ps_list: if str(lp) == str(p): run=True break if not run: rmpids.append(lp) rmpids.sort() rmpids.reverse() for pid in rmpids: vim.eval("filter("+var+", 'v:val !~ \""+str(pid)+"\"')") EOL endfunction "}}} "{{{ atplib#callback#ProgressBar function! atplib#callback#ProgressBar(value,pid,bufnr) if a:value != 'end' let progress_bar = getbufvar(a:bufnr, "atp_ProgressBar") let progress_bar[a:pid]=a:value call setbufvar(a:bufnr, "atp_ProgressBar", progress_bar) else let progress_bar = copy(getbufvar(a:bufnr, "atp_ProgressBar")) call remove(progress_bar, a:pid) call setbufvar(a:bufnr, "atp_ProgressBar", progress_bar) endif redrawstatus endfunction "}}} "{{{ atplib#callback#redrawstatus function! atplib#callback#redrawstatus() redrawstatus endfunction "}}} "{{{ atplib#callback#CursorMoveI " function! atplib#callback#CursorMoveI() " if mode() != "i" " return " endif " let cursor_pos=[ line("."), col(".")] " call feedkeys("\", "n") " call cursor(cursor_pos) " endfunction "}}} " {{{ atplib#callback#HighlightErrors function! atplib#callback#HighlightErrors() call atplib#callback#ClearHighlightErrors() let qf_list = getqflist() for error in qf_list if error.type ==? 'e' let hlgroup = g:atp_Highlight_ErrorGroup else let hlgroup = g:atp_Highlight_WarningGroup endif if hlgroup == "" continue endif let m_id = matchadd(hlgroup, '\%'.error.lnum.'l.*', 20) call add(s:matchid, m_id) let error_msg=split(error.text, "\n") endfor endfunction "}}} " {{{ atplib#callback#ClearHighlightErrors function! atplib#callback#ClearHighlightErrors() if !exists("s:matchid") let s:matchid=[] return endif for m_id in s:matchid try silent call matchdelete(m_id) catch /E803:/ endtry endfor let s:matchid=[] endfunction "}}} "{{{ atplib#callback#Echo function! atplib#callback#Echo(msg, cmd, hlgroup, ...) if a:0 >= 1 && a:1 redraw endif exe "echohl ".a:hlgroup exe a:cmd." '".a:msg."'" echohl None endfunction "}}} " vim:fdm=marker:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/common.vim [[[1 132 " Author: Marcin Szamotulski " Description: This script has functions which have to be called before ATP_files/options.vim " Note: This file is a part of Automatic Tex Plugin for Vim. " Language: tex " This file contains set of functions which are needed to set to set the atp " options and some common tools. " Set the project name "{{{ atplib#common#SetProjectName (function and autocommands) " This function sets the main project name (b:atp_MainFile) " " It is used by EditInputFile which copies the value of this variable to every " input file included in the main source file. " " nmap gf (GotoFile function) is not using this function. " " the b:atp_MainFile variable is set earlier in the startup " (by the augroup ATP_Syntax_TikzZone), calling SetProjectName to earlier cause " problems (g:atp_raw_bibinputs undefined). " " ToDo: CHECK IF THIS IS WORKS RECURSIVELY? " ToDo: THIS FUNCTION SHUOLD NOT SET AUTOCOMMANDS FOR AuTeX function! " every tex file should be compiled (the compiler function calls the " right file to compile! " " {{{ atplib#common#SetProjectName ( function ) " store a list of all input files associated to some file function! atplib#common#SetProjectName(...) let bang = ( a:0 >= 1 ? a:1 : "" ) " do we override b:atp_project let did = ( a:0 >= 2 ? a:2 : 1 ) " do we check if the project name was set " but also overrides the current b:atp_MainFile when 0 " if the project name was already set do not set it for the second time " (which sets then b:atp_MainFile to wrong value!) if &filetype == "fd_atp" " this is needed for EditInputFile function to come back to the main " file. let b:atp_MainFile = ( g:atp_RelativePath ? expand("%:t") : expand("%:p") ) let s:did_project_name = 1 endif let g:did_project_name = (exists("s:did_project_name") ? s:did_project_name : -1) if exists("s:did_project_name") && s:did_project_name && did && exists("b:atp_MainFile") return " project name was already set" else let s:did_project_name = 1 endif let b:atp_MainFile = exists("b:atp_MainFile") && did ? b:atp_MainFile : \ ( g:atp_RelativePath ? expand("%:t") : expand("%:p") ) if !exists("b:atp_ProjectDir") let b:atp_ProjectDir = ( exists("b:atp_ProjectScriptFile") ? fnamemodify(b:atp_ProjectScriptFile, ":h") : fnamemodify(resolve(expand("%:p")), ":h") ) endif endfunction " }}} "}}} " This functions sets the value of b:atp_OutDir variable " {{{ atplib#common#SetOutDir " This options are set also when editing .cls files. " It can overwrite the value of b:atp_OutDir " if arg != 0 then set errorfile option accordingly to b:atp_OutDir " if a:0 >0 0 then b:atp_atp_OutDir is set iff it doesn't exsits. function! atplib#common#SetOutDir(arg, ...) " THIS FUNCTION SHOULD BE REVIEWED !!! if exists("b:atp_OutDir") && a:0 >= 1 return "atp_OutDir EXISTS" endif " if the user want to be asked for b:atp_OutDir if g:askfortheoutdir == 1 let b:atp_OutDir=substitute(input("Where to put output? do not escape white spaces "), '\\\s', ' ', 'g') endif if ( get(getbufvar(bufname("%"),""),"outdir","optionnotset") == "optionnotset" \ && g:askfortheoutdir != 1 \ || b:atp_OutDir == "" && g:askfortheoutdir == 1 ) \ && !exists("$TEXMFOUTPUT") let b:atp_OutDir=substitute(fnamemodify(resolve(expand("%:p")),":h") . "/", '\\\s', ' ', 'g') elseif exists("$TEXMFOUTPUT") let b:atp_OutDir=substitute($TEXMFOUTPUT, '\\\s', ' ', 'g') endif " if arg != 0 then set errorfile option accordingly to b:atp_OutDir if bufname("") =~ ".tex$" && a:arg != 0 " \ && ( !exists("t:atp_QuickFixOpen") || exists("t:atp_QuickFixOpen") && !t:atp_QuickFixOpen ) call atplib#common#SetErrorFile() endif if exists("g:outdir_dict") let g:outdir_dict = extend(g:outdir_dict, {fnamemodify(bufname("%"),":p") : b:atp_OutDir }) else let g:outdir_dict = { fnamemodify(bufname("%"),":p") : b:atp_OutDir } endif return b:atp_OutDir endfunction " }}} " This function sets vim 'errorfile' option. "{{{ atplib#common#SetErrorFile " let &l:errorfile=b:atp_OutDir . fnameescape(fnamemodify(expand("%"),":t:r")) . ".log" function! atplib#common#SetErrorFile() " set b:atp_OutDir if it is not set if !exists("b:atp_OutDir") call atplib#common#SetOutDir(0) endif " set the b:atp_MainFile varibale if it is not set (the project name) if !exists("b:atp_MainFile") call atplib#common#SetProjectName() endif let atp_MainFile = atplib#FullPath(b:atp_MainFile) " vim doesn't like escaped spaces in file names ( cg, filereadable(), " writefile(), readfile() - all acepts a non-escaped white spaces) if has("win16") || has("win32") || has("win64") || has("win95") let errorfile = substitute(atplib#append(b:atp_OutDir, '\') . fnamemodify(atp_MainFile,":t:r") . ".log", '\\\s', ' ', 'g') else let errorfile = substitute(atplib#append(b:atp_OutDir, '/') . fnamemodify(atp_MainFile,":t:r") . ".log", '\\\s', ' ', 'g') endif let &l:errorfile = errorfile return &l:errorfile endfunction "}}} " vim:fdm=marker:tw=85:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/compiler.vim [[[1 2418 " Author: Marcin Szamotulski " Note: this file contain the main compiler function and related tools, to " view the output, see error file. " Note: This file is a part of Automatic Tex Plugin for Vim. " Language: tex " Internal Variables " {{{ " This limits how many consecutive runs there can be maximally. " Note: compile.py script has hardcoded the same value. let s:runlimit = 9 " }}} " This is the function to view output. It calls compiler if the output is a not " readable file. " {{{ atplib#compiler#ViewOutput " a:1 == "RevSearch" if run from RevSearch() function and the output file doesn't " exsists call compiler and RevSearch(). function! atplib#compiler#ViewOutput(bang,...) let atp_MainFile = atplib#FullPath(b:atp_MainFile) let fwd_search = ( a:bang == "!" ? 1 : 0 ) call atplib#outdir() " Set the correct output extension (if nothing matches set the default '.pdf') let ext = get(g:atp_CompilersDict, matchstr(b:atp_TexCompiler, '^\s*\zs\S\+\ze'), ".pdf") " Read the global options from g:atp_{b:atp_Viewer}Options variables let global_options = join((exists("g:atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? g:atp_{matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')}Options : []), " ") let local_options = join((exists("b:atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? getbufvar(bufnr("%"), "atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") : []), " ") " Follow the symbolic link let link=resolve(atp_MainFile) if link != "" let outfile = fnamemodify(link,":r") . ext else let outfile = fnamemodify(atp_MainFile,":r"). ext endif if b:atp_Viewer == "xpdf" let viewer = b:atp_Viewer . " -remote " . shellescape(b:atp_XpdfServer) else let viewer = b:atp_Viewer . " " endif if g:atp_debugV let g:global_options = global_options let g:local_options = local_options let g:viewer = viewer endif let view_cmd = viewer." ".global_options." ".local_options." ".shellescape(outfile)." &" if g:atp_debugV let g:view_cmd = view_cmd endif if filereadable(outfile) if b:atp_Viewer == "xpdf" call system(view_cmd) else call system(view_cmd) redraw! endif else echomsg "[ATP:] output file do not exists. Calling " . b:atp_TexCompiler if fwd_search if g:atp_Compiler == 'python' call atplib#compiler#PythonCompiler( 0, 2, 1, 'silent' , "AU" , atp_MainFile, "") else call atplib#compiler#Compiler( 0, 2, 1, 'silent' , "AU" , atp_MainFile, "") endif else if g:atp_Compiler == 'python' call atplib#compiler#PythonCompiler( 0, 1, 1, 'silent' , "AU" , atp_MainFile, "") else call atplib#compiler#Compiler( 0, 1, 1, 'silent' , "AU" , atp_MainFile, "") endif endif endif if fwd_search let msg = "[SyncTex:] waiting for the viewer " let i=1 while !atplib#compiler#IsRunning(viewer, outfile) && i<10 echo msg sleep 100m redraw let msg.="." let i+=1 endwhile if i<15 call atplib#compiler#SyncTex("", 0) else echohl WarningMsg echomsg "[SyncTex:] viewer is not running" echohl None endif endif endfunction "}}} " Forward Search: " {{{ atplib#compiler#GetSyncData function! atplib#compiler#GetSyncData(line, col) if !filereadable(fnamemodify(atplib#FullPath(b:atp_MainFile), ":r").'.synctex.gz') redraw! let cmd=b:atp_TexCompiler." ".join(split(b:atp_TexOptions, ','), " ")." ".shellescape(atplib#FullPath(b:atp_MainFile)) if b:atp_TexOptions !~ '\%(-synctex\s*=\s*1\|-src-specials\>\)' echomsg "[SyncTex:] b:atp_TexOptions does not contain -synctex=1 or -src-specials switches!" return else echomsg "[SyncTex:] calling ".get(g:CompilerMsg_Dict, b:atp_TexCompiler, b:atp_TexCompiler)." to generate synctex data. Wait a moment..." endif call system(cmd) endif " Note: synctex view -i line:col:tex_file -o output_file " tex_file must be full path. let synctex_cmd="synctex view -i ".a:line.":".a:col.":'".fnamemodify(b:atp_MainFile, ":p"). "' -o '".fnamemodify(b:atp_MainFile, ":p:r").".pdf'" " SyncTex is fragile for the file name: if it is file name or full path, it " must agree literally with what is written in .synctex.gz file " first we try with full path then with file name without path. let synctex_output=split(system(synctex_cmd), "\n") if get(synctex_output, 1, '') =~ '^SyncTex Warning: No tag for' " Write better test (above) let synctex_cmd="synctex view -i ".a:line.":".a:col.":'".b:atp_MainFile. "' -o '".fnamemodify(b:atp_MainFile, ":r").".pdf'" let synctex_output=split(system(synctex_cmd), "\n") " call add(g:debug,get(synctex_output, 1, '')) if get(synctex_output, 1, '') =~ '^SyncTex Warning:' return [ "no_sync", get(synctex_output, 1, ''), 0 ] endif endif if g:atp_debugSync let g:synctex_cmd=synctex_cmd let g:synctex_output=copy(synctex_output) endif let page_list=copy(synctex_output) call filter(page_list, "v:val =~ '^\\cpage:\\d\\+'") let page=get(page_list, 0, "no_sync") let y_coord_list=copy(synctex_output) call filter(y_coord_list, "v:val =~ '^\\cy:\\d\\+'") let y_coord=get(y_coord_list, 0, "no sync data") let y_coord= ( y_coord != "no sync data" ? matchstr(y_coord, 'y:\zs[0-9.]*') : y_coord ) let x_coord_list=copy(synctex_output) call filter(x_coord_list, "v:val =~ '^\\cx:\\d\\+'") let x_coord=get(x_coord_list, 0, "no sync data") let x_coord= ( x_coord != "no sync data" ? matchstr(x_coord, 'x:\zs[0-9.]*') : x_coord ) if g:atp_debugSync let g:page=page let g:y_coord=y_coord let g:x_coord=x_coord endif if page == "no_sync" return [ "no_sync", "No SyncTex Data: try on another line (or recompile the document).", 0 ] endif let page_nr=matchstr(page, '^\cPage:\zs\d\+') let [ b:atp_synctex_pagenr, b:atp_synctex_ycoord, b:atp_synctex_xcoord ] = [ page_nr, y_coord, x_coord ] return [ page_nr, y_coord, x_coord ] endfunction function! atplib#compiler#SyncShow( page_nr, y_coord) if a:y_coord < 300 let height="top" elseif a:y_coord < 500 let height="middle" else let height="bottom" endif if a:page_nr != "no_sync" echomsg "[SyncTex:] ".height." of page ".a:page_nr else echohl WarningMsg echomsg "[SyncTex:] ".a:y_coord " echomsg " You cannot forward search on comment lines, if this is not the case try one or two lines above/below" echohl None endif endfunction "}}} " {{{ atplib#compiler#SyncTex function! atplib#compiler#SyncTex(bang, mouse, ...) if g:atp_debugSyncTex exe "redir! > ".g:atp_TempDir."/SyncTex.log" endif let output_check = ( a:0 >= 1 && a:1 == 0 ? 0 : 1 ) let IsRunning_check = ( a:bang == "!" ? 0 : 1 ) let dryrun = ( a:0 >= 2 && a:2 == 1 ? 1 : 0 ) " Mouse click is mapped to ... => thus it first changes " the cursor position. let [ line, col ] = [ line("."), col(".") ] let atp_MainFile = atplib#FullPath(b:atp_MainFile) let ext = get(g:atp_CompilersDict, matchstr(b:atp_TexCompiler, '^\s*\zs\S\+\ze'), ".pdf") let output_file = fnamemodify(atp_MainFile,":p:r") . ext if !filereadable(output_file) && output_check " Here should be a test if viewer is running, this can be made with python. " this is way viewer starts not well when using :SyncTex command while Viewer " is not running. " call atplib#compiler#ViewOutput("sync") " if g:atp_debugSyncTex " silent echo "ViewOutput sync" " redir END " endif echohl WarningMsg echomsg "[SyncTex:] no output file" echohl None return 2 endif let atp_MainFile = atplib#FullPath(b:atp_MainFile) let ext = get(g:atp_CompilersDict, matchstr(b:atp_TexCompiler, '^\s*\zs\S\+\ze'), ".pdf") let link=resolve(atp_MainFile) if link != "" let outfile = fnamemodify(link,":r") . ext else let outfile = fnamemodify(atp_MainFile,":r"). ext endif if IsRunning_check if (!atplib#compiler#IsRunning(b:atp_Viewer, atplib#FullPath(outfile), b:atp_XpdfServer) && output_check) "Note: I should test here if Xpdf is not holding a file (it might be not "visible through cmdline arguments -> this happens if file is opened in "another server. We can use: xpdf -remote b:atp_XpdfServer "run('echo %f')" echohl WarningMsg echomsg "[SyncTex:] please open the file first. (if file is opend add bang \"!\")" echohl None return endif endif if b:atp_Viewer == "xpdf" let [ page_nr, y_coord, x_coord ] = atplib#compiler#GetSyncData(line, col) let sync_cmd_page = "xpdf -remote " . shellescape(b:atp_XpdfServer) . " -exec 'gotoPage(".page_nr.")'" let sync_cmd_y = "xpdf -remote " . shellescape(b:atp_XpdfServer) . " -exec 'scrollDown(".y_coord.")'" let sync_cmd_x = "xpdf -remote " . shellescape(b:atp_XpdfServer) . " -exec 'scrollRight(".x_coord.")'" " There is a bug in xpdf. We need to sleep between sending commands: let sleep = ( g:atp_XpdfSleepTime ? 'sleep '.string(g:atp_XpdfSleepTime).'s;' : '' ) let sync_cmd = "(".sync_cmd_page.";".sleep.sync_cmd_y.")&" if !dryrun call system(sync_cmd) call atplib#compiler#SyncShow(page_nr, y_coord) endif elseif b:atp_Viewer == "okular" let [ page_nr, y_coord, x_coord ] = atplib#compiler#GetSyncData(line, col) " This will not work in project files. (so where it is mostly needed.) let sync_cmd = "okular --unique ".shellescape(expand("%:p:r")).".pdf\\#src:".line.shellescape(expand("%:p"))." &" let sync_args = " ".shellescape(expand("%:p:r")).".pdf\\#src:".line.shellescape(expand("%:p"))." " if !dryrun call system(sync_cmd) call atplib#compiler#SyncShow(page_nr, y_coord) endif elseif b:atp_Viewer == "skim" let [ page_nr, y_coord, x_coord ] = atplib#compiler#GetSyncData(line, col) let sync_cmd = "displayline ".line." ".shellescape(expand("%:p:r")).".pdf ".shellescape(expand("%:p"))." &" if !dryrun call system(sync_cmd) call atplib#compiler#SyncShow(page_nr, y_coord) endif " elseif b:atp_Viewer == "evince" " let rev_searchcmd="synctex view -i ".line(".").":".col(".").":".fnameescape(b:atp_MainFile). " -o ".fnameescape(fnamemodify(b:atp_MainFile, ":p:r").".pdf") . " -x 'evince %{output} -i %{page}'" " endif elseif b:atp_Viewer =~ '^\s*xdvi\>' let options = (exists("g:atp_xdviOptions") ? " ".join(g:atp_xdviOptions, " ") : " " ) ." ".join(getbufvar(bufnr(""), "atp_xdviOptions"), " ") let sync_cmd = "xdvi ".options. \ " -editor '".v:progname." --servername ".v:servername. \ " --remote-wait +%l %f' -sourceposition ". \ line.":".col.shellescape(fnameescape(fnamemodify(expand("%"),":p"))). \ " ".fnameescape(output_file)." &" let sync_args = " -sourceposition ".line.":".col.shellescape(fnameescape(fnamemodify(expand("%"),":p")))." " if !dryrun call system(sync_cmd) endif if g:atp_debugSyncTex silent echo "sync_cmd=".sync_cmd endif else let sync_cmd="" if g:atp_debugSyncTex silent echo "sync_cmd=EMPTY" endif endif if g:atp_debugSyncTex let g:sync_cmd = sync_cmd endif if g:atp_debugSyncTex redir END endif return endfunction "}}} " " This function gets the pid of the running compiler " ToDo: review LatexBox has a better approach! "{{{ Get PID Functions function! atplib#compiler#getpid() let atplib#compiler#command="ps -ef | grep -v " . $SHELL . " | grep " . b:atp_TexCompiler . " | grep -v grep | grep " . fnameescape(expand("%")) . " | awk 'BEGIN {ORS=\" \"} {print $2}'" let atplib#compiler#var = system(atplib#compiler#command) return atplib#compiler#var endfunction " The same but using python (it is not used) " TODO: end this. function! atplib#compiler#PythonGetPID() python << EOF import psutil latex = vim.eval("b:atp_TexCompiler") # Make dictionary: xpdf_servername : file # to test if the server host file use: # basename(xpdf_server_file_dict().get(server, ['_no_file_'])[0]) == basename(file) ps_list=psutil.get_pid_list() latex_running = False for pr in ps_list: try: name=psutil.Process(pr).name cmdline=psutil.Process(pr).cmdline if name == latex: latex_pid=pr latex_running=True break except psutil.error.NoSuchProcess: pass except psutil.error.AccessDenied: pass if latex_running: vim.command("let atplib#compiler#var="+str(latex_pid)) else: vim.command("let atplib#compiler#var=''") EOF endfunction function! atplib#compiler#GetPID() if g:atp_Compiler == "bash" let atplib#compiler#var=atplib#compiler#getpid() if atplib#compiler#var != "" echomsg "[ATP:] ".b:atp_TexCompiler . " pid(s): " . atplib#compiler#var else let b:atp_running = 0 echomsg "[ATP:] ".b:atp_TexCompiler . " is not running" endif else call atplib#callback#PIDsRunning("b:atp_LatexPIDs") if len(b:atp_LatexPIDs) > 0 echomsg "[ATP:] ".b:atp_TexCompiler . " pid(s): " . join(b:atp_LatexPIDs, ", ") else let b:atp_LastLatexPID = 0 echomsg "[ATP:] ".b:atp_TexCompiler . " is not running" endif endif endfunction "}}} " This function compares two files: file written on the disk a:file and the current " buffer "{{{ atplib#compiler#compare " relevant variables: " g:atp_compare_embedded_comments " g:atp_compare_double_empty_lines " Problems: " This function is too slow it takes 0.35 sec on file with 2500 lines. " Ideas: " Maybe just compare current line! " (search for the current line in the written " file with vimgrep) function! atplib#compiler#compare(file) let l:buffer=getbufline(bufname("%"),"1","$") " rewrite l:buffer to remove all comments let l:buffer=filter(l:buffer, 'v:val !~ "^\s*%"') let l:i = 0 if g:atp_compare_double_empty_lines == 0 || g:atp_compare_embedded_comments == 0 while l:i < len(l:buffer)-1 let l:rem=0 " remove comment lines at the end of a line if g:atp_compare_embedded_comments == 0 let l:buffer[l:i] = substitute(l:buffer[l:i],'%.*$','','') endif " remove double empty lines (i.e. from two conecutive empty lines " the first one is deleted, the second remains), if the line was " removed we do not need to add 1 to l:i (this is the role of " l:rem). if g:atp_compare_double_empty_lines == 0 && l:i< len(l:buffer)-2 if l:buffer[l:i] =~ '^\s*$' && l:buffer[l:i+1] =~ '^\s*$' call remove(l:buffer,l:i) let l:rem=1 endif endif if l:rem == 0 let l:i+=1 endif endwhile endif " do the same with a:file let l:file=filter(a:file, 'v:val !~ "^\s*%"') let l:i = 0 if g:atp_compare_double_empty_lines == 0 || g:atp_compare_embedded_comments == 0 while l:i < len(l:file)-1 let l:rem=0 " remove comment lines at the end of a line if g:atp_compare_embedded_comments == 0 let l:file[l:i] = substitute(a:file[l:i],'%.*$','','') endif " remove double empty lines (i.e. from two conecutive empty lines " the first one is deleted, the second remains), if the line was " removed we do not need to add 1 to l:i (this is the role of " l:rem). if g:atp_compare_double_empty_lines == 0 && l:i < len(l:file)-2 if l:file[l:i] =~ '^\s*$' && l:file[l:i+1] =~ '^\s*$' call remove(l:file,l:i) let l:rem=1 endif endif if l:rem == 0 let l:i+=1 endif endwhile endif " This is the way to make it not sensitive on new line signs. " let file_j = join(l:file) " let buffer_j = join(l:buffer) " return file_j !=# buffer_j return l:file !=# l:buffer endfunction " function! atplib#compiler#sompare(file) " return Compare(a:file) " endfunction " This is very fast (0.002 sec on file with 2500 lines) " but the proble is that vimgrep greps the buffer rather than the file! " so it will not indicate any differences. function! atplib#compiler#NewCompare() let line = getline(".") let lineNr = line(".") let saved_loclist = getloclist(0) try exe "lvimgrep /^". escape(line, '\^$') . "$/j " . fnameescape(expand("%:p")) catch /E480:/ endtry " call setloclist(0, saved_loclist) let loclist = getloclist(0) call map(loclist, "v:val['lnum']") return !(index(loclist, lineNr)+1) endfunction "}}} " This function copies the file a:input to a:output "{{{ atplib#compiler#copy function! atplib#compiler#copy(input,output) call writefile(readfile(a:input),a:output) endfunction "}}} "{{{ atplib#compiler#GetSid function! atplib#compiler#GetSid() return matchstr(expand(''), '\zs\d\+_\ze.*$') endfunction let atplib#compiler#compiler_SID = atplib#compiler#GetSid() "}}} "{{{ atplib#compiler#SidWrap function! atplib#compiler#SidWrap(func) return atplib#compiler#compiler_SID . a:func endfunction "}}} " {{{ atplib#compiler#SetBiberSettings function! atplib#compiler#SetBiberSettings() if b:atp_BibCompiler !~# '^\s*biber\>' return elseif !exists("atplib#compiler#biber_keep_done") let atplib#compiler#biber_keep_done = 1 if index(g:atp_keep, "run.xml") == -1 let g:atp_keep += [ "run.xml" ] endif if index(g:atp_keep, "bcf") == -1 let g:atp_keep += [ "bcf" ] endif endif endfunction "}}} " {{{ atplib#compiler#IsRunning " This function checks if program a:program is running a file a:file. " a:file should be full path to the file. function! atplib#compiler#IsRunning(program, file, ...) " Since there is an issue in psutil on OS X, we cannot run this function: " http://code.google.com/p/psutil/issues/detail?id=173 " Reported by F.Heiderich. if has("mac") || has("gui_mac") let atplib#compiler#running=1 return atplib#compiler#running endif let s:return_is_running=0 python << EOF import vim, psutil, os, pwd from psutil import NoSuchProcess x=0 program =vim.eval("a:program") f =vim.eval("a:file") pat ="|".join(vim.eval("a:000")) for pid in psutil.get_pid_list(): try: p=psutil.Process(pid) if p.username == pwd.getpwuid(os.getuid())[0] and re.search(program, p.cmdline[0]): for arg in p.cmdline: if arg == f or re.search(pat, arg): x=1 break if x: break except psutil.error.NoSuchProcess: pass except psutil.error.AccessDenied: pass except IndexError: pass vim.command("let s:return_is_running="+str(x)) EOF let l:return=s:return_is_running unlet s:return_is_running return l:return endfunction " }}} "{{{ atplib#compiler#KillAll " This function kills all running latex processes. " a slightly better approach would be to kill compile.py scripts " the argument is a list of pids " a:1 if present supresses a message. function! atplib#compiler#Kill(bang) if !has("python") if a:bang != "!" echohl WarningMsg echomsg "[ATP:] you need python suppor" echohl None endif return endif if len(b:atp_LatexPIDs) call atplib#KillPIDs(b:atp_LatexPIDs) endif if len(b:atp_PythonPIDs) call atplib#KillPIDs(b:atp_PythonPIDs) endif let b:atp_ProgressBar={} endfunction "}}} " THE MAIN COMPILER FUNCTIONs: " This function is called to run TeX compiler and friends as many times as necessary. " Makes references and bibliographies (supports bibtex), indexes. "{{{ atplib#compiler#MakeLatex " Function Arguments: function! atplib#compiler#MakeLatex(bang, mode, start) if a:mode =~# '^s\%[ilent]$' let mode = 'silent' elseif a:mode =~# '^d\%[ebug]$' let mode = 'debug' elseif a:mode =~# 'D\%[ebug]$' let mode = 'Debug' elseif a:mode =~# '^v\%[erbose]$' let mode = 'debug' else let mode = t:atp_DebugMode endif " and a:bang are not yet used by makelatex.py let PythonMakeLatexPath = split(globpath(&rtp, "ftplugin/ATP_files/makelatex.py"), "\n")[0] let interaction = ( mode=="verbose" ? b:atp_VerboseLatexInteractionMode : 'nonstopmode' ) let tex_options = shellescape(b:atp_TexOptions.',-interaction='.interaction) let ext = get(g:atp_CompilersDict, matchstr(b:atp_TexCompiler, '^\s*\zs\S\+\ze'), ".pdf") let ext = substitute(ext, '\.', '', '') let global_options = join((exists("g:atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? g:atp_{matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')}Options : []), ";") let local_options = join((exists("b:atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? getbufvar(bufnr("%"), "atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") : []), ";") if global_options != "" let viewer_options = global_options.";".local_options else let viewer_options = local_options endif let reload_viewer = ( index(g:atp_ReloadViewers, b:atp_Viewer)+1 ? ' --reload-viewer ' : '' ) let reload_on_error = ( b:atp_ReloadOnError ? ' --reload-on-error ' : '' ) let bibliographies = join(keys(filter(copy(b:TypeDict), "v:val == 'bib'")), ',') let cmd=g:atp_Python." ".PythonMakeLatexPath. \ " --texfile ".shellescape(atplib#FullPath(b:atp_MainFile)). \ " --bufnr ".bufnr("%"). \ " --start ".a:start. \ " --output-format ".ext. \ " --verbose ".mode. \ " --cmd ".b:atp_TexCompiler. \ " --bibcmd ".b:atp_BibCompiler. \ " --bibliographies ".shellescape(bibliographies). \ " --outdir ".shellescape(b:atp_OutDir). \ " --keep ". shellescape(join(g:atp_keep, ',')). \ " --tex-options ".tex_options. \ " --servername ".v:servername. \ " --viewer ".shellescape(b:atp_Viewer). \ " --xpdf-server ".shellescape(b:atp_XpdfServer). \ " --viewer-options ".shellescape(viewer_options). \ " --progname ".v:progname. \ " --tempdir ".shellescape(g:atp_TempDir). \ (t:atp_DebugMode=='verbose'||mode=='verbose'?' --env ""': " --env ".shellescape(b:atp_TexCompilerVariable)). \ reload_viewer . reload_on_error unlockvar g:atp_TexCommand let g:atp_TexCommand=cmd lockvar g:atp_TexCommand " Write file call atplib#write("silent") if mode == "verbose" exe ":!".cmd elseif has("win16") || has("win32") || has("win64") let output=system(cmd) else let output=system(cmd." &") endif endfunction "}}} " {{{ atplib#compiler#PythonCompiler function! atplib#compiler#PythonCompiler(bibtex, start, runs, verbose, command, filename, bang) " Kill comiple.py scripts if there are too many of them. if len(b:atp_PythonPIDs) >= b:atp_MaxProcesses && b:atp_MaxProcesses let a=copy(b:atp_LatexPIDs) try if b:atp_KillYoungest " Remove the newest PIDs (the last in the b:atp_PythonPIDs) let pids=remove(b:atp_LatexPIDs, b:atp_MaxProcesses, -1) else " Remove the oldest PIDs (the first in the b:atp_PythonPIDs) /works nicely/ let pids=remove(b:atp_LatexPIDs, 0, max([len(b:atp_PythonPIDs)-b:atp_MaxProcesses-1,0])) endif echomsg string(a)." ".string(pids)." ".string(b:atp_LatexPIDs) call atplib#KillPIDs(pids) catch E684: endtry echomsg string(b:atp_LatexPIDs) endif " Set biber setting on the fly call atplib#compiler#SetBiberSettings() if !has('gui') && a:verbose == 'verbose' && len(b:atp_LatexPIDs) > 0 redraw! echomsg "[ATP:] please wait until compilation stops." return " This is not working: (I should kill compile.py scripts) echomsg "[ATP:] killing all instances of ".get(g:CompilerMsg_Dict,b:atp_TexCompiler,'TeX') call atplib#KillPIDs(b:atp_LatexPIDs,1) sleep 1 PID endif " Debug varibles " On Unix the output of compile.py run by this function is available at " g:atp_TempDir/compiler.py.log if g:atp_debugPythonCompiler call atplib#Log("PythonCompiler.log", "", "init") call atplib#Log("PythonCompiler.log", "a:bibtex=".a:bibtex) call atplib#Log("PythonCompiler.log", "a:start=".a:start) call atplib#Log("PythonCompiler.log", "a:runs=".a:runs) call atplib#Log("PythonCompiler.log", "a:verbose=".a:verbose) call atplib#Log("PythonCompiler.log", "a:command=".a:command) call atplib#Log("PythonCompiler.log", "a:filename=".a:filename) call atplib#Log("PythonCompiler.log", "a:bang=".a:bang) endif if !exists("t:atp_DebugMode") let t:atp_DebugMode = g:atp_DefaultDebugMode endif if t:atp_DebugMode != 'verbose' && a:verbose != 'verbose' let b:atp_LastLatexPID = -1 endif if t:atp_DebugMode != "silent" && b:atp_TexCompiler !~ "luatex" && \ (b:atp_TexCompiler =~ "^\s*\%(pdf\|xetex\)" && b:atp_Viewer == "xdvi" ? 1 : \ b:atp_TexCompiler !~ "^\s*pdf" && b:atp_TexCompiler !~ "xetex" && (b:atp_Viewer == "xpdf" || b:atp_Viewer == "epdfview" || b:atp_Viewer == "acroread" || b:atp_Viewer == "kpdf")) echohl WaningMsg | echomsg "[ATP:] your ".b:atp_TexCompiler." and ".b:atp_Viewer." are not compatible:" echomsg " b:atp_TexCompiler=" . b:atp_TexCompiler echomsg " b:atp_Viewer=" . b:atp_Viewer echohl None endif if !has('clientserver') if has("win16") || has("win32") || has("win64") || has("win95") echohl WarningMsg echomsg "[ATP:] ATP needs +clientserver vim compilation option." echohl None else echohl WarningMsg echomsg "[ATP:] python compiler needs +clientserver vim compilation option." echomsg " falling back to g:atp_Compiler=\"bash\"" echohl None let g:atp_Compiler = "bash" return endif endif " Set options for compile.py let interaction = ( a:verbose=="verbose" ? b:atp_VerboseLatexInteractionMode : 'nonstopmode' ) let tex_options = b:atp_TexOptions.',-interaction='.interaction " let g:tex_options=tex_options let ext = get(g:atp_CompilersDict, matchstr(b:atp_TexCompiler, '^\s*\zs\S\+\ze'), ".pdf") let ext = substitute(ext, '\.', '', '') let global_options = join((exists("g:atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? g:atp_{matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')}Options : []), ";") let local_options = join(( exists("atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? getbufvar(bufnr("%"), "atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") : []), ";") if global_options != "" let viewer_options = global_options.";".local_options else let viewer_options = local_options endif let bang = ( a:bang == '!' ? ' --bang ' : '' ) let bibtex = ( a:bibtex ? ' --bibtex ' : '' ) let reload_on_error = ( b:atp_ReloadOnError ? ' --reload-on-error ' : '' ) let gui_running = ( has("gui_running") ? ' --gui-running ' : '' ) let reload_viewer = ( index(g:atp_ReloadViewers, b:atp_Viewer)+1 ? ' --reload-viewer ' : '' ) let aucommand = ( a:command == "AU" ? ' --aucommand ' : '' ) let no_progress_bar = ( g:atp_ProgressBar ? '' : ' --no-progress-bar ' ) let bibliographies = join(keys(filter(copy(b:TypeDict), "v:val == 'bib'")), ',') let autex_wait = ( b:atp_autex_wait ? ' --autex_wait ' : '') " Set the command let cmd=g:atp_Python." ".g:atp_PythonCompilerPath." --command ".b:atp_TexCompiler \ ." --tex-options ".shellescape(tex_options) \ ." --verbose ".a:verbose \ ." --file ".shellescape(atplib#FullPath(a:filename)) \ ." --bufnr ".bufnr("%") \ ." --output-format ".ext \ ." --runs ".a:runs \ ." --servername ".v:servername \ ." --start ".a:start \ ." --viewer ".shellescape(b:atp_Viewer) \ ." --xpdf-server ".shellescape(b:atp_XpdfServer) \ ." --viewer-options ".shellescape(viewer_options) \ ." --keep ". shellescape(join(g:atp_keep, ',')) \ ." --progname ".v:progname \ ." --bibcommand ".b:atp_BibCompiler \ ." --bibliographies ".shellescape(bibliographies) \ ." --logdir ".shellescape(g:atp_TempDir) \ .(t:atp_DebugMode=='verbose'||a:verbose=='verbose'?' --env ""': " --env ".shellescape(b:atp_TexCompilerVariable)) \ . bang . bibtex . reload_viewer . reload_on_error . gui_running . aucommand . no_progress_bar \ . autex_wait " Write file if g:atp_debugPythonCompiler call atplib#Log("PythonCompiler.log", "PRE WRITING b:atp_changedtick=".b:atp_changedtick." b:changedtick=".b:changedtick) endif call atplib#write("silent") if g:atp_debugPythonCompiler call atplib#Log("PythonCompiler.log", "POST WRITING b:atp_changedtick=".b:atp_changedtick." b:changedtick=".b:changedtick) endif unlockvar g:atp_TexCommand let g:atp_TexCommand = cmd lockvar g:atp_TexCommand " Call compile.py let b:atp_running += ( a:verbose != "verbose" ? 1 : 0 ) if a:verbose == "verbose" exe ":!".cmd elseif g:atp_debugPythonCompiler && has("unix") call system(cmd." 2".g:atp_TempDir."/PythonCompiler.log &") elseif has("win16") || has("win32") || has("win64") call system(cmd) else call system(cmd." &") endif if g:atp_debugPythonCompiler call atplib#Log("PythonCompiler.log", "END b:atp_changedtick=".b:atp_changedtick." b:changedtick=".b:changedtick) endif endfunction " }}} " {{{ atplib#compiler#Compiler " This is the MAIN FUNCTION which sets the command and calls it. " NOTE: the argument is not escaped! " a:verbose = silent/verbose/debug " debug -- switch to show errors after compilation. " verbose -- show compiling procedure. " silent -- compile silently (gives status information if fails) " a:start = 0/1/2 " 1 start viewer " 2 start viewer and make reverse search " function! atplib#compiler#Compiler(bibtex, start, runs, verbose, command, filename, bang) " Set biber setting on the fly call atplib#compiler#SetBiberSettings() if !has('gui') && a:verbose == 'verbose' && b:atp_running > 0 redraw! echomsg "[ATP:] please wait until compilation stops." return endif if g:atp_debugCompiler exe "redir! > ".g:atp_TempDir."/Compiler.log" silent echomsg "________ATP_COMPILER_LOG_________" silent echomsg "changedtick=" . b:changedtick . " atp_changedtick=" . b:atp_changedtick silent echomsg "a:bibtex=" . a:bibtex . " a:start=" . a:start . " a:runs=" . a:runs . " a:verbose=" . a:verbose . " a:command=" . a:command . " a:filename=" . a:filename . " a:bang=" . a:bang silent echomsg "1 b:changedtick=" . b:changedtick . " b:atp_changedtick" . b:atp_changedtick . " b:atp_running=" . b:atp_running endif if has('clientserver') && !empty(v:servername) && g:atp_callback && a:verbose != 'verbose' let b:atp_running+=1 endif call atplib#outdir() " IF b:atp_TexCompiler is not compatible with the viewer " ToDo: (move this in a better place). (luatex can produce both pdf and dvi " files according to options so this is not the right approach.) if !exists("t:atp_DebugMode") let t:atp_DebugMode = g:atp_DefaultDebugMode endif if t:atp_DebugMode !=? "silent" && b:atp_TexCompiler !~? "luatex" && \ (b:atp_TexCompiler =~ "^\s*\%(pdf\|xetex\)" && b:atp_Viewer == "xdvi" ? 1 : \ b:atp_TexCompiler !~ "^\s*pdf" && b:atp_TexCompiler !~ "xetex" && (b:atp_Viewer == "xpdf" || b:atp_Viewer == "epdfview" || b:atp_Viewer == "acroread" || b:atp_Viewer == "kpdf")) echohl WaningMsg | echomsg "[ATP:] your ".b:atp_TexCompiler." and ".b:atp_Viewer." are not compatible:" echomsg " b:atp_TexCompiler=" . b:atp_TexCompiler echomsg " b:atp_Viewer=" . b:atp_Viewer echohl None endif " There is no need to run more than ~5 (s:runlimit=9) consecutive runs " this prevents from running tex as many times as the current line " what can be done by a mistake using the range for the command. if ( a:runs > s:runlimit ) let runs = s:runlimit else let runs = a:runs endif let tmpdir=b:atp_TempDir . matchstr(tempname(), '\/\w\+\/\d\+') let tmpfile=atplib#append(tmpdir, "/") . fnamemodify(a:filename,":t:r") if g:atp_debugCompiler let g:tmpdir=tmpdir let g:tmpfile=tmpfile endif call system("mkdir -m 0700 -p ".shellescape(tmpdir)) " if exists("*mkdir") " call mkdir(tmpdir, "p", 0700) " else " echoerr "[ATP:] Your vim doesn't have mkdir function, please try the python compiler." " return " endif " SET THE NAME OF OUTPUT FILES " first set the extension pdf/dvi let ext = get(g:atp_CompilersDict, matchstr(b:atp_TexCompiler, '^\s*\zs\S\+\ze'), ".pdf") " check if the file is a symbolic link, if it is then use the target " name. let link=system("readlink " . a:filename) if link != "" let basename=fnamemodify(link,":r") else let basename=a:filename endif " finally, set the output file names. let outfile = b:atp_OutDir . fnamemodify(basename,":t:r") . ext let outaux = b:atp_OutDir . fnamemodify(basename,":t:r") . ".aux" let outbbl = b:atp_OutDir . fnamemodify(basename,":t:r") . ".bbl" let tmpaux = fnamemodify(tmpfile, ":r") . ".aux" let tmpbbl = fnamemodify(tmpfile, ":r") . ".bbl" let tmptex = fnamemodify(tmpfile, ":r") . ".tex" let outlog = b:atp_OutDir . fnamemodify(basename,":t:r") . ".log" let syncgzfile = b:atp_OutDir . fnamemodify(basename,":t:r") . ".synctex.gz" let syncfile = b:atp_OutDir . fnamemodify(basename,":t:r") . ".synctex" " COPY IMPORTANT FILES TO TEMP DIRECTORY WITH CORRECT NAME " except log and aux files. let list = copy(g:atp_keep) call filter(list, 'v:val != "log"') for i in list let ftc = b:atp_OutDir . fnamemodify(basename,":t:r") . "." . i if filereadable(ftc) call atplib#compiler#copy(ftc,tmpfile . "." . i) endif endfor " HANDLE XPDF RELOAD let reload_viewer = ( index(g:atp_ReloadViewers, b:atp_Viewer) == '-1' ? ' --reload-viewer ' : '' ) if b:atp_Viewer =~ '^\s*xpdf\>' && reload_viewer if a:start "if xpdf is not running and we want to run it. let Reload_Viewer = b:atp_Viewer . " -remote " . shellescape(b:atp_XpdfServer) . " " . shellescape(outfile) . " ; " else " TIME: this take 1/3 of time! 0.039 call atplib#compiler#xpdfpid() " I could use here atplib#compiler#XpdPid(), the reason to not use it is that " then there is a way to run ATP without python. if atplib#compiler#xpdfpid != "" "if xpdf is running (then we want to reload it). "This is where I use 'ps' command to check if xpdf is "running. let Reload_Viewer = b:atp_Viewer . " -remote " . shellescape(b:atp_XpdfServer) . " -reload ; " else "if xpdf is not running (but we do not want "to run it). let Reload_Viewer = " " endif endif else if a:start " if b:atp_Viewer is not running and we want to open it. " the name of this variable is not missleading ... let Reload_Viewer = b:atp_Viewer . " " . shellescape(outfile) . " ; " " If run through RevSearch command use source specials rather than " just reload: if str2nr(a:start) == 2 let synctex = atplib#compiler#SidWrap('SyncTex') let callback_rs_cmd = v:progname . " --servername " . v:servername . " --remote-expr " . "'".synctex."()' ; " let Reload_Viewer = callback_rs_cmd endif else " If b:atp_Viewer is not running then we do not want to " open it. let Reload_Viewer = " " endif endif if g:atp_debugCompiler let g:Reload_Viewer = Reload_Viewer endif " IF OPENING NON EXISTING OUTPUT FILE " only xpdf needs to be run before (we are going to reload it) if a:start && b:atp_Viewer == "xpdf" let xpdf_options = ( exists("g:atp_xpdfOptions") ? join(g:atp_xpdfOptions, " ") : "" )." ".(exists("b:xpdfOptions") ? join(getbufvar(0, "atp_xpdfOptions"), " ") : " ") let start = b:atp_Viewer . " -remote " . shellescape(b:atp_XpdfServer) . " " . xpdf_options . " & " else let start = "" endif " SET THE COMMAND let interaction = ( a:verbose=="verbose" ? b:atp_VerboseLatexInteractionMode : 'nonstopmode' ) let variable = ( a:verbose!="verbose" ? substitute(b:atp_TexCompilerVariable, ';', ' ', 'g') : '' ) let comp = variable . " " . b:atp_TexCompiler . " " . substitute(b:atp_TexOptions, ',', ' ','g') . " -interaction=" . interaction . " -output-directory=" . shellescape(tmpdir) . " " . shellescape(a:filename) let vcomp = variable . " " . b:atp_TexCompiler . " " . substitute(b:atp_TexOptions, ',', ' ','g') . " -interaction=". interaction . " -output-directory=" . shellescape(tmpdir) . " " . shellescape(a:filename) " make function: " let make = "vim --servername " . v:servername . " --remote-expr 'MakeLatex\(\"".tmptex."\",1,0\)'" if a:verbose == 'verbose' let texcomp=vcomp else let texcomp=comp endif if runs >= 2 && a:bibtex != 1 " how many times we want to call b:atp_TexCompiler let i=1 while i < runs - 1 let i+=1 let texcomp=texcomp . " ; " . comp endwhile if a:verbose != 'verbose' let texcomp=texcomp . " ; " . comp else let texcomp=texcomp . " ; " . vcomp endif endif if a:bibtex == 1 " this should be decided using the log file as well. if filereadable(outaux) " call atplib#compiler#copy(outaux,tmpfile . ".aux") let texcomp="bibtex " . shellescape(fnamemodify(outaux, ":t")) . "; ".g:atp_cpcmd." ".shellescape(outbbl)." ".shellescape(tmpbbl).";" . comp . " 1>/dev/null 2>&1 " else let texcomp=comp.";clear;".g:atp_cpcmd." ".shellescape(tmpaux)." ".shellescape(outaux)."; bibtex ".shellescape(fnamemodify(outaux, ":t")).";".g:atp_cpcmd." ".shellescape(outbbl)." ".shellescape(tmpbbl)."; ".comp." 1>/dev/null 2>&1 " endif if a:verbose != 'verbose' let texcomp=texcomp . " ; " . comp else let texcomp=texcomp . " ; " . vcomp endif endif " catch the status if has('clientserver') && v:servername != "" && g:atp_callback == 1 let catchstatus_cmd = v:progname . ' --servername ' . v:servername . ' --remote-expr ' . \ shellescape('atplib#callback#TexReturnCode') . '\($?\) ; ' else let catchstatus_cmd = '' endif " copy output file (.pdf\|.ps\|.dvi) " let cpoptions = "--remove-destination" let cpoptions = "" let cpoutfile = g:atp_cpcmd." ".cpoptions." ".shellescape(atplib#append(tmpdir,"/"))."*".ext." ".shellescape(atplib#append(b:atp_OutDir,"/"))." ; " if a:start let command = "(" . texcomp . " ; (" . catchstatus_cmd . " " . cpoutfile . " " . Reload_Viewer . " ) || ( ". catchstatus_cmd . " " . cpoutfile . ") ; " else " Reload on Error: " for xpdf it copies the out file but does not reload the xpdf " server for other viewers it simply doesn't copy the out file. if b:atp_ReloadOnError || a:bang == "!" if a:bang == "!" let command="( ".texcomp." ; ".catchstatus_cmd." ".g:atp_cpcmd." ".cpoptions." ".shellescape(tmpaux)." ".shellescape(b:atp_OutDir)." ; ".cpoutfile." ".Reload_Viewer else let command="( (".texcomp." && ".g:atp_cpcmd." ".cpoptions." ".shellescape(tmpaux)." ".shellescape(b:atp_OutDir)." ) ; ".catchstatus_cmd." ".cpoutfile." ".Reload_Viewer endif else if b:atp_Viewer =~ '\' let command="( ".texcomp." && (".catchstatus_cmd.cpoutfile." ".Reload_Viewer." ".g:atp_cpcmd." ".cpoptions." ".shellescape(tmpaux)." ".shellescape(b:atp_OutDir)." ) || (".catchstatus_cmd." ".cpoutfile.") ; " else let command="(".texcomp." && (".catchstatus_cmd.cpoutfile." ".Reload_Viewer." ".g:atp_cpcmd." ".cpoptions." ".shellescape(tmpaux)." ".shellescape(b:atp_OutDir)." ) || (".catchstatus_cmd.") ; " endif endif endif if g:atp_debugCompiler silent echomsg "Reload_Viewer=" . Reload_Viewer let g:Reload_Viewer = Reload_Viewer let g:command = command elseif g:atp_debugCompiler >= 2 silent echomsg "command=" . command endif " Preserve files with extension belonging to the g:atp_keep list variable. let copy_cmd="" let j=1 for i in g:atp_keep " ToDo: this can be done using internal vim functions. if i != "aux" let copycmd=g:atp_cpcmd." ".cpoptions." ".shellescape(atplib#append(tmpdir,"/")). \ "*.".i." ".shellescape(atplib#append(b:atp_OutDir,"/")) else let copycmd=g:atp_cpcmd." ".cpoptions." ".shellescape(atplib#append(tmpdir,"/")). \ "*.".i." ".shellescape(atplib#append(b:atp_OutDir,"/".fnamemodify(b:atp_MainFile, ":t:r")."_aux")) endif if j == 1 let copy_cmd=copycmd else let copy_cmd=copy_cmd . " ; " . copycmd endif let j+=1 endfor if g:atp_debugCompiler let g:copy_cmd = copy_cmd endif let command=command . " " . copy_cmd . " ; " " Callback: if has('clientserver') && v:servername != "" && g:atp_callback == 1 " let callback = atplib#compiler#SidWrap('CallBack') let callback_cmd = v:progname . ' --servername ' . v:servername . ' --remote-expr ' . \ shellescape('atplib#callback#CallBack').'\(\"'.bufnr("%").'\",\"'.a:verbose.'\",\"'.a:command.'\",\"'.a:bibtex.'\"\)'. " ; " let command = command . " " . callback_cmd if g:atp_debugCompiler silent echomsg "callback_cmd=" . callback_cmd endif endif let rmtmp="rm -rf " . shellescape(fnamemodify(tmpdir, ":h")) . "; " let command=command . " " . rmtmp . ") &" if str2nr(a:start) != 0 let command=start . command endif " Take care about backup and writebackup options. if g:atp_debugCompiler silent echomsg "BEFORE WRITING: b:changedtick=" . b:changedtick . " b:atp_changedtick=" . b:atp_changedtick . " b:atp_running=" . b:atp_running endif call atplib#write("silent") if g:atp_debugCompiler silent echomsg "AFTER WRITING: b:changedtick=" . b:changedtick . " b:atp_changedtick=" . b:atp_changedtick . " b:atp_running=" . b:atp_running endif if a:verbose != 'verbose' " "cd ".shellescape(tmpdir).";". let g:atp_TexOutput=system(command) else let command="!clear;" . texcomp . " " . cpoutfile . " " . copy_cmd exe command endif unlockvar g:atp_TexCommand let g:atp_TexCommand=command lockvar g:atp_TexCommand if g:atp_debugCompiler silent echomsg "command=" . command redir END endif endfunction "}}} "{{{ aptlib#compiler#ThreadedCompiler function! atplib#compiler#ThreadedCompiler(bibtex, start, runs, verbose, command, filename, bang) " Write file: if g:atp_debugPythonCompiler call atplib#Log("ThreadedCompiler.log", "", "init") call atplib#Log("ThreadedCompiler.log", "PRE WRITING b:atp_changedtick=".b:atp_changedtick." b:changedtick=".b:changedtick) endif call atplib#write("silent") if g:atp_debugPythonCompiler call atplib#Log("ThreadedCompiler.log", "POST WRITING b:atp_changedtick=".b:atp_changedtick." b:changedtick=".b:changedtick) endif " Kill comiple.py scripts if there are too many of them. if len(b:atp_PythonPIDs) >= b:atp_MaxProcesses && b:atp_MaxProcesses let a=copy(b:atp_LatexPIDs) try if b:atp_KillYoungest " Remove the newest PIDs (the last in the b:atp_PythonPIDs) let pids=remove(b:atp_LatexPIDs, b:atp_MaxProcesses, -1) else " Remove the oldest PIDs (the first in the b:atp_PythonPIDs) /works nicely/ let pids=remove(b:atp_LatexPIDs, 0, max([len(b:atp_PythonPIDs)-b:atp_MaxProcesses-1,0])) endif echomsg string(a)." ".string(pids)." ".string(b:atp_LatexPIDs) call atplib#KillPIDs(pids) catch E684: endtry echomsg string(b:atp_LatexPIDs) endif " Set biber setting on the fly call atplib#compiler#SetBiberSettings() if !has('gui') && a:verbose == 'verbose' && len(b:atp_LatexPIDs) > 0 redraw! echomsg "[ATP:] please wait until compilation stops." return " This is not working: (I should kill compile.py scripts) echomsg "[ATP:] killing all instances of ".get(g:CompilerMsg_Dict,b:atp_TexCompiler,'TeX') call atplib#KillPIDs(b:atp_LatexPIDs,1) sleep 1 PID endif " Debug varibles " On Unix the output of compile.py run by this function is available at " g:atp_TempDir/compiler.py.log if g:atp_debugPythonCompiler call atplib#Log("ThreadedCompiler.log", "", "init") call atplib#Log("ThreadedCompiler.log", "a:bibtex=".a:bibtex) call atplib#Log("ThreadedCompiler.log", "a:start=".a:start) call atplib#Log("ThreadedCompiler.log", "a:runs=".a:runs) call atplib#Log("ThreadedCompiler.log", "a:verbose=".a:verbose) call atplib#Log("ThreadedCompiler.log", "a:command=".a:command) call atplib#Log("ThreadedCompiler.log", "a:filename=".a:filename) call atplib#Log("ThreadedCompiler.log", "a:bang=".a:bang) endif if !exists("t:atp_DebugMode") let t:atp_DebugMode = g:atp_DefaultDebugMode endif if t:atp_DebugMode != 'verbose' && a:verbose != 'verbose' let b:atp_LastLatexPID = -1 endif if t:atp_DebugMode != "silent" && b:atp_TexCompiler !~ "luatex" && \ (b:atp_TexCompiler =~ "^\s*\%(pdf\|xetex\)" && b:atp_Viewer == "xdvi" ? 1 : \ b:atp_TexCompiler !~ "^\s*pdf" && b:atp_TexCompiler !~ "xetex" && (b:atp_Viewer == "xpdf" || b:atp_Viewer == "epdfview" || b:atp_Viewer == "acroread" || b:atp_Viewer == "kpdf")) echohl WaningMsg | echomsg "[ATP:] your ".b:atp_TexCompiler." and ".b:atp_Viewer." are not compatible:" echomsg " b:atp_TexCompiler=" . b:atp_TexCompiler echomsg " b:atp_Viewer=" . b:atp_Viewer echohl None endif if !has('clientserver') if has("win16") || has("win32") || has("win64") || has("win95") echohl WarningMsg echomsg "[ATP:] ATP needs +clientserver vim compilation option." echohl None else echohl WarningMsg echomsg "[ATP:] python compiler needs +clientserver vim compilation option." echomsg " falling back to g:atp_Compiler=\"bash\"" echohl None let g:atp_Compiler = "bash" return endif endif " Set options for compile.py let interaction = ( a:verbose=="verbose" ? b:atp_VerboseLatexInteractionMode : 'nonstopmode' ) let tex_options = b:atp_TexOptions.',-interaction='.interaction " let g:tex_options=tex_options let ext = get(g:atp_CompilersDict, matchstr(b:atp_TexCompiler, '^\s*\zs\S\+\ze'), ".pdf") let ext = substitute(ext, '\.', '', '') let global_options = join((exists("g:atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? g:atp_{matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')}Options : []), ";") let local_options = join(( exists("atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") ? getbufvar(bufnr("%"), "atp_".matchstr(b:atp_Viewer, '^\s*\zs\S\+\ze')."Options") : []), ";") if global_options != "" let viewer_options = global_options.";".local_options else let viewer_options = local_options endif let file = atplib#FullPath(a:filename) let bang = ( a:bang == '!' ? ' --bang ' : '' ) let bibtex = ( a:bibtex ? ' --bibtex ' : '' ) let reload_on_error = ( b:atp_ReloadOnError ? ' --reload-on-error ' : '' ) let gui_running = ( has("gui_running") ? ' --gui-running ' : '' ) let reload_viewer = ( index(g:atp_ReloadViewers, b:atp_Viewer)+1 ? ' --reload-viewer ' : '' ) let aucommand = ( a:command == "AU" ? ' --aucommand ' : '' ) let no_progress_bar = ( g:atp_ProgressBar ? '' : ' --no-progress-bar ' ) let bibliographies = join(keys(filter(copy(b:TypeDict), "v:val == 'bib'")), ',') let autex_wait = ( b:atp_autex_wait ? ' --autex_wait ' : '') let keep = join(g:atp_keep, ',') python << ENDPYTHON import vim, threading import sys, errno, os.path, shutil, subprocess, psutil, re, tempfile, optparse, glob import traceback, atexit from os import chdir, mkdir, putenv, devnull from collections import deque #################################### # # Functions: # #################################### def nonempty(string): if str(string) == '': return False else: return True def decode_list(byte): return byte.decode() def latex_progress_bar(cmd): # Run latex and send data for progress bar, child = subprocess.Popen(cmd, stdout=subprocess.PIPE) # If I remove the code below and only put child.wait() # then vim crashes. pid = child.pid vim.eval("atplib#callback#LatexPID("+str(pid)+")") debug_file.write("latex pid "+str(pid)+"\n") stack = deque([]) while True: try: out = child.stdout.read(1).decode() except UnicodeDecodeError: debug_file.write("UNICODE DECODE ERROR:\n") debug_file.write(child.stdout.read(1)) debug_file.write("\n") debug_file.write("stack="+''.join(stack)+"\n") out = "" if out == '' and child.poll() != None: break if out != '': stack.append(out) if len(stack)>10: stack.popleft() match = re.match('\[(\n?\d(\n|\d)*)({|\])',str(''.join(stack))) if match: vim.eval("atplib#callback#ProgressBar("+match.group(1)[match.start():match.end()]+","+str(pid)+")") child.wait() vim.eval("atplib#callback#ProgressBar('end',"+str(pid)+")") vim.eval("atplib#callback#PIDsRunning(\"b:atp_LatexPIDs\")") return child def xpdf_server_file_dict(): # Make dictionary of the type { xpdf_servername : [ file, xpdf_pid ] }, # to test if the server host file use: # basename(xpdf_server_file_dict().get(server, ['_no_file_'])[0]) == basename(file) # this dictionary always contains the full path (Linux). # TODO: this is not working as I want to: # when the xpdf was opened first without a file it is not visible in the command line # I can use 'xpdf -remote -exec "run('echo %f')"' # where get_filename is a simple program which returns the filename. # Then if the file matches I can just reload, if not I can use: # xpdf -remote -exec "openFile(file)" ps_list=psutil.get_pid_list() server_file_dict={} for pr in ps_list: try: name=psutil.Process(pr).name cmdline=psutil.Process(pr).cmdline if name == 'xpdf': try: ind=cmdline.index('-remote') except: ind=0 if ind != 0 and len(cmdline) >= 1: server_file_dict[cmdline[ind+1]]=[cmdline[len(cmdline)-1], pr] except psutil.error.NoSuchProcess: pass except psutil.error.AccessDenied: pass return server_file_dict #################################### # # Options: # #################################### tex_file = vim.eval("b:atp_MainFile") command = vim.eval("b:atp_TexCompiler") bibcommand = vim.eval("b:atp_BibCompiler") progname = vim.eval("v:progname") if vim.eval("aucommand") == ' --aucommand ': aucommand_bool = True aucommand="AU" else: aucommand_bool = False aucommand="COM" command_opt = list(filter(nonempty,re.split('\s*,\s*', vim.eval("tex_options")))) mainfile_fp = vim.eval("file") output_format = vim.eval("ext") if output_format == "pdf": extension = ".pdf" else: extension = ".dvi" runs = int(vim.eval("a:runs")) servername = vim.eval("v:servername") start = str(vim.eval("a:start")) viewer = vim.eval("b:atp_Viewer") if vim.eval("autex_wait") == "--autex_wait": autex_wait = True else: autex_wait = False XpdfServer = vim.eval("b:atp_XpdfServer") viewer_rawopt = re.split('\s*;\s*', vim.eval("viewer_options")) viewer_it = list(filter(nonempty, viewer_rawopt)) viewer_opt =[] for opt in viewer_it: viewer_opt.append(opt) viewer_rawopt = viewer_opt if viewer == "xpdf" and XpdfServer != None: viewer_opt.extend(["-remote", XpdfServer]) verbose = vim.eval("a:verbose") keep = vim.eval("keep").split(',') keep = list(filter(nonempty, keep)) def keep_filter_aux(string): if string == 'aux': return False else: return True def keep_filter_log(string): if string == 'log': return False else: return True def mysplit(string): return re.split('\s*=\s*', string) env = list(map(mysplit, list(filter(nonempty, re.split('\s*;\s*',vim.eval("b:atp_TexCompilerVariable")))))) # Boolean options if vim.eval("reload_viewer") == ' --reload-viewer ': reload_viewer = True else: reload_viewer = False if vim.eval("bibtex") == ' --bibtex ': bibtex = True else: bibtex = False bibliographies = vim.eval("bibliographies").split(",") bibliographies = list(filter(nonempty, bibliographies)) if vim.eval("a:bang") == "!": bang = True else: bang = False if vim.eval("reload_on_error") == ' --reload-on-error ': reload_on_error = True else: reload_on_error = False if vim.eval("gui_running") == ' --gui-running ': gui_running = True else: gui_running = False if vim.eval("no_progress_bar") == ' --no-progress-bar ': progress_bar = False else: progress_bar = True # Debug file should be changed for sth platform independent # There should be a switch to get debug info. logdir = vim.eval("g:atp_TempDir") script_logfile = os.path.join(logdir, 'compile.log') debug_file = open(script_logfile, 'w') debug_file.write("COMMAND "+command+"\n") debug_file.write("BIBCOMMAND "+bibcommand+"\n") debug_file.write("BIBCOMMAND "+bibcommand+"\n") debug_file.write("AUCOMMAND "+aucommand+"\n") debug_file.write("PROGNAME "+progname+"\n") debug_file.write("COMMAND_OPT "+str(command_opt)+"\n") debug_file.write("MAINFILE_FP "+str(mainfile_fp)+"\n") debug_file.write("OUTPUT FORMAT "+str(output_format)+"\n") debug_file.write("EXT "+extension+"\n") debug_file.write("RUNS "+str(runs)+"\n") debug_file.write("VIM_SERVERNAME "+str(servername)+"\n") debug_file.write("START "+str(start)+"\n") debug_file.write("VIEWER "+str(viewer)+"\n") debug_file.write("XPDF_SERVER "+str(XpdfServer)+"\n") debug_file.write("VIEWER_OPT "+str(viewer_opt)+"\n") debug_file.write("DEBUG MODE (verbose) "+str(verbose)+"\n") debug_file.write("KEEP "+str(keep)+"\n") debug_file.write("BIBLIOGRAPHIES "+str(bibliographies)+"\n") # debug_file.write("ENV OPTION "+str(options.env)+"\n") debug_file.write("ENV "+str(env)+"\n") debug_file.write("*BIBTEX "+str(bibtex)+"\n") debug_file.write("*BANG "+str(bang)+"\n") debug_file.write("*RELOAD_VIEWER "+str(reload_viewer)+"\n") debug_file.write("*RELOAD_ON_ERROR "+str(reload_on_error)+"\n") debug_file.write("*GUI_RUNNING "+str(gui_running)+"\n") debug_file.write("*PROGRESS_BAR "+str(progress_bar)+"\n") class LatexThread( threading.Thread ): def run( self ): # Author: Marcin Szamotulski # This file is a part of Automatic TeX Plugin for Vim. # readlink is not available on Windows. readlink=True try: from os import readlink except ImportError: readlink=False # Cleanup on exit: def cleanup(debug_file): debug_file.close() shutil.rmtree(tmpdir) # atexit.register(cleanup, debug_file) #################################### # # Arguments: # #################################### global tex_file, command, bibcommand, progname, aucommand_bool, aucommand global command_opt, mainfile_fp, output_format, extension, runs, servername, start global viewer, autex_wait, XpdfServer, viewer_rawopt, viewer_it, viewer_opt global viewer_rawopt, verbose, keep, env global reload_viewer, bibtex, bibliographies, bang, reload_on_error, gui_running, progress_bar # If mainfile_fp is not a full path make it. # glob=glob.glob(os.path.join(os.getcwd(),mainfile_fp)) # if len(glob) != 0: # mainfile_fp = glob[0] mainfile = os.path.basename(mainfile_fp) mainfile_dir = os.path.dirname(mainfile_fp) if mainfile_dir == "": mainfile_fp = os.path.join(os.getcwd(), mainfile) mainfile = os.path.basename(mainfile_fp) mainfile_dir= os.path.dirname(mainfile_fp) if os.path.islink(mainfile_fp): if readlink: mainfile_fp = os.readlink(mainfile_fp) # The above line works if the symlink was created with full path. mainfile = os.path.basename(mainfile_fp) mainfile_dir= os.path.dirname(mainfile_fp) mainfile_dir = os.path.normcase(mainfile_dir) [basename, ext] = os.path.splitext(mainfile) output_fp = os.path.splitext(mainfile_fp)[0]+extension try: # Send pid to ATP: if verbose != "verbose": vim.eval("atplib#callback#PythonPID("+str(os.getpid())+")") #################################### # # Make temporary directory, # Copy files and Set Environment: # #################################### cwd = os.getcwd() if not os.path.exists(os.path.join(mainfile_dir,".tmp")): # This is the main tmp dir (./.tmp) # it will not be deleted by this script # as another instance might be using it. # it is removed by Vim on exit. os.mkdir(os.path.join(mainfile_dir,".tmp")) tmpdir = tempfile.mkdtemp(dir=os.path.join(mainfile_dir,".tmp"),prefix="") debug_file.write("TMPDIR: "+tmpdir+"\n") tmpaux = os.path.join(tmpdir,basename+".aux") command_opt.append('-output-directory='+tmpdir) latex_cmd = [command]+command_opt+[mainfile_fp] debug_file.write("COMMAND "+str(latex_cmd)+"\n") debug_file.write("COMMAND "+" ".join(latex_cmd)+"\n") # Copy important files to output directory: # /except the log file/ os.chdir(mainfile_dir) for ext in filter(keep_filter_log,keep): file_cp=basename+"."+ext if os.path.exists(file_cp): shutil.copy(file_cp, tmpdir) tempdir_list = os.listdir(tmpdir) debug_file.write("\nls tmpdir "+str(tempdir_list)+"\n") # Set environment for var in env: debug_file.write("ENV "+var[0]+"="+var[1]+"\n") os.putenv(var[0], var[1]) # Link local bibliographies: for bib in bibliographies: if os.path.exists(os.path.join(mainfile_dir,os.path.basename(bib))): os.symlink(os.path.join(mainfile_dir,os.path.basename(bib)),os.path.join(tmpdir,os.path.basename(bib))) #################################### # # Compile: # #################################### # Start Xpdf (this can be done before compelation, because we can load file # into afterwards) in this way Xpdf starts faster (it is already running when # file compiles). # TODO: this might cause problems when the tex file is very simple and short. # Can we test if xpdf started properly? okular doesn't behave nicely even with # --unique switch. # Latex might not run this might happedn with bibtex (?) latex_returncode=0 if bibtex and os.path.exists(tmpaux): if bibcommand == 'biber': bibfname = basename else: bibfname = basename+".aux" debug_file.write("\nBIBTEX1"+str([bibcommand, bibfname])+"\n") os.chdir(tmpdir) bibtex_popen=subprocess.Popen([bibcommand, bibfname], stdout=subprocess.PIPE) vim.eval("atplib#callback#BibtexPID('"+str(bibtex_popen.pid)+"')") vim.eval("atplib#callback#redrawstatus()") bibtex_popen.wait() vim.eval("atplib#callback#PIDsRunning(\"b:atp_BibtexPIDs\")") os.chdir(mainfile_dir) bibtex_returncode=bibtex_popen.returncode bibtex_output=re.sub('"', '\\"', bibtex_popen.stdout.read()) debug_file.write("BIBTEX RET CODE "+str(bibtex_returncode)+"\nBIBTEX OUTPUT\n"+bibtex_output+"\n") if verbose != 'verbose': vim.eval("atplib#callback#BibtexReturnCode('"+str(bibtex_returncode)+"',\""+str(bibtex_output)+"\")") else: print(bibtex_output) # We need run latex at least 2 times bibtex=False runs=max([runs, 2]) # If bibtex contained errros we stop: # if not bibtex_returncode: # runs=max([runs, 2]) # else: # runs=1 elif bibtex: # we need run latex at least 3 times runs=max([runs, 3]) debug_file.write("\nRANGE="+str(range(1,runs+1))+"\n") debug_file.write("RUNS="+str(runs)+"\n") for i in range(1, runs+1): debug_file.write("RUN="+str(i)+"\n") debug_file.write("DIR="+str(os.getcwd())+"\n") tempdir_list = os.listdir(tmpdir) debug_file.write("ls tmpdir "+str(tempdir_list)+"\n") debug_file.write("BIBTEX="+str(bibtex)+"\n") if verbose == 'verbose' and i == runs: # compiler() contains here ( and not bibtex ) debug_file.write("VERBOSE"+"\n") latex=subprocess.Popen(latex_cmd) pid=latex.pid debug_file.write("latex pid "+str(pid)+"\n") latex.wait() latex_returncode=latex.returncode debug_file.write("latex ret code "+str(latex_returncode)+"\n") else: if progress_bar and verbose != 'verbose': latex=latex_progress_bar(latex_cmd) else: latex = subprocess.Popen(latex_cmd, stdout=subprocess.PIPE) pid = latex.pid vim.eval("atplib#callback#LatexPID("+str(pid)+")") debug_file.write("latex pid "+str(pid)+"\n") latex.wait() vim.eval("atplib#callback#PIDsRunning(\"b:atp_LatexPIDs\")") latex_returncode=latex.returncode debug_file.write("latex return code "+str(latex_returncode)+"\n") tempdir_list = os.listdir(tmpdir) debug_file.write("JUST AFTER LATEX ls tmpdir "+str(tempdir_list)+"\n") # Return code of compilation: if verbose != "verbose": vim.eval("atplib#callback#TexReturnCode('"+str(latex_returncode)+"')") if bibtex and i == 1: if bibcommand == 'biber': bibfname = basename else: bibfname = basename+".aux" debug_file.write("BIBTEX2 "+str([bibcommand, bibfname])+"\n") debug_file.write(os.getcwd()+"\n") tempdir_list = os.listdir(tmpdir) debug_file.write("ls tmpdir "+str(tempdir_list)+"\n") os.chdir(tmpdir) bibtex_popen=subprocess.Popen([bibcommand, bibfname], stdout=subprocess.PIPE) vim.eval("atplib#callback#BibtexPID('"+str(bibtex_popen.pid)+"')") vim.eval("atplib#callback#redrawstatus()") bibtex_popen.wait() vim.eval("atplib#callback#PIDsRunning(\"b:atp_BibtexPIDs\")") os.chdir(mainfile_dir) bibtex_returncode=bibtex_popen.returncode bibtex_output=re.sub('"', '\\"', bibtex_popen.stdout.read()) debug_file.write("BIBTEX2 RET CODE"+str(bibtex_returncode)+"\n") if verbose != 'verbose': vim.eval("atplib#callback#BibtexReturnCode('"+str(bibtex_returncode)+"',\""+str(bibtex_output)+"\")") else: print(bibtex_output) # If bibtex had errors we stop, # at this point tex file was compiled at least once. # if bibtex_returncode: # debug_file.write("BIBTEX BREAKE "+str(bibtex_returncode)+"\n") # break #################################### # # Copy Files: # #################################### # Copy files: os.chdir(tmpdir) for ext in list(filter(keep_filter_aux,keep))+[output_format]: file_cp=basename+"."+ext if os.path.exists(file_cp): debug_file.write(file_cp+' ') shutil.copy(file_cp, mainfile_dir) # Copy aux file if there were no compilation errors or if it doesn't exists in mainfile_dir. # copy aux file to _aux file (for atplib#tools#GrepAuxFile) if latex_returncode == 0 or not os.path.exists(os.path.join(mainfile_dir, basename+".aux")): file_cp=basename+".aux" if os.path.exists(file_cp): shutil.copy(file_cp, mainfile_dir) file_cp=basename+".aux" if os.path.exists(file_cp): shutil.copy(file_cp, os.path.join(mainfile_dir, basename+"._aux")) os.chdir(cwd) #################################### # # Call Back Communication: # #################################### if verbose != "verbose": debug_file.write("CALL BACK "+"atplib#callback#CallBack('"+str(verbose)+"','"+aucommand+"','"+str(bibtex)+"')"+"\n") vim.eval("atplib#callback#CallBack('"+str(verbose)+"','"+aucommand+"','"+str(bibtex)+"')") # return code of compelation is returned before (after each compilation). #################################### # # Reload/Start Viewer: # #################################### if re.search(viewer, '^\s*xpdf\e') and reload_viewer: # The condition tests if the server XpdfServer is running xpdf_server_dict=xpdf_server_file_dict() cond = xpdf_server_dict.get(XpdfServer, ['_no_file_']) != ['_no_file_'] debug_file.write("XPDF SERVER DICT="+str(xpdf_server_dict)+"\n") debug_file.write("COND="+str(cond)+":"+str(reload_on_error)+":"+str(bang)+"\n") debug_file.write("COND="+str( not reload_on_error or bang )+"\n") debug_file.write(str(xpdf_server_dict)+"\n") if start == 1: run=['xpdf'] run.extend(viewer_opt) run.append(output_fp) debug_file.write("D1: "+str(run)+"\n") subprocess.Popen(run) elif cond and ( reload_on_error or latex_returncode == 0 or bang ): run=['xpdf', '-remote', XpdfServer, '-reload'] subprocess.Popen(run, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) debug_file.write("D2: "+str(['xpdf', '-remote', XpdfServer, '-reload'])+"\n") else: if start >= 1: run=[viewer] run.extend(viewer_opt) run.append(output_fp) debug_file.write("RUN "+str(run)+"\n") subprocess.Popen(run, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) if start == 2: vim.eval("atplib#SyncTex()") #################################### # # Clean: # #################################### except Exception: error_str=re.sub("'", "''",re.sub('"', '\\"', traceback.format_exc())) traceback.print_exc(None, debug_file) vim.eval("atplib#callback#Echo(\"[ATP:] error in compile.py, catched python exception:\n"+error_str+"[ATP info:] this error message is recorded in compile.py.log under g:atp_TempDir\",'echo','ErrorMsg')") # cleanup(debug_file) # return(latex_returncode) LatexThread().start() ENDPYTHON endfunction "}}} " {{{ atplib#compiler#tex [test function] function! atplib#compiler#tex() " Notes: " this goes well untill status line is calling functions or functions which " are called via autocommands. Strange errors occur, for example: " Error detected while processing function 106_HighlightMatchingPair..LatexBox_InComment: " line 3: " E121: Undefined variable: a:var " and other similar errors. Mainly (if not only) errors E121. python << ENDPYTHON import vim, threading import sys, errno, os.path, shutil, subprocess, psutil, re, tempfile, optparse, glob import traceback, atexit from os import chdir, mkdir, putenv, devnull from collections import deque def latex_progress_bar(cmd): # Run latex and send data for progress bar, child = subprocess.Popen(cmd, stdout=subprocess.PIPE) # If I remove the code below and only put child.wait() # then vim crashes. pid = child.pid vim.eval("atplib#callback#LatexPID("+str(pid)+")") stack = deque([]) while True: try: out = child.stdout.read(1).decode() except UnicodeDecodeError: out = "" if out == '' and child.poll() != None: break if out != '': stack.append(out) if len(stack)>10: stack.popleft() match = re.match('\[(\n?\d(\n|\d)*)({|\])',str(''.join(stack))) if match: vim.eval("atplib#callback#ProgressBar("+match.group(1)[match.start():match.end()]+","+str(pid)+")") child.wait() vim.eval("atplib#callback#ProgressBar('end',"+str(pid)+")") vim.eval("atplib#callback#PIDsRunning(\"b:atp_LatexPIDs\")") return child class LatexThread( threading.Thread ): def run( self ): file=vim.eval("b:atp_MainFile") latex_progress_bar(['pdflatex', file]) LatexThread().start() ENDPYTHON endfunction "}}} " AUTOMATIC TEX PROCESSING: " {{{ atplib#compiler#auTeX " This function calls the compilers in the background. It Needs to be a global " function (it is used in options.vim, there is a trick to put function into " a dictionary ... ) augroup ATP_changedtick au! au BufEnter *.tex :let b:atp_changedtick = b:changedtick au BufWritePost *.tex :let b:atp_changedtick = b:changedtick augroup END function! atplib#compiler#auTeX(...) if !exists("b:atp_changedtick") let b:atp_changedtick = b:changedtick endif if g:atp_debugauTeX echomsg "*****************" echomsg "b:atp_changedtick=".b:atp_changedtick." b:changedtick=".b:changedtick endif if mode() == 'i' && b:atp_updatetime_insert == 0 || \ mode()=='n' && b:atp_updatetime_normal == 0 if g:atp_debugauTeX echomsg "autex is off for the mode: ".mode() endif return "autex is off for the mode: ".mode()." (see :help mode())" endif if mode() == 'i' && g:atp_noautex_in_math && atplib#IsInMath() return "noautex in math mode" endif " Wait if the compiler is running. The problem is that CursorHoldI autocommands " are not triggered more than once after 'updatetime'. " if index(split(g:atp_autex_wait, ','), mode()) != -1 " " \ !b:atp_autex_wait " if g:atp_Compiler == "python" " call atplib#callback#PIDsRunning("b:atp_PythonPIDs") " else " call atplib#callback#PIDsRunning("b:atp_LatexPIDs") " endif " call atplib#callback#PIDsRunning("b:atp_BibtexPIDs") " echo string(b:atp_BibtexPIDs) " if g:atp_Compiler == "python" && len(b:atp_PythonPIDs) || " \ g:atp_Compiler == "bash" && len(b:atp_LatexPIDs) || " \ len(b:atp_BibtexPIDs) " " unlockvar b:atp_autex_wait " " let b:atp_autex_wait=1 " " lockvar b:atp_autex_wait " if g:atp_debugauTeX " echomsg "autex wait" " endif " return " endif " " else " " unlockvar b:atp_autex_wait " " let b:atp_autex_wait=0 " " lockvar b:atp_autex_wait " endif " Using vcscommand plugin the diff window ends with .tex thus the autocommand " applies but the filetype is 'diff' thus we can switch tex processing by: if &l:filetype !~ "tex$" echo "wrong file type" return "wrong file type" endif let atp_MainFile = atplib#FullPath(b:atp_MainFile) let mode = ( g:atp_DefaultDebugMode == 'verbose' ? 'debug' : g:atp_DefaultDebugMode ) if !b:atp_autex if g:atp_debugauTeX echomsg "autex is off" endif return "autex is off" endif " if the file (or input file is modified) compile the document if filereadable(expand("%")) " if !exists("b:atp_changedtick") " let b:atp_changedtick = b:changedtick " endif if g:atp_Compare ==? "changedtick" let cond = ( b:changedtick != b:atp_changedtick ) else let cond = ( atplib#compiler#compare(readfile(expand("%"))) ) endif if g:atp_debugauTeX let g:cond=cond if g:atp_debugauTeX echomsg "COND=".cond endif endif if cond " This is for changedtick only let b:atp_changedtick = b:changedtick + 1 " +1 because atplib#compiler#Compiler saves the file what increases b:changedtick by 1. " this is still needed as I use not nesting BufWritePost autocommand to set " b:atp_changedtick (by default autocommands do not nest). Alternate solution is to " run atplib#compiler#AuTeX() with nested autocommand (|autocmd-nested|). But this seems " to be less user friendly, nested autocommands allows only 10 levels of " nesting (which seems to be high enough). " " if atplib#compiler#NewCompare() let g:debug=0 if g:atp_Compiler == 'python' if g:atp_devversion == 0 call atplib#compiler#PythonCompiler(0, 0, b:atp_auruns, mode, "AU", atp_MainFile, "") else call atplib#compiler#ThreadedCompiler(0, 0, b:atp_auruns, mode, "AU", atp_MainFile, "") endif else call atplib#compiler#Compiler(0, 0, b:atp_auruns, mode, "AU", atp_MainFile, "") endif redraw if g:atp_debugauTeX echomsg "compile" endif return "compile" endif " if compiling for the first time else try " Do not write project script file while saving the file. let atp_ProjectScript = ( exists("g:atp_ProjectScript") ? g:atp_ProjectScript : -1 ) let g:atp_ProjectScript = 0 w if atp_ProjectScript == -1 unlet g:atp_ProjectScript else let g:atp_ProjectScript = atp_ProjectScript endif catch /E212:/ echohl ErrorMsg if g:atp_debugauTeX echomsg expand("%") . "E212: Cannon open file for writing" endif echohl None if g:atp_debugauTeX echomsg " E212" endif return " E212" catch /E382:/ " This option can be set by VCSCommand plugin using VCSVimDiff command if g:atp_debugauTeX echomsg " E382" endif return " E382" endtry if g:atp_Compiler == 'python' call atplib#compiler#PythonCompiler(0, 0, b:atp_auruns, mode, "AU", atp_MainFile, "") else call atplib#compiler#Compiler(0, 0, b:atp_auruns, mode, "AU", atp_MainFile, "") endif redraw if g:atp_debugauTeX echomsg "compile for the first time" endif return "compile for the first time" endif if g:atp_debugauTeX echomsg "files does not differ" endif return "files does not differ" endfunction " function! ATP_auTeX() " call atplib#compiler#auTeX() " endfunction " This is set by SetProjectName (options.vim) where it should not! augroup ATP_auTeX au! au CursorHold *.tex call atplib#compiler#auTeX() au CursorHoldI *.tex call atplib#compiler#auTeX() augroup END "}}} " Related Functions " {{{ atplib#compiler#TeX " a:runs = how many consecutive runs " a:1 = one of 'default','silent', 'debug', 'verbose' " if not specified uses 'default' mode " (g:atp_DefaultDebugMode). function! atplib#compiler#TeX(runs, bang, ...) let atp_MainFile = atplib#FullPath(b:atp_MainFile) if !exists("t:atp_DebugMode") let t:atp_DebugMode = g:atp_DefaultDebugMode endif if a:0 >= 1 let mode = ( a:1 != 'default' ? a:1 : t:atp_DebugMode ) else let mode = t:atp_DebugMode endif if mode =~# '^s\%[ilent]$' let mode = 'silent' elseif mode =~# '^d\%[ebug]$' let mode = 'debug' elseif mode =~# 'D\%[ebug]$' let mode = 'Debug' elseif mode =~# '^v\%[erbose]$' let mode = 'verbose' else let mode = t:atp_DebugMode endif for cmd in keys(g:CompilerMsg_Dict) if b:atp_TexCompiler =~ '^\s*' . cmd . '\s*$' let Compiler = g:CompilerMsg_Dict[cmd] break else let Compiler = b:atp_TexCompiler endif endfor if l:mode != 'silent' if a:runs > 2 && a:runs <= 5 echo "[ATP:] ".Compiler . " will run " . a:1 . " times." elseif a:runs == 2 echo "[ATP:] ".Compiler . " will run twice." elseif a:runs == 1 echo "[ATP:] ".Compiler . " will run once." elseif a:runs > 5 echo "[ATP:] ".Compiler . " will run " . s:runlimit . " times." endif endif if g:atp_Compiler == 'python' if g:atp_devversion == 0 call atplib#compiler#PythonCompiler(0,0, a:runs, mode, "COM", atp_MainFile, a:bang) else call atplib#compiler#ThreadedCompiler(0,0, a:runs, mode, "COM", atp_MainFile, a:bang) endif else call atplib#compiler#Compiler(0,0, a:runs, mode, "COM", atp_MainFile, a:bang) endif endfunction " command! -buffer -count=1 VTEX :call atplib#compiler#TeX(, 'verbose') "}}} "{{{ atplib#compiler#DebugComp() function! atplib#compiler#DebugComp(A,L,P) return "silent\ndebug\nDebug\nverbose" endfunction "}}} "{{{ atplib#compiler#Bibtex function! atplib#compiler#SimpleBibtex() let bibcommand = b:atp_BibCompiler." " let atp_MainFile = atplib#FullPath(b:atp_MainFile) if b:atp_BibCompiler =~ '^\s*biber\>' let file = fnamemodify(resolve(atp_MainFile),":t:r") else let file = fnamemodify(resolve(atp_MainFile),":t:r") . ".aux" endif let auxfile = fnamemodify(resolve(atp_MainFile),":t:r") . ".aux" " When oupen_out = p (in texmf.cnf) bibtex can only open files in the working " directory and they should no be given with full path: " p (paranoid) : as `r' and disallow going to parent directories, and " restrict absolute paths to be under $TEXMFOUTPUT. let saved_cwd = getcwd() exe "lcd " . fnameescape(b:atp_OutDir) let g:cwd = getcwd() if filereadable(auxfile) let command = bibcommand . shellescape(file) let b:atp_BibtexOutput=system(command) let b:atp_BibtexReturnCode=v:shell_error echo b:atp_BibtexOutput else echo "[ATP:] aux file " . auxfile . " not readable." endif exe "lcd " . fnameescape(saved_cwd) endfunction function! atplib#compiler#Bibtex(bang, ...) if a:0 >= 1 && a:1 =~# '^o\%[utput]$' redraw! if exists("b:atp_BibtexReturnCode") echo "[Bib:] BibTeX returned with exit code " . b:atp_BibtexReturnCode endif if exists("b:atp_BibtexOutput") echo substitute(b:atp_BibtexOutput, '\(^\zs\|\n\)', '\1 ', "g") else echo "No BibiTeX output." endif return elseif a:bang == "" call atplib#compiler#SimpleBibtex() return endif let atp_MainFile = atplib#FullPath(b:atp_MainFile) let g:a=a:0 if a:0 >= 1 let mode = ( a:1 != 'default' ? a:1 : t:atp_DebugMode ) else let mode = t:atp_DebugMode endif if mode =~# '^s\%[ilent]$' let mode = 'silent' elseif mode =~# '^d\%[ebug]$' let mode = 'debug' elseif mode =~# 'D\%[ebug]$' let mode = 'Debug' elseif mode =~# '^v\%[erbose]$' let mode = 'verbose' else let mode = t:atp_DebugMode endif if g:atp_Compiler == 'python' if g:atp_devversion == 0 call atplib#compiler#PythonCompiler(1, 0, 0, mode, "COM", atp_MainFile, "") else call atplib#compiler#ThreadedCompiler(1, 0, 0, mode, "COM", atp_MainFile, "") endif else call atplib#compiler#Compiler(1, 0, 0, mode, "COM", atp_MainFile, "") endif endfunction function! atplib#compiler#BibtexComp(A,L,P) return "silent\ndebug\nDebug\nverbose\noutput" endfunction "}}} " Show Errors Function " (some error tools are in various.vim: ':ShowErrors o') " {{{ SHOW ERRORS " " this functions sets errorformat according to the flag given in the argument, " possible flags: " e - errors (or empty flag) " w - all warning messages " c - citation warning messages " r - reference warning messages " f - font warning messages " fi - font warning and info messages " F - files " p - package info messages " {{{ atplib#compiler#SetErrorFormat " first argument is a word in flags " the default is a:1=e /show only error messages/ function! atplib#compiler#SetErrorFormat(cgetfile,...) " This a:cgetfile == 1 only if run by the command :ErrorFormat let efm = ( a:0 >= 1 ? a:1 : '' ) if efm == "" || a:0 == 0 echo "[ATP:] current error format: ".getbufvar(bufnr(fnamemodify(&l:errorfile, ":r").".tex"), "atp_ErrorFormat") return endif let carg_raw = ( a:0 >= 1 ? a:1 : g:atp_DefaultErrorFormat ) let carg_list= split(carg_raw, '\zs') if carg_list[0] =~ '^[+-]$' let add=remove(carg_list,0) else let add=0 endif for i in range(0, len(carg_list)-2) if carg_list[i] == 'f' && get(carg_list,i+1, "") == "i" call remove(carg_list, i+1) let carg_list[i]="fi" endif endfor " Get the bufnr of tex file corresponding to the &l:errorfile let bufnr = bufnr(fnamemodify(&l:errorfile, ":r").".tex") let carg = !exists("w:quickfix_title") && exists("b:atp_ErrorFormat") \ ? b:atp_ErrorFormat \ : getbufvar((bufnr), "atp_ErrorFormat") let atp_ErrorFormat = ( exists("b:atp_ErrorFormat") ? b:atp_ErrorFormat : getbufvar((bufnr), "atp_ErrorFormat") ) if carg_raw =~ '^+' for flag in carg_list if flag != 'f' && atp_ErrorFormat !~ flag || flag == 'f' && atp_ErrorFormat !~ 'fi\@!' let carg .= flag endif endfor elseif carg_raw =~ '^-' for flag in carg_list if flag != 'f' let carg=substitute(carg, flag, '', 'g') else let carg=substitute(carg, 'fi\@!', '', 'g') endif endfor else let carg=carg_raw endif let b:atp_ErrorFormat = carg if exists("w:quickfix_title") call setbufvar(bufnr, "atp_ErrorFormat", carg) endif let &l:errorformat="" if ( carg =~ 'e' || carg =~# 'all' ) " let efm = "!\ LaTeX\ %trror:\ %m,!\ %m,!pdfTeX %trror:\ %m" let efm = "%E!\ LaTeX\ Error:\ %m,\%E!\ %m,%E!pdfTeX Error:\ %m" if &l:errorformat == "" let &l:errorformat= efm else let &l:errorformat= &l:errorformat . "," . efm endif endif if ( carg =~ 'w' || carg =~# 'all' ) let efm='%WLaTeX\ %tarning:\ %m\ on\ input\ line\ %l%., \%WLaTeX\ %.%#Warning:\ %m, \%Z(Font) %m\ on\ input\ line\ %l%., \%+W%.%#\ at\ lines\ %l--%*\\d' " let efm= " \'%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#, " \%+W%.%#\ at\ lines\ %l--%*\\d, " \%WLaTeX\ %.%#Warning:\ %m' if &l:errorformat == "" let &l:errorformat=efm else let &l:errorformat= &l:errorformat . ',' . efm " let &l:errorformat= &l:errorformat . ',%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#, " \%WLaTeX\ %.%#Warning:\ %m, " \%+W%.%#\ at\ lines\ %l--%*\\d' endif endif if ( carg =~ '\Cc' || carg =~# 'all' ) " NOTE: " I would like to include 'Reference/Citation' as an error message (into %m) " but not include the 'LaTeX Warning:'. I don't see how to do that actually. " The only solution, that I'm aware of, is to include the whole line using " '%+W' but then the error messages are long and thus not readable. if &l:errorformat == "" let &l:errorformat = "%WLaTeX\ Warning:\ Citation\ %m\ on\ input\ line\ %l%.%#" else let &l:errorformat = &l:errorformat . ",%WLaTeX\ Warning:\ Citation\ %m\ on\ input\ line\ %l%.%#" endif endif if ( carg =~ '\Cr' || carg =~# 'all' ) if &l:errorformat == "" let &l:errorformat = "%WLaTeX\ Warning:\ Reference %m on\ input\ line\ %l%.%#,%WLaTeX\ %.%#Warning:\ Reference %m,%C %m on input line %l%.%#" else let &l:errorformat = &l:errorformat . ",%WLaTeX\ Warning:\ Reference %m on\ input\ line\ %l%.%#,%WLaTeX\ %.%#Warning:\ Reference %m,%C %m on input line %l%.%#" endif endif if carg =~ '\Cf' if &l:errorformat == "" let &l:errorformat = "%WLaTeX\ Font\ Warning:\ %m,%Z(Font) %m on input line %l%.%#" else let &l:errorformat = &l:errorformat . ",%WLaTeX\ Font\ Warning:\ %m,%Z(Font) %m on input line %l%.%#" endif endif if carg =~ '\Cfi' if &l:errorformat == "" let &l:errorformat = '%ILatex\ Font\ Info:\ %m on input line %l%.%#, \%ILatex\ Font\ Info:\ %m, \%Z(Font) %m\ on input line %l%.%#, \%C\ %m on input line %l%.%#' else let &l:errorformat = &l:errorformat . ',%ILatex\ Font\ Info:\ %m on input line %l%.%#, \%ILatex\ Font\ Info:\ %m, \%Z(Font) %m\ on input line %l%.%#, \%C\ %m on input line %l%.%#' endif endif if carg =~ '\CF' let efm = '%+P)%#%\\s%#(%f,File: %m,Package: %m,Document Class: %m,LaTeX2e %m' if &l:errorformat == "" let &l:errorformat = efm else let &l:errorformat = &l:errorformat . ',' . efm endif endif if carg =~ '\Cp' if &l:errorformat == "" let &l:errorformat = 'Package: %m' else let &l:errorformat = &l:errorformat . ',Package: %m' endif endif if &l:errorformat != "" " let pm = ( g:atp_show_all_lines == 1 ? '+' : '-' ) " let l:dont_ignore = 0 " if carg =~ '\CA\cll' " let l:dont_ignore = 1 " let pm = '+' " endif let l:dont_ignore= 1 let pm = '+' let &l:errorformat = &l:errorformat.", \%-C<%.%#>%.%#, \%-Zl.%l\ , \%-Zl.%l\ %m, \%-ZI've inserted%.%#, \%-ZThe control sequence%.%#, \%-ZYour command was ignored%.%#, \%-ZYou've closed more groups than you opened%.%#, \%-ZThe `$' that I just saw%.%#, \%-ZA number should have been here%.%#, \%-ZI'm ignoring this;%.%#, \%-ZI suspect you've forgotten%.%#, \%-GSee LaTeX%.%#, \%-GType\ \ H\ %m, \%-C\\s%#%m, \%-C%.%#-%.%#, \%-C%.%#[]%.%#, \%-C[]%.%#, \%-C%.%#%[{}\\]%.%#, \%-G ...%.%#, \%-G%.%#\ (C)\ %.%#, \%-G(see\ the\ transcript%.%#), \%-G\\s%#, \%-G%.%#" " These two appeared before l.%l (cannot be -Z): " \%-GSee LaTeX%.%#, " \%-GType\ \ H\ %m, let &l:errorformat = &l:errorformat.", \%".pm."O(%*[^()])%r, \%".pm."O%*[^()](%*[^()])%r, \%".pm."P(%f%r, \%".pm."P\ %\\=(%f%r, \%".pm."P%*[^()](%f%r, \%".pm."P[%\\d%[^()]%#(%f%r" let &l:errorformat = &l:errorformat.", \%".pm."Q)%r, \%".pm."Q%*[^()])%r, \%".pm."Q[%\\d%*[^()])%r" endif if a:cgetfile try cgetfile catch E40: endtry endif if t:atp_QuickFixOpen let winnr=winnr() " Quickfix is opened, jump to it and change the size copen exe "resize ".min([atplib#qflength(), g:atp_DebugModeQuickFixHeight]) exe winnr."wincmd w" endif if add != "0" echo "[ATP:] current error format: ".b:atp_ErrorFormat endif endfunction "}}} "{{{ ShowErrors " each argument can be a word in flags as for atplib#compiler#SetErrorFormat (except the " word 'whole') + two other flags: all (include all errors) and ALL (include " all errors and don't ignore any line - this overrides the variables " g:atp_ignore_unmatched and g:atp_show_all_lines. function! atplib#compiler#ShowErrors(...) " It is not atplib#compiler# because it is run from atplib#callback#CallBack() let errorfile = &l:errorfile " read the log file and merge warning lines " filereadable doesn't like shellescaped file names not fnameescaped. " The same for readfile() and writefile() built in functions. if !filereadable(errorfile) echohl WarningMsg echo "[ATP:] no error file: " . errorfile echohl None return endif let log=readfile(errorfile) let nr=1 for line in log if line =~ "LaTeX Warning:" && log[nr] !~ "^$" let newline=line . log[nr] let log[nr-1]=newline call remove(log,nr) endif let nr+=1 endfor call writefile(log, errorfile) " set errorformat let l:arg = ( a:0 >= 1 ? a:1 : b:atp_ErrorFormat ) if l:arg =~ 'o' OpenLog return elseif l:arg =~ 'b' echo b:atp_BibtexOutput return endif call atplib#compiler#SetErrorFormat(0, l:arg) let show_message = ( a:0 >= 2 ? a:2 : 1 ) " read the log file cgetfile " signs if g:atp_signs call atplib#callback#Signs(bufnr("%")) endif " final stuff if len(getqflist()) == 0 if show_message echo "[ATP:] no errors :)" endif return ":)" else cl return 1 endif endfunction "}}} if !exists("*ListErrorsFlags") function! atplib#compiler#ListErrorsFlags(A,L,P) return "all\nAll\nc\ne\nF\nf\nfi\no\nr\nw\nb" endfunction endif if !exists("*ListErrorsFlags_A") function! atplib#compiler#ListErrorsFlags_A(A,L,P) " This has no o flag. return "all\nAll\nc\ne\nF\nf\nfi\nr\nw\nb" endfunction endif "}}} " vim:fdm=marker:tw=85:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/complete.vim [[[1 3186 " Title: Vim library for ATP filetype plugin. " Author: Marcin Szamotulski " Email: mszamot [AT] gmail [DOT] com " Note: This file is a part of Automatic Tex Plugin for Vim. " URL: https://launchpad.net/automatictexplugin " Language: tex " Check If Closed: " This functions checks if an environment is closed/opened. " atplib#complete#CheckClosed {{{1 " check if last bpat is closed. " starting from the current line, limits the number of " lines to search. It returns 0 if the environment is not closed or the line " number where it is closed (an env is cannot be closed in 0 line) " ToDo: the two function should only check not commented lines! " " Method 0 makes mistakes if the pattern is \begin:\end, if " \begin{env_name}:\end{env_names} rather no (unless there are nested " environments in the same name. " Method 1 doesn't make mistakes and thus is preferable. " after testing I shall remove method 0 " Method 2 doesn't makes less mistakes than method 1 (which makes them :/) but it is only for " brackets, returns >0 if the bracket is closed 0 if it is not. try function! atplib#complete#CheckClosed(bpat, epat, line, col, limit,...) " NOTE: THIS IS MUCH FASTER !!! or SLOWER !!! ??? " " let l:pos_saved=getpos(".") " let l:cline=line(".") " if a:line != l:cline " let l:col=len(getline(a:line)) " keepjumps call setpos(".",[0,a:line,l:col,0]) " endif " let l:line=searchpair(a:bpat,'',a:epat,'nWr','',max([(a:line+a:limit),1])) " if a:line != l:cline " keepjumps call setpos(".",l:pos_saved) " endif " return l:line let time = reltime() let l:method = ( a:0 >= 1 ? a:1 : 0 ) let saved_pos = getpos(".") " let l:count_method = ( a:0 >= 2 ? a:2 : 1 ) let l:len = len(getbufline(bufname("%"),1,'$')) let l:nr = a:line let cline = line(".") if a:limit == "$" || a:limit == "-1" let l:limit=l:len-a:line else let l:limit=a:limit endif if g:atp_debugCheckClosed let g:saved_pos = getpos(".") let g:nr = a:line let g:bpat = a:bpat let g:limit = l:limit endif if g:atp_debugCheckClosed == 1 call atplib#Log("CheckClosed.log","", "init") endif if l:method==0 " {{{2 while l:nr <= a:line+l:limit let l:line=getline(l:nr) " Remove comments: let l:line=substitute(l:line, '\(\\\@> cline=".cline."> cpos_bpat_count=".cpos_bpat_count." cpos_epat_count=".cpos_epat_count) endif endif " Strip comments: let comment_match = match(l:line, '\%(\\\\\|\\\@= 0 if g:atp_debugCheckClosed call atplib#Log("CheckClosed.log", l:nr." l:bpat_count=".l:bpat_count." l:epat_count=".l:epat_count." ".l:line) if l:nr == saved_pos[1] call atplib#Log("CheckClosed.log", l:nr." l:closed_before_count=".l:closed_before_count) endif if l:nr >= saved_pos[1] call atplib#Log("CheckClosed.log", "cond (closed-opened)=".cond." value=".(l:epat_count - l:closed_before_count - l:bpat_count)) endif endif if l:nr >= saved_pos[1] && cond let g:time_CheckClosed=reltimestr(reltime(time)) if g:atp_debugCheckClosed let g:return = l:nr endif return l:nr endif let l:nr+=1 endwhile let g:time_CheckClosed=reltimestr(reltime(time)) return 0 elseif l:method==3 " {{{2 " This is a special method for brackets. " But it is too slow! " silent echomsg "***************" let saved_pos = getpos(".") call cursor(a:line, a:col) let c_pos = [a:line, a:col] let line = a:line " silent echomsg "a:line=".a:line." c_pos=".string(c_pos)." a:limit=".a:limit." cond=".string(a:line-c_pos[0] <= a:limit) while a:line-c_pos[0] <= a:limit let pos=searchpairpos(a:bpat, '', a:epat, 'b') " silent echomsg string(pos) if pos == [0, 0] " silent echomsg "C1" call cursor(saved_pos[1], saved_pos[2]) let g:time_CheckClosed=reltimestr(reltime(time)) return c_pos[0] endif if pos == c_pos " silent echomsg "C2" call cursor(saved_pos[1], saved_pos[2]) let g:time_CheckClosed=reltimestr(reltime(time)) return 0 endif if atplib#CompareCoordinates(c_pos, pos) " silent echomsg "C3" call cursor(saved_pos[1], saved_pos[2]) let g:time_CheckClosed=reltimestr(reltime(time)) return 0 endif let c_pos = copy(pos) endwhile " silent echomsg "C4" call cursor(saved_pos[1], saved_pos[2]) let g:time_CheckClosed=reltimestr(reltime(time)) return 1 endif endfunction catch /E127:/ endtry " }}}1 " {{{1 atplib#complete#CheckClosed_math " This functions makes a test if in line math is closed. This works well with " \(:\) and \[:\] but not yet with $:$ and $$:$$. " a:mathZone = texMathZoneV or texMathZoneW or texMathZoneX or texMathZoneY " The function return 1 if the mathZone is to be closed (i.e. it is not closed). function! atplib#complete#CheckClosed_math(mathZone) let time = reltime() let synstack = map(synstack(line("."), max([1, col(".")-1])), "synIDattr( v:val, 'name')") let check = 0 let patterns = { \ 'texMathZoneV' : [ '\\\@' " (some times one wants to have a command which opens an environment. " Todo: write a faster function using searchpairpos() which returns correct " values. function! atplib#complete#CheckOpened(bpat,epat,line,limit) " this is almost good: " let l:line=searchpair(a:bpat,'',a:epat,'bnWr','',max([(a:line-a:limit),1])) " return l:line let l:len=len(getbufline(bufname("%"),1,'$')) let l:nr=a:line if a:limit == "^" || a:limit == "-1" let l:limit=a:line-1 else let l:limit=a:limit endif while l:nr >= a:line-l:limit && l:nr >= 1 let l:line=getline(l:nr) if l:nr == a:line if substitute(strpart(l:line,0,getpos(".")[2]), a:bpat . '.\{-}' . a:epat,'','g') \ =~ a:bpat return l:nr endif else " if l:check_mode == 0 " if substitute(l:line, a:bpat . '.\{-}' . a:epat,'','g') " \ =~ a:bpat " " check if it is closed up to the place where we start. (There " " is no need to check after, it will be checked anyway " " b a serrate call in atplib#complete#TabCompletion. " if !atplib#complete#CheckClosed(a:bpat,a:epat,l:nr,0,a:limit,0) " " LAST CHANGE 1->0 above " " let b:cifo_return=2 . " " . l:nr " return l:nr " endif " endif " elseif l:check_mode == 1 if substitute(l:line, a:bpat . '.\{-}' . a:epat,'','g') \ =~ '\%(\\def\|\%(re\)\?newcommand\)\@= a:line " let b:cifo_return=2 . " " . l:nr return l:nr endif endif " endif endif let l:nr-=1 endwhile return 0 endfunction " }}}1 " {{{1 atplib#complete#CheckSyntaxGroups " This functions returns one if one of the environment given in the list " a:zones is present in they syntax stack at line a:1 and column a:0. " a:zones = a list of zones " a:1 = line nr (default: current cursor line) " a:2 = column nr (default: column before the current cursor position) " The function doesn't make any checks if the line and column supplied are " valid /synstack() function returns 0 rather than [] in such a case/. function! atplib#complete#CheckSyntaxGroups(zones,...) let line = a:0 >= 1 ? a:1 : line(".") let col = a:0 >= 2 ? a:2 : col(".")-1 let col = max([1, col]) let zones = copy(a:zones) let synstack_raw = synstack(line, col) if type(synstack_raw) != 3 unlet synstack_raw return 0 endif let synstack = map(synstack_raw, 'synIDattr(v:val, "name")') return max(map(zones, "count(synstack, v:val)")) endfunction " atplib#complete#CopyIndentation {{{1 function! atplib#complete#CopyIndentation(line) let raw_indent = split(a:line,'\s\zs') let indent = "" for char in raw_indent if char =~ '^\%(\s\|\t\)' let indent.=char else break endif endfor return indent endfunction "}}}1 " Close Environments And Brackets: " atplib#complete#CloseLastEnvironment {{{1 " a:1 = i (append before, so the cursor will be after - the dafult) " a (append after) " a:2 = math the pairs \(:\), $:$, \[:\] or $$:$$ (if filetype is " plaintex or b:atp_TexFlavor="plaintex") " environment " by the way, treating the math pairs together is very fast. " a:3 = environment name (if present and non zero sets a:2 = environment) " if one wants to find an environment name it must be 0 or "" or not " given at all. " a:4 = line and column number (in a vim list) where environment is opened " a:5 = return only (only return the closing code (implemented only for a:2="math") " ToDo: Ad a highlight to messages!!! AND MAKE IT NOT DISAPPEAR SOME HOW? " (redrawing doesn't help) CHECK lazyredraw. " Note: this function tries to not double the checks what to close if it is " given in the arguments, and find only the information that is not given " (possibly all the information as all arguments can be omitted). function! atplib#complete#CloseLastEnvironment(...) let time = reltime() let l:com = a:0 >= 1 ? a:1 : 'i' let l:close = a:0 >= 2 && a:2 != "" ? a:2 : 0 if a:0 >= 3 let l:env_name = ( a:3 == "" ? 0 : a:3 ) let l:close = ( a:3 != '' ? "environment" : l:close ) else let l:env_name = 0 endif let l:bpos_env = ( a:0 >= 4 ? a:4 : [0, 0] ) let return_only = ( a:0 >= 5 ? a:5 : 0 ) if g:atp_debugCloseLastEnvironment call atplib#Log('CloseLastEnvironment.log', '', 'init') let g:CLEargs = string(l:com) . " " . string(l:close) . " " . string(l:env_name) . " " . string(l:bpos_env) silent echo "args=".g:CLEargs let g:close = l:close let g:env_name = l:env_name let g:bpos_env = l:bpos_env call atplib#Log('CloseLastEnvironment.log', 'ARGS = '.g:CLEargs) endif " {{{2 find the begining line of environment to close (if we are closing " an environment) if l:env_name == 0 && ( l:close == "environment" || l:close == 0 ) && l:close != "math" let filter = 'strpart(getline(''.''), 0, col(''.'') - 1) =~ ''\\\@', 'bnW') " Check if one of \(:\), \[:\], $:$, $$:$$ is opened using syntax " file. If it is fined the starting position. let synstack = map(synstack(line("."),max([1, col(".")-1])), 'synIDattr(v:val, "name")') if g:atp_debugCloseLastEnvironment let g:synstackCLE = deepcopy(synstack) let g:openCLE = getline(".")[col(".")-1] . getline(".")[col(".")] call atplib#Log('CloseLastEnvironment.log', "g:openCLE=".string(g:openCLE)) call atplib#Log('CloseLastEnvironment.log', 'synstack='.string(synstack)) endif let bound_1 = getline(".")[col(".")-1] . getline(".")[col(".")] =~ '^\\\%((\|)\)$' let math_1 = (index(synstack, 'texMathZoneV') != -1 && !bound_1 ? 1 : 0 ) if math_1 if l:bpos_env == [0, 0] let bpos_math_1 = searchpos('\%(\%(\\\)\@= 1 let l:close = 'math' elseif l:env_name let l:close = 'environment' else if g:atp_debugCloseLastEnvironment call atplib#Log('CloseLastEnvironment.log', "return: l:env_name=".string(l:env_name)." && math_1+...+math_4=".string(math_1+math_2+math_3+math_4)) endif let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '' endif endif if g:atp_debugCloseLastEnvironment let g:close = l:close call atplib#Log('CloseLastEnvironment.log', 'l:close='.l:close) call atplib#Log('CloseLastEnvironment.log', 'l:env_name='.l:env_name) endif let l:env=l:env_name "}}}2 if l:close == "0" || l:close == 'math' && !exists("begin_line") if g:atp_debugCloseLastEnvironment call atplib#Log('CloseLastEnvironment.log', 'there was nothing to close') endif let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '' endif if ( &filetype != "plaintex" && b:atp_TexFlavor != "plaintex" && exists("math_4") && math_4 ) echohl ErrorMsg echomsg "[ATP:] $$:$$ in LaTeX are deprecated (this breaks some LaTeX packages)" echomsg " You can set b:atp_TexFlavor = 'plaintex', and ATP will ignore this. " echohl None if g:atp_debugCloseLastEnvironment call atplib#Log('CloseLastEnvironment.log', "return A") endif let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '' endif if l:env_name =~ '^\s*document\s*$' if g:atp_debugCloseLastEnvironment call atplib#Log('CloseLastEnvironment.log', "return B") endif let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '' endif let l:cline = getline(".") let l:pos = getpos(".") if l:close == "math" let l:line = getline(l:begin_line) elseif l:close == "environment" let l:line = getline(l:bpos_env[0]) endif if g:atp_debugCloseLastEnvironment let g:line = ( exists("l:line") ? l:line : 0 ) call atplib#Log('CloseLastEnvironment.log', "g:line=".g:line) endif " Copy the indentation of what we are closing. let l:eindent=atplib#complete#CopyIndentation(l:line) "{{{2 close environment if l:close == 'environment' " Info message redraw " silent echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] " Rules: " env & \[ \]: close in the same line " unless it starts in a serrate line, " \( \): close in the same line. "{{{3 close environment in the same line if l:line != "" && l:line !~ '^\s*\%(\$\|\$\$\|[^\\]\\%(\|\\\@= 0 let [ l:line_nr, l:col_nr ]=searchpos('\%(%.*\)\@ 0 let l:max=max(l:cenv_lines) let l:pos[1]=l:max+1 " find the first closed item below the last closed " pair (below l:pos[1]). (I assume every env is in " a seprate line! let l:end=atplib#complete#CheckClosed('\%(%.*\)\@= l:end call append(l:end-1, l:eindent . l:str) echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] . " at line " . l:end call setpos(".",[0,l:end,len(l:eindent.l:str)+1,0]) endif else if line(".") >= l:max call append(l:pos_saved[1], l:eindent . l:str) keepjumps call setpos(".",l:pos_saved) echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] . " at line " . line(".")+1 call setpos(".",[0,l:pos_saved[1]+1,len(l:eindent.l:str)+1,0]) elseif line(".") < l:max call append(l:max, l:eindent . l:str) echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] . " at line " . l:max+1 call setpos(".",[0,l:max+1,len(l:eindent.l:str)+1,0]) endif endif else let l:pos[1]=l:line_nr let l:pos[2]=1 " put cursor at the end of the line where not closed \begin was " found keepjumps call setpos(".",[0,l:line_nr,len(getline(l:line_nr)),0]) let l:cline = getline(l:pos_saved[1]) if g:atp_debugCloseLastEnvironment let g:cline = l:cline let g:pos_saved = copy(l:pos_saved) let g:line = l:pos_saved[1] endif let l:iline=searchpair('\\begin{','','\\end{','nW') if l:iline > l:line_nr && l:iline <= l:pos_saved[1] call append(l:iline-1, l:eindent . l:str) echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] . " at line " . l:iline let l:pos_saved[2]+=len(l:str) call setpos(".",[0,l:iline,len(l:eindent.l:str)+1,0]) else if l:cline =~ '\\begin{\%('.l:uenv.'\)\@!' call append(l:pos_saved[1]-1, l:eindent . l:str) echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] . " at line " . l:pos_saved[1] let l:pos_saved[2]+=len(l:str) call setpos(".",[0,l:pos_saved[1],len(l:eindent.l:str)+1,0]) elseif l:cline =~ '^\s*$' call append(l:pos_saved[1]-1, l:eindent . l:str) echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] . " at line " . l:pos_saved[1] let l:pos_saved[2]+=len(l:str) call setpos(".",[0,l:pos_saved[1]+1,len(l:eindent.l:str)+1,0]) else call append(l:pos_saved[1], l:eindent . l:str) echomsg "[ATP:] closing " . l:env_name . " from line " . l:bpos_env[0] . " at line " . l:pos_saved[1]+1 " Do not move corsor if: '\begin{env_name}' if l:cline !~ '\\begin\s*{\s*\%('.l:uenv.'\)\s*}' let l:pos_saved[2]+=len(l:str) call setpos(".",[0,l:pos_saved[1]+1,len(l:eindent.l:str)+1,0]) else call setpos(".", l:pos_saved) endif endif endif if g:atp_debugCloseLastEnvironment silent echo "return E" redir END endif let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '' endif else if g:atp_debugCloseLastEnvironment silent echo "return F" redir END endif let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '' endif unlet! l:env_names unlet! l:env_dict unlet! l:cenv_names unlet! l:pos unlet! l:pos_saved " if getline('.') =~ '^\s*$' " exec "normal dd" endif "}}}3 "{{{2 close math: texMathZoneV, texMathZoneW, texMathZoneX, texMathZoneY else "{{{3 Close math in the current line if !return_only if l:begin_line != line(".") echomsg "[ATP:] closing math from line " . l:begin_line endif endif if \ math_mode == 'texMathZoneV' && ( l:line !~ '^\s*\\(\s*$' || line(".") == l:begin_line ) || \ math_mode == 'texMathZoneW' && ( l:line !~ '^\s*\\\[\s*$' ) || \ math_mode == 'texMathZoneX' && ( l:line !~ '^\s*\$\s*$' || line(".") == l:begin_line ) || \ math_mode == 'texMathZoneY' && ( l:line !~ '^\s*\$\{2,2}\s*$' ) if g:atp_debugCloseLastEnvironment call atplib#Log('CloseLastEnvironment.log', 'inline math') endif if math_mode == "texMathZoneW" if !return_only if l:com == 'a' if getline(l:begin_line) =~ '^\s*\\\[\s*$' call append(line("."),atplib#complete#CopyIndentation(getline(l:begin_line)).'\]') else call setline(line("."), strpart(l:cline,0,getpos(".")[2]) . '\]'. strpart(l:cline,getpos(".")[2])) endif else if getline(l:begin_line) =~ '^\s*\\\[\s*$' call append(line("."),atplib#complete#CopyIndentation(getline(l:begin_line)).'\]') else call setline(line("."), strpart(l:cline,0,getpos(".")[2]-1) . '\]'. strpart(l:cline,getpos(".")[2]-1)) " TODO: This could be optional: (but the option rather " should be an argument of this function rather than " here! endif let l:pos=getpos(".") let l:pos[2]+=2 keepjumps call setpos(("."),l:pos) let b:cle_return="texMathZoneW" endif else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '\]' endif elseif math_mode == "texMathZoneV" if !return_only if l:com == 'a' call setline(line("."), strpart(l:cline,0,getpos(".")[2]) . '\)'. strpart(l:cline,getpos(".")[2])) else call setline(line("."), strpart(l:cline,0,getpos(".")[2]-1) . '\)'. strpart(l:cline,getpos(".")[2]-1)) call cursor(line("."),col(".")+2) let b:cle_return="V" endif else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '\)' endif elseif math_mode == "texMathZoneX" if !return_only call setline(line("."), strpart(l:cline,0,getpos(".")[2]-1) . '$'. strpart(l:cline,getpos(".")[2]-1)) call cursor(line("."),col(".")+1) else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return "$" endif elseif math_mode == "texMathZoneY" if !return_only call setline(line("."), strpart(l:cline,0,getpos(".")[2]-1) . '$$'. strpart(l:cline,getpos(".")[2]-1)) call cursor(line("."),col(".")+2) else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '$$' endif endif " }}}3 "{{{3 Close math in a new line, preserv the indentation. else let l:eindent=atplib#complete#CopyIndentation(l:line) if math_mode == 'texMathZoneW' if !return_only let l:iline=line(".") " if the current line is empty append before it. if getline(".") =~ '^\s*$' && l:iline > 1 let l:iline-=1 endif call append(l:iline, l:eindent . '\]') echomsg "[ATP:] \[ closed in line " . l:iline else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '\]' endif " let b:cle_return=2 . " dispalyed math " . l:iline . " indent " . len(l:eindent) " DEBUG elseif math_mode == 'texMathZoneV' if !return_only let l:iline=line(".") " if the current line is empty append before it. if getline(".") =~ '^\s*$' && l:iline > 1 let l:iline-=1 endif call append(l:iline, l:eindent . '\)') echomsg "[ATP:] \( closed in line " . l:iline else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '\)' endif " let b:cle_return=2 . " inline math " . l:iline . " indent " .len(l:eindent) " DEBUG elseif math_mode == 'texMathZoneX' if !return_only let l:iline=line(".") " if the current line is empty append before it. if getline(".") =~ '^\s*$' && l:iline > 1 let l:iline-=1 endif let sindent=atplib#complete#CopyIndentation(getline(search('\$', 'bnW'))) call append(l:iline, sindent . '$') echomsg "[ATP:] $ closed in line " . l:iline else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '$' endif elseif math_mode == 'texMathZoneY' if !return_only let l:iline=line(".") " if the current line is empty append before it. if getline(".") =~ '^\s*$' && l:iline > 1 let l:iline-=1 endif let sindent=atplib#complete#CopyIndentation(getline(search('\$\$', 'bnW'))) call append(l:iline, sindent . '$$') echomsg "[ATP:] $ closed in line " . l:iline else let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '$$' endif endif endif "}}3 endif if g:atp_debugCloseLastEnvironment silent echo "return G" redir END endif "}}}2 let g:time_CloseLastEnvironment = reltimestr(reltime(time)) return '' endfunction " imap :call atplib#CloseLastEnvironment() " }}}1 " {{{1 atplib#complete#CheckBracket " The first function only tests if there is a bracket to be closed. " Returns a list [ l:open_line, l:open_col, l:open_bracket ] " l:open_col != 0 if any of brackets (in values(g:atp_bracket_dict) ) is " opened and not closed. l:open_bracket is the most recent such bracket " ([ l:open_line, l:open_col ] are its coordinates). " " a:bracket_dict is a dictionary of brackets to use: " { open_bracket : close_bracket } " " Note: the most time consuming part is searchpairpos() function, especially " for the {:} pair. " to make it faster I could first count the number of { and } and compare " them. try function! atplib#complete#CheckBracket(bracket_dict) let time = reltime() let limit_line = max([1,(line(".")-g:atp_completion_limits[4])]) let pos = getpos(".") call search('\S', 'bW') let begin_line = max([search('\%(\\par\>\|^\s*$\)', 'bnW'), limit_line]) let end_line = min([search('\%(\\par\>\|^\s*$\)', 'nW'), min([line('$'), line(".")+g:atp_completion_limits[4]])]) call cursor(pos[1:2]) let length = end_line-begin_line if g:atp_debugCheckBracket let g:begin_line = begin_line let g:end_line = end_line let g:limit_line = limit_line let g:length = length endif let pos_saved = getpos(".") " Bracket sizes: let ket_pattern = '\%(' . join(values(filter(copy(g:atp_sizes_of_brackets), "v:val != '\\'")), '\|') . '\)' " But maybe we shouldn't check if the bracket is closed sometimes one can " want to close closed bracket and delete the old one. let check_list = [] if g:atp_debugCheckBracket call atplib#Log("CheckBracket.log","", "init") let g:check_list = check_list endif " change the position! and then: " check the flag 'r' in searchpair!!! "Note: this can be much faster to first to check if the line is matching " \({\|...\)[^}...]*, etc., but this would not " break which bracket to close. let i=0 let bracket_list= keys(a:bracket_dict) for ket in bracket_list let pos = deepcopy(pos_saved) let time_{i} = reltime() if ket != '{' && ket != '(' && ket != '[' if search('\\\@= 2 echomsg escape(ket,'\[]') . " pair_".i."=".string(pair_{i}) . " limit_line=" . limit_line endif if g:atp_debugCheckBracket >= 1 call atplib#Log("CheckBracket.log", ket." time_A_".i."=".string(g:time_A_{i})) call atplib#Log("CheckBracket.log", ket." pair_".i."=".string(pair_{i})) endif let pos[1] = pair_{i}[0] let pos[2] = pair_{i}[1] let no_backslash = ( i == 0 || i == 2 ? '\\\@= 1 call atplib#Log("CheckBracket.log", ket." check_".i."=".string(check_{i})) let g:check_{i} = check_{i} let g:arg_{i}=[escape(ket,'\[]'), '\%('.escape(a:bracket_dict[ket],'\[]').'\|\\\.\)', begin_line, 1, 2*g:atp_completion_limits[4],2] endif " check_dot_{i} is 1 if the bracket is closed with a dot (\right.) . " let check_dot_{i} = atplib#complete#CheckClosed('\\\@= 1 call atplib#Log("CheckBracket.log", ket." check_dot_".i."=".string(check_{i})) endif if g:atp_debugCheckBracket >= 2 echomsg escape(ket,'\[]') . " check_".i."=".string(check_{i}) . " check_dot_".i."=".string(check_dot_{i}) endif let check_{i} = min([check_{i}, check_dot_{i}]) call add(check_list, [ pair_{i}[0], ((check_{i})*pair_{i}[1]), i ] ) keepjumps call setpos(".",pos_saved) let g:time_B_{i} = reltimestr(reltime(time_{i})) call atplib#Log("CheckBracket.log", ket." time_B_".i."=".string(g:time_B_{i})) let i+=1 endfor " let g:time_CheckBracket_A=reltimestr(reltime(time)) keepjumps call setpos(".", pos_saved) " Find opening line and column numbers call sort(check_list, "atplib#CompareCoordinates") let g:check_list = check_list let [ open_line, open_col, open_bracket_nr ] = check_list[0] let [ s:open_line, s:open_col, s:opening_bracket ] = [ open_line, open_col, bracket_list[open_bracket_nr] ] if g:atp_debugCheckBracket let [ g:open_lineCB, g:open_colCB, g:opening_bracketCB ] = [ open_line, open_col, bracket_list[open_bracket_nr] ] call atplib#Log("CheckBracket.log", "return:") call atplib#Log("CheckBracket.log", "open_line=".open_line) call atplib#Log("CheckBracket.log", "open_col=".open_col) call atplib#Log("CheckBracket.log", "opening_bracketCB=".g:opening_bracketCB) endif let g:time_CheckBracket=reltimestr(reltime(time)) " let g:time=g:time+str2float(substitute(g:time_CheckBracket, '\.', ',', '')) return [ open_line, open_col, bracket_list[open_bracket_nr] ] endfunction catch /E127:/ endtry " }}}1 " {{{1 atplib#complete#CloseLastBracket " " The second function closes the bracket if it was not closed. " (as returned by atplib#complete#CheckBracket or [ s:open_line, s:open_col, s:opening_bracket ]) " It is not used to close \(:\) and \[:\] as atplib#complete#CloseLastEnvironment has a better " way of doing that (preserving indentation) " a:bracket_dict is a dictionary of brackets to use: " { open_bracket : close_bracket } " a:1 = 1 just return the bracket " a:2 = 0 (default), 1 when used in atplib#complete#TabCompletion " then s:open_line, s:open_col and s:opening_bracket are " used to avoid running twice atplib#complete#CheckBracket(): " once in atplib#complete#TabCompletion and secondly in CloseLastBracket " function. function! atplib#complete#CloseLastBracket(bracket_dict, ...) let only_return = ( a:0 >= 1 ? a:1 : 0 ) let tab_completion = ( a:0 >= 2 ? a:2 : 0 ) " {{{2 preambule let pattern = "" let size_patterns = [] for size in keys(g:atp_sizes_of_brackets) call add(size_patterns,escape(size,'\')) endfor let pattern_b = '\C\%('.join(size_patterns,'\|').'\)' let pattern_o = '\%('.join(map(keys(a:bracket_dict),'escape(v:val,"\\[]")'),'\|').'\)' if g:atp_debugCloseLastBracket call atplib#Log("CloseLastBracket.log","","init") let g:pattern_b = pattern_b let g:pattern_o = pattern_o call atplib#Log("CloseLastBracket.log", "pattern_b=".pattern_b) call atplib#Log("CloseLastBracket.log", "pattern_o=".pattern_o) endif let limit_line = max([1,(line(".")-g:atp_completion_limits[1])]) let pos_saved = getpos(".") " But maybe we shouldn't check if the bracket is closed sometimes one can " want to close closed bracket and delete the old one. call cursor(line("."), col(".")-1) let [ open_line, open_col, opening_bracket ] = ( tab_completion ? \ deepcopy([ s:open_line, s:open_col, s:opening_bracket ]) : atplib#complete#CheckBracket(a:bracket_dict) ) call cursor(line("."), pos_saved[2]) " Check and Close Environment: for env_name in g:atp_closebracket_checkenv " To Do: this should check for the most recent opened environment let limit_line = exists("open_line") ? open_line : search('\\\@= 3 " let saved_pos=getpos(".") " let pos = a:3 " call setpos(".", a:3) " else let pos = getpos(".") " let saved_pos = getpos(".") " endif " let g:pos = copy(pos) " let g:apos = getpos(".") " call cursor(pos[1], pos[2]-1) " let g:bpos = copy(getpos(".")) let begParen = ( a:0 >=2 && a:2 != [] ? a:2 : atplib#complete#CheckBracket(a:bracket_dict) ) let g:begParen = copy(begParen) if begParen[2] == '\begin' && begParen[1] && !atplib#complete#CheckSyntaxGroups(['texMathZoneX', 'texMathZoneY', 'texMathZoneV', 'texMathZoneW']) call atplib#complete#CloseLastEnvironment(a:append, 'environment', matchstr(getline(begParen[0]), '.*\\begin{\s*\zs[^}]*\ze\s*}'), [begParen[0], begParen[1]-6]) return '' endif call cursor(pos[1], pos[2]) if begParen[1] != 0 || atplib#complete#CheckSyntaxGroups(['texMathZoneX', 'texMathZoneY', 'texMathZoneV', 'texMathZoneW']) || ( a:0 >= 1 && a:1 ) let g:cpos = getpos(".") if atplib#complete#CheckSyntaxGroups(['texMathZoneV']) let pattern = '\\\@ or (if g:atp_no_tab_map=1) " expert_mode = 0 (off) gives more matches but in some cases better ones, the " string has to match somewhare and is case in " sensitive, for example: " \arrow will show all the arrows definded in tex, " in expert mode there would be no match (as there is no " command in tex which begins with \arrow). " or (if g:atp_no_tab_map=1) " " Completion Modes: (this is not a complete list any more, see the " documentation of ATP) " documentclass (\documentclass) " labels (\ref,\eqref) " packages (\usepackage) " commands " environments (\begin,\(:\),\[:\]) " brackets ((:),[:],{:}) preserves the size operators! " Always: check first brackets then environments. Bracket " funnction can call function which closes environemnts but not " vice versa. " bibitems (\cite\|\citep\|citet) " bibfiles (\bibliography) " bibstyle (\bibliographystyle) " end (close \begin{env} with \end{env}) " font encoding " font family " font series " font shape " "ToDo: the completion should be only done if the completed text is different "from what it is. But it might be as it is, there are reasons to keep this. " try " Main tab completion function function! atplib#complete#TabCompletion(expert_mode,...) if g:atp_debugTabCompletion call atplib#Log("TabCompletion.log", "", "init") endif let time=reltime() let atp_MainFile = atplib#FullPath(b:atp_MainFile) " {{{2 Match the completed word let normal_mode=0 if a:0 >= 1 let normal_mode=a:1 endif " this specifies the default argument for atplib#complete#CloseLastEnvironment() " in some cases it is better to append after than before. let append='i' " Define string parts used in various completitons let pos = getpos(".") let pos_saved = deepcopy(pos) let line = join(getbufline("%",pos[1])) let nchar = strpart(line,pos[2]-1,1) " let rest = strpart(line,pos[2]-1) let l = strpart(line,0,pos[2]-1) let n = strridx(l,'{') let m = strridx(l,',') let o = strridx(l,'\') let s = strridx(l,' ') let p = strridx(l,'[') let r = strridx(l,'=') let c = match(l, '\\cite\>\(.*\\cite\>\)\@!') let a = len(l) - stridx(join(reverse(split(l, '\zs')), ''), "=") let nr=max([n,m,o,s,p]) let color_nr=max([nr, r]) " this matches for =... let abegin = strpart(l, a-1) " this matches for \... let begin = strpart(l,nr+1) let color_begin = strpart(l,color_nr+1) let cbegin = strpart(l,nr) " and this for '\<\w*$' (beginning of last started word) -- used in " tikzpicture completion method let tbegin = matchstr(l,'\zs\<\w*$') " start with last '\' let obegin = strpart(l,o) " start with last = let ebegin = strpart(l,max([r,m,n])+1) " what we are trying to complete: usepackage, environment. let pline = strpart(l, 0, nr) " \cite[Theorem~1]{Abcd -> \cite[Theorem~] let ppline = strpart(l, c) " \cite[Theorem~1]{Abcd -> \cite[Theorem~1]{ let limit_line=max([1,(pos[1]-g:atp_completion_limits[1])]) if g:atp_debugTabCompletion let g:nchar = nchar call atplib#Log("TabCompletion.log", "nchar=".nchar) let g:l = l call atplib#Log("TabCompletion.log", "l=".l) let g:n = n call atplib#Log("TabCompletion.log", "n=".n) let g:o = o call atplib#Log("TabCompletion.log", "o=".o) let g:s = s call atplib#Log("TabCompletion.log", "s=".s) let g:p = p call atplib#Log("TabCompletion.log", "p=".p) let g:a = a call atplib#Log("TabCompletion.log", "a=".a) let g:nr = nr call atplib#Log("TabCompletion.log", "nr=".nr) let g:line = line call atplib#Log("TabCompletion.log", "line=".line) let g:abegin = abegin call atplib#Log("TabCompletion.log", "abegin=".abegin) let g:tbegin = tbegin call atplib#Log("TabCompletion.log", "tbegin=".tbegin) let g:cbegin = cbegin call atplib#Log("TabCompletion.log", "cbegin=".cbegin) let g:obegin = obegin call atplib#Log("TabCompletion.log", "obegin=".obegin) let g:begin = begin call atplib#Log("TabCompletion.log", "begin=".begin) let g:ebegin = ebegin call atplib#Log("TabCompletion.log", "ebegin=".ebegin) let g:pline = pline call atplib#Log("TabCompletion.log", "pline=".pline) let g:ppline = ppline call atplib#Log("TabCompletion.log", "ppline=".ppline) let g:color_begin = color_begin call atplib#Log("TabCompletion.log", "color_begin=".color_begin) let g:limit_line= limit_line call atplib#Log("TabCompletion.log", "limit_line=".limit_line) endif " {{{2 SET COMPLETION METHOD " {{{3 --------- command if o > n && o > s && \ pline !~ '\%(input\s*{[^}]*$\|include\%(only\)\=\s*{[^}]*$\|[^\\]\\\\[^\\]$\)' && \ pline !~ '\\\@.*\|\\\%(re\)\?newcommand\>.*\|%.*\)\@ search('[^%]*\\end{tikzpicture}','bnW') || \ !atplib#CompareCoordinates(searchpos('[^%]*\zs\\tikz{','bnw'),searchpos('}','bnw')) ) "{{{4 ----------- tikzpicture colors if begin =~ '^color=' " This is for tikz picture color completion. let completion_method='tikzpicture colors' let b:comp_method='tikzpicture colors' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{4 ----------- tikzpicture keywords elseif l =~ '\%(\s\|\[\|{\|}\|,\|\.\|=\|:\)' . tbegin . '$' && \ !a:expert_mode let b:comp_method='tikzpicture keywords' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) let completion_method="tikzpicture keywords" "{{{4 ----------- brackets else let begParen = atplib#complete#CheckBracket(g:atp_bracket_dict) let g:begParen = begParen if begParen[2] != '\begin' && ( begParen[1] != 0 || atplib#complete#CheckSyntaxGroups(['texMathZoneX', 'texMathZoneY']) && \ (!normal_mode && index(g:atp_completion_active_modes, 'brackets') != -1 ) || \ (normal_mode && index(g:atp_completion_active_modes_normal_mode, 'brackets') != -1 ) ) let b:comp_method='brackets tikzpicture' let completion_method = 'brackets' let bracket=atplib#complete#GetBracket(append, g:atp_bracket_dict, 0, begParen) let g:time_TabCompletion=reltimestr(reltime(time)) let move = ( !a:expert_mode ? join(map(range(len(bracket)), '"\"'), '') : '' ) return bracket.move "{{{4 ----------- close environments elseif (!normal_mode && index(g:atp_completion_active_modes, 'close environments') != '-1' ) || \ (normal_mode && index(g:atp_completion_active_modes_normal_mode, 'close environments') != '-1' ) let completion_method='close_env' " DEBUG: let b:comp_method='close_env tikzpicture' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) else return '' endif endif "{{{3 --------- package options values elseif l =~ '\\usepackage\[[^\]]*=\%([^\],]*\|{\([^}]\+,\)\?[^}]*\)$' && \ !( l =~ '\\usepackage\[[^\]]*=\%(.*\]\|{.*}\),$' ) && \ !normal_mode && \ index(g:atp_completion_active_modes, 'package options values') != -1 let completion_method='package options values' let b:comp_method=completion_method "{{{3 --------- package options elseif l =~ '\\usepackage\[[^\]]*$' && !normal_mode && \ index(g:atp_completion_active_modes, 'package options') != -1 let completion_method='package options' let b:comp_method=completion_method "{{{3 --------- package elseif pline =~ '\\usepackage\%([.*]\)\?\s*' && !normal_mode && \ index(g:atp_completion_active_modes, 'package names') != -1 let completion_method='package' " DEBUG: let b:comp_method='package' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- tikz libraries elseif pline =~ '\\usetikzlibrary\%([.*]\)\?\s*' && !normal_mode && \ index(g:atp_completion_active_modes, 'tikz libraries') != -1 let completion_method='tikz libraries' " DEBUG: let b:comp_method='tikz libraries' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- inputfiles elseif (l =~ '\\input\%([^{}]*\|\s*{[^}]*\)$'|| \ l =~ '\\include\s*{[^}]*$' || \ l =~ '\\includeonly\s*{[^}]*$') && !normal_mode && \ index(g:atp_completion_active_modes, 'input files') != -1 if begin =~ 'input' let begin=substitute(begin,'.*\%(input\|include\%(only\)\?\)\s\?','','') endif let completion_method='inputfiles' " DEBUG: let b:comp_method='inputfiles' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- includegraphics elseif (l =~ '\\includegraphics\s*\(\[[^\]]*\]\s*\)\?{[^}]*$') && \ index(g:atp_completion_active_modes, 'includegraphics') != -1 let completion_method='includegraphics' " DEBUG: let b:comp_method='includegraphics' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- bibfiles elseif pline =~ '\\\%(bibliography\%(style\)\@!\|addbibresource\|addglobalbib\)' && !normal_mode && \ index(g:atp_completion_active_modes, 'bibfiles') != -1 let completion_method='bibfiles' " DEBUG: let b:comp_method='bibfiles' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- bibstyles elseif pline =~ '\\bibliographystyle' && !normal_mode && \ index(g:atp_completion_active_modes, 'bibstyles') != -1 let completion_method='bibstyles' let b:comp_method='bibstyles' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- todo & missingfigure options elseif obegin =~ '\\todo\[[^\]]*$' && \ ( index(g:atp_completion_active_modes, 'todonotes') != -1 ) let completion_method='todo options' let b:comp_method='todo options' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) elseif obegin =~ '\\missingfigure\[[^\]]*$' && \ ( index(g:atp_completion_active_modes, 'todonotes') != -1 ) let completion_method='missingfigure options' let b:comp_method='missingfigure options' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- documentclass options elseif l =~ '\\documentclass\s*\[[^\]]*$' && !normal_mode && \ index(g:atp_completion_active_modes, 'documentclass options') != -1 let completion_method='documentclass options' let b:comp_method=completion_method call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- documentclass elseif pline =~ '\\documentclass\>' && !normal_mode && \ index(g:atp_completion_active_modes, 'documentclass') != -1 let completion_method='documentclass' let b:comp_method='documentclass' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- font family elseif l =~ '\%(\\renewcommand\s*{\s*\\\%(rm\|sf\|bf\|tt\|md\|it\|sl\|sc\|up\)default\s*}\s*{\|\\usefont{[^}]*}{\|\\DeclareFixedFont{[^}]*}{[^}]*}{\|\\fontfamily{\)[^}]*$' && !normal_mode && \ index(g:atp_completion_active_modes, 'font family') != -1 let completion_method='font family' let b:comp_method='font family' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- font series elseif l =~ '\%(\\usefont{[^}]*}{[^}]*}{\|\\DeclareFixedFont{[^}]*}{[^}]*}{[^}]*}{\|\\fontseries{\)[^}]*$' && \ !normal_mode && \ index(g:atp_completion_active_modes, 'font series') != -1 let completion_method='font series' let b:comp_method='font series' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- font shape elseif l =~ '\%(\\usefont{[^}]*}{[^}]*}{[^}]*}{\|\\DeclareFixedFont{[^}]*}{[^}]*}{[^}]*}{[^}]*}{\|\\fontshape{\)[^}]*$' \ && !normal_mode && \ index(g:atp_completion_active_modes, 'font shape') != -1 let completion_method='font shape' let b:comp_method='font shape' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- font encoding elseif l =~ '\%(\\usefont{\|\\DeclareFixedFont{[^}]*}{\|\\fontencoding{\)[^}]*$' && !normal_mode && \ index(g:atp_completion_active_modes, 'font encoding') != -1 let completion_method='font encoding' let b:comp_method='font encoding' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- command values " this is at the end because there are many command completions done " before - they would not work if this would be on the top. elseif (l =~ '\%(\\\w\+\({\%([^}]\|{[^}]*}\)*\)\?{\%([^}]\|{[^}]*}\)*$\|\\renewcommand{[^}]*}{[^}]*$\)' && !normal_mode) && \ index(g:atp_completion_active_modes, 'environment names') != -1 let completion_method="command values" " DEBUG: let b:comp_method=completion_method call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{3 --------- brackets, algorithmic, abbreviations, close environments else let begParen = atplib#complete#CheckBracket(g:atp_bracket_dict) "{{{4 --------- abbreviations if l =~ '=[a-zA-Z]\+\*\=$' && \ index(g:atp_completion_active_modes, 'abbreviations') != -1 && \ !atplib#IsInMath() let completion_method='abbreviations' let b:comp_method='abbreviations' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{4 --------- brackets elseif begParen[2] != '\begin' && ( begParen[1] != 0 || atplib#complete#CheckSyntaxGroups(['texMathZoneX', 'texMathZoneY']) && \ (!normal_mode && index(g:atp_completion_active_modes, 'brackets') != -1 ) || \ (normal_mode && index(g:atp_completion_active_modes_normal_mode, 'brackets') != -1 ) ) let completion_method = 'brackets' let b:comp_method='brackets' let bracket=atplib#complete#GetBracket(append, g:atp_bracket_dict, 0, begParen) let g:time_TabCompletion=reltimestr(reltime(time)) let move = ( !a:expert_mode ? join(map(range(len(bracket)), '"\"'), '') : '' ) return bracket.move "{{{4 --------- close environments elseif (!normal_mode && index(g:atp_completion_active_modes, 'close environments') != '-1' ) || \ (normal_mode && index(g:atp_completion_active_modes_normal_mode, 'close environments') != '-1' ) let completion_method='close_env X' " DEBUG: let b:comp_method='close_env' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) "{{{4 --------- algorithmic elseif atplib#complete#CheckBracket(g:atp_algorithmic_dict)[0] != 0 && \ atplib#complete#CheckSyntaxGroups(['texMathZoneALG']) && \ ((!normal_mode && index(g:atp_completion_active_modes, 'algorithmic' ) != -1 ) || \ (normal_mode && index(g:atp_completion_active_modes_normal_mode, 'algorithmic') != -1 )) let b:comp_method='algorithmic' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) call atplib#complete#CloseLastBracket(g:atp_algorithmic_dict, 0, 1) let g:time_TabCompletion=reltimestr(reltime(time)) return '' "}}}4 else let g:time_TabCompletion=reltimestr(reltime(time)) return '' endif "}}}3 endif let b:completion_method = ( exists("completion_method") ? completion_method : 'completion_method does not exists' ) "}}}2 " {{{2 close environments if completion_method=='close_env' " let g:time_A=reltimestr(reltime(time)) " Close one line math if atplib#complete#CheckClosed_math('texMathZoneV') || \ atplib#complete#CheckClosed_math('texMathZoneW') || \ atplib#complete#CheckClosed_math('texMathZoneX') || \ b:atp_TexFlavor == 'plaintex' && atplib#complete#CheckClosed_math('texMathZoneY') let b:tc_return = "close_env math" call atplib#complete#CloseLastEnvironment(append, 'math') " Close environments else let b:tc_return = "close_env environment" let stopline_forward = line(".") + g:atp_completion_limits[2] let stopline_backward = max([ 1, line(".") - g:atp_completion_limits[2]]) let line_nr=line(".") let pos_saved=getpos(".") while line_nr >= stopline_backward let [ line_nr, col_nr ] = searchpairpos('\\begin\s*{', '', '\\end\s*{', 'bW', 'strpart(getline("."), 0, col(".")-1) =~ "\\\\\\@= stopline_backward let env_name = matchstr(strpart(getline(line_nr), col_nr-1), '\\begin\s*{\zs[^}]*\ze}') if env_name =~# '^\s*document\s*$' break endif let line_forward = searchpair('\\begin\s*{'.env_name.'}', '', '\\end\s*{'.env_name.'}', \ 'nW', '', stopline_forward) if line_forward == 0 break endif else let line_nr = 0 break endif endwhile call cursor(pos_saved[1], pos_saved[2]) if line_nr " the env_name variable might have wrong value as it is " looking using '\\begin' and '\\end' this might be not enough, " however the function atplib#CloseLastEnv works perfectly and this " should be save: let g:time_TabCompletion=reltimestr(reltime(time)) if env_name !~# '^\s*document\s*$' call atplib#complete#CloseLastEnvironment(append, 'environment', '', [line_nr, 0]) return "" else return "" endif endif endif let g:time_TabCompletion=reltimestr(reltime(time)) return "" endif " {{{2 SET COMPLETION LIST " generate the completion names " {{{3 ------------ ENVIRONMENT NAMES if completion_method == 'environment_names' let end=strpart(line,pos[2]-1) keepjumps call setpos(".",[0,1,1,0]) let stop_line=search('\\begin\s*{document}','cnW') keepjumps call setpos(".",pos_saved) if end !~ '\s*}' let completion_list = [] " if atplib#search#DocumentClass(b:atp_MainFile) == 'beamer' " call extend(completion_list, g:atp_BeamerEnvironments) " endif call extend(completion_list,deepcopy(g:atp_Environments)) if g:atp_local_completion " Make a list of local envs and commands if !exists("s:atp_LocalEnvironments") LocalCommands let s:atp_LocalEnvironments=copy(b:atp_LocalEnvironments) elseif has("python") LocalCommands let s:atp_LocalEnvironments=copy(b:atp_LocalEnvironments) endif let completion_list=atplib#Extend(completion_list,s:atp_LocalEnvironments) endif let completion_list=atplib#Add(completion_list,'}') else let completion_list = [] " if atplib#search#DocumentClass(b:atp_MainFile) == 'beamer' " call extend(completion_list, g:atp_BeamerEnvironments) " endif call extend(completion_list,deepcopy(g:atp_Environments)) if g:atp_local_completion " Make a list of local envs and commands if !exists("s:atp_LocalEnvironments") LocalCommands let s:atp_LocalEnvironments=copy(b:atp_LocalEnvironments) elseif has("python") LocalCommands let s:atp_LocalEnvironments=copy(b:atp_LocalEnvironments) endif call atplib#Extend(completion_list,s:atp_LocalEnvironments) endif endif " TIKZ let in_tikz=searchpair('\\begin\s*{tikzpicture}','','\\end\s*{tikzpicture}','bnW',"", max([1,(line(".")-g:atp_completion_limits[2])])) || atplib#complete#CheckOpened('\\tikz{','}',line("."),g:atp_completion_limits[0]) if in_tikz if end !~ '\s*}' call extend(completion_list,atplib#Add(g:atp_tikz_environments,'}')) else call extend(completion_list,g:atp_tikz_environments) endif endif " AMSMATH if atplib#search#SearchPackage('amsmath', stop_line) || g:atp_amsmath != 0 || atplib#search#DocumentClass(b:atp_MainFile) =~ '^ams' if end !~ '\s*}' call extend(completion_list,atplib#Add(g:atp_amsmath_environments,'}'),0) else call extend(completion_list,g:atp_amsmath_environments,0) endif endif " MathTools " moved to packages/mathtools.vim " if atplib#search#SearchPackage('mathtools', stop_line) " if end !~ '\s*}' " call extend(completion_list,atplib#Add(g:atp_MathTools_environments,'}')) " else " call extend(completion_list,g:atp_MathTools_environments) " endif " endif " Packages for package in g:atp_packages if atplib#search#SearchPackage(package) && exists("g:atp_".package."_environments") if end !~ '\s*}' call extend(completion_list,atplib#Add({'g:atp_'.package.'_environments'},'}')) else call extend(completion_list,{'g:atp_'.package.'_environments'}) endif endif endfor " {{{3 ------------ ENVIRONMENT OPTIONS elseif completion_method == 'environment options' let env_name = matchstr(l, '.*\\begin{\s*\zs\w\+\ze\s*}') let completion_list=[] for package in g:atp_packages if exists("g:atp_".package."_environment_options") && atplib#search#SearchPackage(package) echomsg package for key in keys({"g:atp_".package."_environment_options"}) if env_name =~ key call extend(completion_list, {"g:atp_".package."_environment_options"}[key]) endif endfor endif endfor "{{{3 ------------ PACKAGE OPTIONS VALUES elseif completion_method == 'package options values' let package = matchstr(line, '\\usepackage\[.*{\zs[^}]*\ze}') let option = matchstr(l,'\zs\<\w\+=\ze[^=]*$') let completion_list=[] if exists("g:atp_".package."_options_values") for pat in keys({"g:atp_".package."_options_values"}) if (option =~ pat) let val={"g:atp_".package."_options_values"}[pat] if type(val) == 3 let completion_list={"g:atp_".package."_options_values"}[pat] elseif type(val) == 1 execute "let add=".val."()" call extend(completion_list, add) else let completion_list = [] endif break endif endfor else let g:time_TabCompletion=reltimestr(reltime(time)) call atplib#Log("TabCompletion.log", 'package options return') return "" endif "{{{3 ------------ PACKAGE OPTIONS elseif completion_method == 'package options' let package = matchstr(line, '\\usepackage.*{\zs[^}]*\ze}') let g:package = package if exists("g:atp_".package."_options") && atplib#search#SearchPackage(package) let completion_list=copy({"g:atp_".package."_options"}) else let g:time_TabCompletion=reltimestr(reltime(time)) return "" endif "{{{3 ------------ PACKAGES elseif completion_method == 'package' if exists("g:atp_LatexPackages") let completion_list = copy(g:atp_LatexPackages) else echo "[ATP:] makeing list of packages (it might take a while) ... " if g:atp_debugTabCompletion let debugTabCompletion_LatexPackages_TimeStart=reltime() endif let g:atp_LatexPackages = atplib#search#KpsewhichGlobPath("tex", "", "*.sty") let completion_list = deepcopy(g:atp_LatexPackages) if g:atp_debugTabCompletion let g:debugTabCompletion_LatexPackages_Time=reltimestr(reltime(debugTabCompletion_LatexPackages_TimeStart)) call atplib#Log("TabCompletion.log", "LatexPackages Time: ".g:debugTabCompletion_LatexPackages_Time) endif redraw endif "{{{3 ------------ PAGESTYLE elseif completion_method == 'pagestyle' let completion_list=copy(g:atp_pagestyles) if atplib#search#SearchPackage('fancyhdr') call extend(completion_list, g:atp_fancyhdr_pagestyles) endif "{{{3 ------------ PAGENUMBERING elseif completion_method == 'pagenumbering' let completion_list=copy(g:atp_pagenumbering) " {{{3 ------------ TIKZ LIBRARIES elseif completion_method == 'tikz libraries' let completion_list=deepcopy(g:atp_tikz_libraries) " {{{3 ------------ TIKZ KEYWORDS elseif completion_method == 'tikzpicture keywords' let completion_list=deepcopy(g:atp_tikz_keywords) " TODO: add support for all tikz libraries let tikz_libraries = atplib#search#GrepPackageList('\\use\%(tikz\|pgf\)library\s*{') call map(tikz_libraries, "substitute(v:val, '\\..*$', '', '')") for lib in tikz_libraries if exists("g:atp_tikz_library_".lib."_keywords") call extend(completion_list,g:atp_tikz_library_{lib}_keywords) endif endfor " {{{3 ------------ TIKZ COMMANDS elseif completion_method == 'tikzpicture commands' let completion_list = [] " if tikz is declared and we are in tikz environment. let tikz_libraries = atplib#search#GrepPackageList('\\use\%(tikz\|pgf\)library\s*{') for lib in tikz_libraries if exists("g:atp_tikz_library_".lib."_commands") call extend(completion_list, g:atp_tikz_library_{lib}_commands) endif endfor " {{{3 ------------ TIKZ COLORS elseif completion_method == 'tikzpicture colors' let completion_list = copy(b:atp_LocalColors) " {{{3 ------------ COMMANDS elseif completion_method == 'command' "{{{4 let tbegin=strpart(l,o+1) let completion_list=[] " Find end of the preambule. if expand("%:p") == atp_MainFile " if the file is the main file let saved_pos=getpos(".") keepjumps call setpos(".", [0,1,1,0]) keepjumps let stop_line=search('\\begin\s*{document}','nW') keepjumps call setpos(".", saved_pos) else " if the file doesn't contain the preambule if &filetype == 'tex' let saved_loclist = getloclist(0) silent! execute '1lvimgrep /\\begin\s*{\s*document\s*}/j ' . fnameescape(atp_MainFile) let stop_line = get(get(getloclist(0), 0, {}), 'lnum', 0) call setloclist(0, saved_loclist) else let stop_line = 0 endif endif " Are we in the math mode? let math_is_opened = atplib#IsInMath() " -------------------- LOCAL commands {{{4 if g:atp_local_completion " make a list of local envs and commands: if !exists("b:atp_LocalCommands") LocalCommands elseif has("python") LocalCommands endif call extend(completion_list, b:atp_LocalCommands) endif " {{{4 -------------------- MATH commands: amsmath, amssymb, mathtools, nicefrac, SIunits, math non expert mode. " if we are in math mode or if we do not check for it. if g:atp_no_math_command_completion != 1 && ( !g:atp_MathOpened || math_is_opened ) call extend(completion_list, g:atp_math_commands) " ----------------------- amsmath && amssymb {{{5 " if g:atp_amsmath is set or the document class is ams... if (g:atp_amsmath != 0 || atplib#search#DocumentClass(b:atp_MainFile) =~ '^ams') call extend(completion_list, g:atp_amsmath_commands) call extend(completion_list, g:atp_ams_negations) call extend(completion_list, g:atp_amsfonts) call extend(completion_list, g:atp_amsextra_commands) if a:expert_mode == 0 call extend(completion_list, g:atp_ams_negations_non_expert_mode) endif " else check if the packages are declared: else if atplib#search#SearchPackage('amsmath', stop_line) call extend(completion_list, g:atp_amsmath_commands,0) endif if atplib#search#SearchPackage('amssymb', stop_line) call extend(completion_list, g:atp_ams_negations) if a:expert_mode == 0 call extend(completion_list, g:atp_ams_negations_non_expert_mode) endif endif endif " ----------------------- nicefrac {{{5 if atplib#search#SearchPackage('nicefrac', stop_line) call add(completion_list,"\\nicefrac{") endif " ----------------------- SIunits {{{5 if atplib#search#SearchPackage('SIunits', stop_line) && ( index(g:atp_completion_active_modes, 'SIunits') != -1 || index(g:atp_completion_active_modes, 'siunits') != -1 ) call extend(completion_list, g:atp_siuinits) endif for package in g:atp_packages if exists("g:atp_".package."_math_commands") call extend(completion_list, {"g:atp_".package."_math_commands"}) endif endfor " ----------------------- math non expert mode {{{5 if a:expert_mode == 0 call extend(completion_list, g:atp_math_commands_non_expert_mode) endif endif " {{{4 -------------------- BEAMER commands " if atplib#search#DocumentClass(b:atp_MainFile) == 'beamer' " call extend(completion_list, g:atp_BeamerCommands) " endif " {{{4 -------------------- TIKZ commands " if tikz is declared and we are in tikz environment. if atplib#search#SearchPackage('\(tikz\|pgf\)') let in_tikz=searchpair('\\begin\s*{tikzpicture}','','\\end\s*{tikzpicture}','bnW',"", max([1,(line(".")-g:atp_completion_limits[2])])) || atplib#complete#CheckOpened('\\tikz{','}',line("."),g:atp_completion_limits[0]) if in_tikz " find all tikz libraries at once: let tikz_libraries = atplib#search#GrepPackageList('\\use\%(tikz\|pgf\)library\s*{') " add every set of library commands: for lib in tikz_libraries if exists("g:atp_tikz_library_".lib."_commands") call extend(completion_list, g:atp_tikz_library_{lib}_commands) endif endfor " add common tikz commands: call extend(completion_list, g:atp_tikz_commands) " if in text mode add normal commands: if searchpair('\\\@ the pattern will not work and we do " not want env name. if env_name == pline let env_name='' endif if has_key(g:atp_shortname_dict,env_name) if g:atp_shortname_dict[env_name] != 'no_short_name' && g:atp_shortname_dict[env_name] != '' let short_env_name=g:atp_shortname_dict[env_name] let no_separator=0 else let short_env_name='' let no_separator=1 endif else let short_env_name='' let no_separator=1 endif " if index(g:atp_no_separator_list, env_name) != -1 " let no_separator = 1 " endif if g:atp_env_short_names == 1 if no_separator == 0 && g:atp_no_separator == 0 let short_env_name=short_env_name . g:atp_separator endif else let short_env_name='' endif call extend(completion_list, [ '\label{' . short_env_name ],0) " {{{3 ------------ COMMAND VALUES elseif completion_method == 'command values' if l !~ '\\renewcommand{[^}]*}{[^}]*$' let command = matchstr(l, '.*\\\w\+\%({\%([^}]\|{[^}]*}}\)*}\)*{\ze\%([^}]\|{[^}]*}\)*$') else let command = matchstr(l, '.*\\renewcommand{\s*\zs\\\?\w*\ze\s*}') endif let completion_list = [] let command_pat='\\\w\+[{\|\[]' for package in g:atp_packages let test = 0 if exists("g:atp_".package."_loading") for key in keys(g:atp_{package}_loading) let package_line_nr = atplib#search#SearchPackage(g:atp_{package}_loading[key]) if g:atp_{package}_loading[key] == "" || package_line_nr == 0 let test = package_line_nr else let package_line = getline(package_line_nr) let test = (package_line=~'\\usepackage\[[^\]]*,\='.g:atp_{package}_loading[key].'[,\]]') endif if test break endif endfor endif if exists("g:atp_".package."_command_values") && \ ( atplib#search#SearchPackage(package) || test || atplib#search#DocumentClass(b:atp_MainFile) == package ) for key in keys({"g:atp_".package."_command_values"}) " uncomment this to debug in which package file there is a mistake. if command =~ key let command_pat = key let val={"g:atp_".package."_command_values"}[key] if g:atp_debugTabCompletion call atplib#Log("TabCompletion.log", 'command_pat='.command_pat." package=".package) call atplib#Log("TabCompletion.log", 'val='.string(val)) endif if type(val) == 3 call extend(completion_list, val) elseif type(val) == 1 && exists("*".val) execute "let add=".val."()" call extend(completion_list, add) else call atplib#Log("TabCompletion.log", "command values: wrong type error") endif endif endfor endif endfor " {{{3 ------------ ABBREVIATIONS elseif completion_method == 'abbreviations' let completion_list = sort(copy(b:atp_LocalEnvironments), "atplib#CompareStarAfter")+[ "document","description","letter","picture","list","minipage","titlepage","thebibliography","bibliography","center","flushright","flushleft","tikzpicture","frame","itemize","enumerate","quote","quotation","verse","abstract","verbatim","figure","array","table","tabular","equation","equation*","align","align*","alignat","alignat*","gather","gather*","multline","multline*","split","flalign","flalign*","corollary","theorem","proposition","lemma","definition","proof","remark","example","exercise","note","question","notation"] for package in g:atp_packages if exists("g:atp_".package."_environments") call extend(completion_list, {"g:atp_".package."_environments"}) endif endfor call map(completion_list, "g:atp_iabbrev_leader.v:val.g:atp_iabbrev_leader") " {{{3 ------------ LABELS /are done later only the completions variable / elseif completion_method == 'labels' let completion_list = [] " {{{3 ------------ TEX INPUTFILES elseif completion_method == 'inputfiles' let completion_list=[] call extend(completion_list, atplib#search#KpsewhichGlobPath('tex', b:atp_OutDir . ',' . g:atp_texinputs, '*.tex', ':t:r', '^\%(\/home\|\.\|.*users\)', '\%(^\\usr\|texlive\|miktex\|kpsewhich\|generic\)')) call sort(completion_list) " {{{3 ------------ TEX INCLUDEGRAPHICS elseif completion_method == 'includegraphics' " Search for \graphicspath but only in the preamble let matches=atplib#search#GrepPreambule('\\graphicspath') if len(matches) for match in matches let dirs = map(split(matchstr(match['text'], '\graphicspath\s*{\zs.*\ze}'), '}'), "substitute(v:val, '^\s*{', '', '')") call map(dirs, "substitute(v:val, '\/\/', '/**', 'g')") endfor else let dirs = [fnamemodify(atplib#FullPath(b:atp_MainFile), ":h")] endif let gr_dirs = join(dirs,',') let g:gr_dirs = gr_dirs if b:atp_TexCompiler == "latex" let gr = ["*.eps", "*.EPS"] else let gr = ["*.gif", "*jpeg", "*.jpg", "*.png", "*.pdf", "*.pdf_tex", "*.eps", \ "*.GIF", "*JPEG", "*.JPG", "*.PNG", "*.PDF", "*.PDF_TEX", "*.EPS"] endif let completion_list=[] if begin !~ '\.\(gif\|jpe\?g\|png\|pdf\|pdf_tex\|eps\)$' for ext in gr let completion_list+=split(globpath(gr_dirs, begin.ext), "\n") endfor else let completion_list+=split(globpath(gr_dirs, begin), "\n") endif call map(completion_list, "substitute(v:val, '^\s*\.\/', '', '')") " {{{3 ------------ BIBFILES elseif completion_method == 'bibfiles' let completion_list=[] call extend(completion_list, atplib#search#KpsewhichGlobPath('bib', b:atp_OutDir . ',' . g:atp_bibinputs, '*.bib', ':t:r', '^\%(\/home\|\.\|.*users\)', '\%(^\\usr\|texlive\|miktex\|kpsewhich\|generic\|miktex\)')) call sort(completion_list) " {{{3 ------------ BIBSTYLES elseif completion_method == 'bibstyles' let completion_list=atplib#search#KpsewhichGlobPath("bst", "", "*.bst") "{{{3 ------------ DOCUMENTCLASS OPTIONS elseif completion_method == 'documentclass options' let documentclass = matchstr(line, '\\documentclass\[[^{]*{\zs[^}]*\ze}') if exists("g:atp_".documentclass."_options") let completion_list={"g:atp_".documentclass."_options"} else let g:time_TabCompletion=reltimestr(reltime(time)) return '' endif "{{{3 ------------ DOCUMENTCLASS elseif completion_method == 'documentclass' if exists("g:atp_LatexClasses") let completion_list = copy(g:atp_LatexClasses) else echo "[ATP:] makeing list of document classes (it might take a while) ... " if g:atp_debugTabCompletion let debugTabCompletion_LatexClasses_TimeStart=reltime() endif let g:atp_LatexClasses = atplib#search#KpsewhichGlobPath("tex", "", "*.cls") if g:atp_debugTabCompletion let g:debugTabCompletion_LatexClasses_Time=reltimestr(reltime(debugTabCompletion_LatexClasses_TimeStart)) call atplib#Log("TabCompletion.log", "LatexClasses Time: ".g:debugTabCompletion_LatexClasses_Time) endif redraw let completion_list = deepcopy(g:atp_LatexClasses) endif " \documentclass must be closed right after the name ends: if nchar != "}" call map(completion_list,'v:val."}"') endif "{{{3 ------------ FONT FAMILY elseif completion_method == 'font family' echo "[ATP:] searching through fd files ..." let time=reltime() let bpos=searchpos('\\selectfon\zst','bnW',line("."))[1] let epos=searchpos('\\selectfont','nW',line("."))[1]-1 if epos == -1 let epos=len(line) endif let fline=strpart(line,bpos,epos-bpos) let encoding=matchstr(fline,'\\\%(usefont\|DeclareFixedFont\s*{[^}]*}\|fontencoding\)\s*{\zs[^}]*\ze}') if encoding == "" let encoding=g:atp_font_encoding endif let completion_list=[] let fd_list=atplib#fontpreview#FdSearch('^'.encoding.begin) " The above function takes .5s to complete. The code below takes more 1s. for file in fd_list call extend(completion_list,map(atplib#fontpreview#ShowFonts(file),'matchstr(v:val,"usefont\\s*{[^}]*}\\s*{\\zs[^}]*\\ze}")')) endfor " call filter(completion_list,'count(completion_list,v:val) == 1 ') " This was taking another .8s. redraw if len(completion_list) == 0 echo "[ATP:] nothing found." endif let g:time_font_family=reltimestr(reltime(time)) "{{{3 ------------ FONT SERIES elseif completion_method == 'font series' let time=reltime() let bpos=searchpos('\\selectfon\zst','bnW',line("."))[1] let epos=searchpos('\\selectfont','nW',line("."))[1]-1 if epos == -1 let epos=len(line) endif let fline=strpart(line,bpos,epos-bpos) let encoding=matchstr(fline,'\\\%(usefont\|DeclareFixedFont\s*{[^}]*}\|fontencoding\)\s*{\zs[^}]*\ze}') if encoding == "" let encoding=g:atp_font_encoding endif let font_family=matchstr(fline,'\\\%(usefont\s*{[^}]*}\|DeclareFixedFont\s*{[^}]*}\s*{[^}]*}\|fontfamily\)\s*{\zs[^}]*\ze}') echo "[ATP:] searching through fd files ..." let completion_list=[] let fd_list=atplib#fontpreview#FdSearch(encoding.font_family) " The above function takes .5s to complete. for file in fd_list call extend(completion_list, map(atplib#fontpreview#ShowFonts(file),'matchstr(v:val,"usefont{[^}]*}{[^}]*}{\\zs[^}]*\\ze}")')) endfor call filter(completion_list,'count(completion_list,v:val) == 1 ') redraw "{{{3 ------------ FONT SHAPE elseif completion_method == 'font shape' let bpos=searchpos('\\selectfon\zst','bnW',line("."))[1] let epos=searchpos('\\selectfont','nW',line("."))[1]-1 if epos == -1 let epos=len(line) endif let fline=strpart(line,bpos,epos-bpos) let encoding=matchstr(fline,'\\\%(usefont\|DeclareFixedFont\s*{[^}]*}\|fontencoding\)\s*{\zs[^}]*\ze}') if encoding == "" let encoding=g:atp_font_encoding endif let font_family=matchstr(fline,'\\\%(usefont{[^}]*}\|DeclareFixedFont\s*{[^}]*}\s*{[^}]*}\|fontfamily\)\s*{\zs[^}]*\ze}') let font_series=matchstr(fline,'\\\%(usefont\s*{[^}]*}\s*{[^}]*}\|DeclareFixedFont\s*{[^}]*}\s*{[^}]*}\s*{[^}]*}\|fontseries\)\s*{\zs[^}]*\ze}') echo "[ATP:] searching through fd files ..." let completion_list=[] let fd_list=atplib#fontpreview#FdSearch('^'.encoding.font_family) for file in fd_list call extend(completion_list,map(atplib#fontpreview#ShowFonts(file),'matchstr(v:val,"usefont{[^}]*}{'.font_family.'}{'.font_series.'}{\\zs[^}]*\\ze}")')) endfor call filter(completion_list,'count(completion_list,v:val) == 1 ') redraw " {{{3 ------------ FONT ENCODING elseif completion_method == 'font encoding' let bpos=searchpos('\\selectfon\zst','bnW',line("."))[1] let epos=searchpos('\\selectfont','nW',line("."))[1]-1 if epos == -1 let epos=len(line) endif let fline=strpart(line,bpos,epos-bpos) let font_family=matchstr(fline,'\\\%(usefont\s*{[^}]*}\|DeclareFixedFont\s*{[^}]*}\s*{[^}]*}\|fontfamily\)\s*{\zs[^}]*\ze}') if font_family != "" echo "[ATP:] searching through fd files ..." let fd_list=atplib#fontpreview#FdSearch(font_family) let completion_list=map(copy(fd_list),'toupper(substitute(fnamemodify(v:val,":t"),"'.font_family.'.*$","",""))') redraw else " let completion_list=[] " for fd_file in fd_list " let enc=substitute(fnamemodify(fd_file,":t"),"\\d\\zs.*$","","") " if enc != fnamemodify(fd_file,":t") " call add(completion_list,toupper(enc)) " endif " endfor let completion_list=g:atp_completion_font_encodings endif " {{{3 ------------ BIBITEMS elseif completion_method == 'bibitems' let time_bibitems=reltime() let col = col('.') - 1 while col > 0 && line[col - 1] !~ '{\|,' let col -= 1 endwhile let pat = strpart(l,col) let g:pat = pat let searchbib_time=reltime() if len(filter(values(copy(b:TypeDict)), "v:val == 'bib'")) if !exists("b:ListOfFiles") && !exists("b:TypeDict") call TreeOfFiles(b:atp_MainFile) endif if has("python") && g:atp_bibsearch == "python" && pat != "" let bibfiles=[] for f in b:ListOfFiles if b:TypeDict[f] == 'bib' call add(bibfiles, f) endif endfor let bibitems_list=values(atplib#bibsearch#searchbib_py(pat, bibfiles)) else let bibdict={} for f in b:ListOfFiles if b:TypeDict[f] == 'bib' let bibdict[f]=readfile(f) endif endfor let bibitems_list=values(atplib#bibsearch#searchbib(pat, bibdict)) endif let g:bibitems_list=bibitems_list let g:time_searchbib_py=reltimestr(reltime(searchbib_time)) if g:atp_debugTabCompletion let g:pat = pat endif let pre_completion_list=[] let completion_dict=[] let completion_list=[] let time_bibitems_for=reltime() for dict in bibitems_list for key in keys(dict) " ToDo: change dict[key][...] to get() to not get errors " if it is not present or to handle situations when it is not " present! call add(pre_completion_list, dict[key]['bibfield_key']) let bibkey=dict[key]['bibfield_key'] let bibkey=substitute(strpart(bibkey,max([stridx(bibkey,'{'),stridx(bibkey,'(')])+1),',\s*','','') if nchar != ',' && nchar != '}' let bibkey.="}" endif let title=get(dict[key],'title', 'notitle') let title=substitute(matchstr(title,'^\s*\ctitle\s*=\s*\%("\|{\|(\)\zs.*\ze\%("\|}\|)\)\s*\%(,\|$\)'),'{\|}','','g') let year=get(dict[key],'year',"") let year=matchstr(year,'^\s*\cyear\s*=\s*\%("\|{\|(\)\zs.*\ze\%("\|}\|)\)\s*\%(,\|$\)') let abbr=get(dict[key],'author',"noauthor") let author = matchstr(abbr,'^\s*\cauthor\s*=\s*\%("\|{\|(\)\zs.*\ze\%("\|}\|)\)\s*,') if abbr=="noauthor" || abbr == "" let abbr=get(dict[key],'editor',"") let author = matchstr(abbr,'^\s*\ceditor\s*=\s*\%("\|{\|(\)\zs.*\ze\%("\|}\|)\)\s*,') endif if len(author) >= 40 if match(author,'\sand\s') let author=strpart(author,0,match(author,'\sand\s')) . ' et al.' else let author=strpart(author,0,40) endif endif let author=substitute(author,'{\|}','','g') if dict[key]['bibfield_key'] =~? '\' let type="[a]" elseif dict[key]['bibfield_key'] =~? '\' let type="[B]" elseif dict[key]['bibfield_key'] =~? '\' let type="[b]" elseif dict[key]['bibfield_key'] =~? '\<\%(proceedings\|conference\)\>' let type="[p]" elseif dict[key]['bibfield_key'] =~? '\' let type="[u]" elseif dict[key]['bibfield_key'] =~? '\' let type="[c]" elseif dict[key]['bibfield_key'] =~? '\' let type="[PhD]" elseif dict[key]['bibfield_key'] =~? '\' let type="[M]" elseif dict[key]['bibfield_key'] =~? '\' let type="[-]" elseif dict[key]['bibfield_key'] =~? '\' let type="[t]" elseif dict[key]['bibfield_key'] =~? '\' let type="[m]" else let type=" " endif let abbr=type." ".author." (".year.") " call add(completion_dict, { "word" : bibkey, "menu" : title, "abbr" : abbr }) endfor endfor let g:completion_dict=completion_dict for key in pre_completion_list call add(completion_list,substitute(strpart(key,max([stridx(key,'{'),stridx(key,'(')])+1),',\s*','','')) endfor else " add the \bibitems found in include files let time_bibitems_SearchBibItems=reltime() let completion_dict=[] let dict=atplib#bibsearch#SearchBibItems() let g:dict = copy(dict) for key in keys(dict) if a:expert_mode && ( key =~ '^'.begin || dict[key]['label'] =~ '^'.begin ) || \ !a:expert_mode && ( key =~ begin || dict[key]['label'] =~ begin ) call add(completion_dict, { "word" : key, "menu" : dict[key]['rest'], "abbrev" : dict[key]['label'] }) endif endfor let g:time_bibitems_SearchBibItems=reltimestr(reltime(time_bibitems_SearchBibItems)) endif let g:time_bibitems=reltimestr(reltime(time_bibitems)) " {{{3 ------------ TODONOTES TODO & MISSING FIGURE OPTIONS elseif completion_method == 'todo options' let completion_list = copy(g:atp_TodoNotes_todo_options) elseif completion_method == 'missingfigure options' let completion_list = copy(g:atp_TodoNotes_missingfigure_options) endif " }}}3 if exists("completion_list") let b:completion_list=completion_list " DEBUG call atplib#Log("TabCompletion.log", "completion_list=".string(completion_list)) endif " {{{2 make the list of matching completions "{{{3 --------- completion_method = !close environments !env_close if completion_method != 'close environments' && completion_method != 'env_close' let completions=[] " {{{4 --------- packages, package options, bibstyles, font (family, series, shapre, encoding), document class, documentclass options if (completion_method == 'package' || \ completion_method == 'package options'|| \ completion_method == 'command values'|| \ completion_method == 'environment options'|| \ completion_method == 'documentclass options'|| \ completion_method == 'bibstyles' || \ completion_method =~ 'beamer\%(\|inner\|outer\|color\|font\)themes' || \ completion_method == 'font family' || \ completion_method == 'font series' || \ completion_method == 'font shape' || \ completion_method == 'font encoding'|| \ completion_method == 'pagestyle'|| \ completion_method == 'pagenumbering'|| \ completion_method == 'documentclass' ) if a:expert_mode let completions = filter(copy(completion_list),' v:val =~? "^".begin') else let completions = filter(copy(completion_list),' v:val =~? begin') endif " {{{4 --------- package options values elseif ( completion_method == 'package options values' ) if a:expert_mode let completions = filter(copy(completion_list),' v:val =~? "^".ebegin') else let completions = filter(copy(completion_list),' v:val =~? ebegin') endif " {{{4 --------- environment names, bibfiles elseif ( completion_method == 'environment_names' || \ completion_method == 'bibfiles' ) if a:expert_mode let completions = filter(copy(completion_list),' v:val =~# "^".begin') else let completions = filter(copy(completion_list),' v:val =~? begin') endif " {{{4 --------- colors elseif completion_method == 'tikzpicture colors' if a:expert_mode let completions = filter(copy(completion_list),' v:val =~# "^".color_begin') else let completions = filter(copy(completion_list),' v:val =~? color_begin') endif " {{{4 --------- tikzpicture libraries, inputfiles " match not only in the beginning elseif (completion_method == 'tikz libraries' || \ completion_method == 'inputfiles') let completions = filter(copy(completion_list),' v:val =~? begin') " if nchar != "}" && nchar != "," && completion_method != 'inputfiles' " call map(completions,'v:val') " endif " {{{4 --------- Commands " must match at the beginning (but in a different way) " (only in expert_mode). elseif completion_method == 'command' if a:expert_mode == 1 let completions = filter(copy(completion_list),'v:val =~# "\\\\".tbegin') elseif a:expert_mode != 1 let completions = filter(copy(completion_list),'v:val =~? tbegin') endif " {{{4 --------- Abbreviations elseif completion_method == 'abbreviations' let completions = filter(copy(completion_list), 'v:val =~# "^" . abegin') " {{{4 --------- Tikzpicture Keywords elseif completion_method == 'tikzpicture keywords' || \ completion_method == 'todo options' || \ completion_method == 'missingfigure options' if g:atp_completion_tikz_expertmode let completions = filter(copy(completion_list),'v:val =~# "^".tbegin') else let completions = filter(copy(completion_list),'v:val =~? tbegin') endif " {{{4 --------- Tikzpicture Commands elseif completion_method == 'tikzpicture commands' if a:expert_mode == 1 let completions = filter(copy(completion_list),'v:val =~# "^".tbegin') elseif a:expert_mode != 1 let completions = filter(copy(completion_list),'v:val =~? tbegin') endif " {{{4 --------- Labels elseif completion_method == 'labels' " Complete label by string or number: let aux_data = atplib#tools#GrepAuxFile() let completion_dict = [] let pattern = matchstr(l, '\%(.\|\\\%(eq\)\=ref\)*\\\%(eq\)\=ref\s*{\zs\S*$') for data in aux_data " match label by string or number if ( data[0] =~ '^' . pattern || data[1] =~ '^'. pattern ) && a:expert_mode || ( data[0] =~ pattern || data[1] =~ pattern ) && !a:expert_mode let close = ( nchar == '}' ? '' : '}' ) call add(completion_dict, { "word" : data[0].close, "abbr" : data[0], "menu" : ( data[2] == 'equation' && data[1] != "" ? "(".data[1].")" : data[1] ) , "kind" : data[2][0] }) endif endfor " {{{4 --------- includegraphics elseif completion_method == 'includegraphics' let completions=copy(completion_list) endif "{{{3 --------- else: try to close environment else call atplib#complete#CloseLastEnvironment('a', 'environment') let b:tc_return="1" let g:time_TabCompletion=reltimestr(reltime(time)) return '' endif "{{{3 --------- SORTING and TRUNCATION " ToDo: we will not truncate if completion method is specific, this should be " made by a variable! Maybe better is to provide a positive list !!! if g:atp_completion_truncate && a:expert_mode && \ index(['bibfiles', 'bibitems', 'bibstyles', 'font family', \ 'environment_names', 'environment options', 'font series', \ 'font shape', 'font encoding', 'inputfiles', 'includefiles', \ 'labels', 'package options', 'package options values', \ 'documentclass options', 'documentclass options values', \ 'tikz libraries' ],completion_method) == -1 call filter(completions, 'len(substitute(v:val,"^\\","","")) >= g:atp_completion_truncate') endif " THINK: about this ... " if completion_method == "tikzpicture keywords" " let bracket = atplib#complete#CloseLastBracket(g:atp_bracket_dict, 1) " if bracket != "" " call add(completions, bracket) " endif " endif " if the list is long it is better if it is sorted, if it short it is " better if the more used things are at the beginning. if g:atp_sort_completion_list && len(completions) >= g:atp_sort_completion_list && completion_method != 'labels' if completion_method == 'abbreviations' let completions=sort(completions, "atplib#CompareStarAfter") else let completions=sort(completions) endif endif " DEBUG let b:completions=completions " {{{2 COMPLETE call cursor(pos_saved[1], pos_saved[2]) " {{{3 package, tikz libraries, environment_names, colors, bibfiles, bibstyles, documentclass, font family, font series, font shape font encoding, input files, includegraphics if \ completion_method == 'package' || \ completion_method == 'environment options' || \ completion_method == 'environment_names' || \ completion_method == 'tikz libraries' || \ completion_method == 'pagestyle' || \ completion_method == 'pagenumbering' || \ completion_method == 'bibfiles' || \ completion_method == 'bibstyles' || \ completion_method == 'documentclass' || \ completion_method == 'font family' || \ completion_method == 'font series' || \ completion_method == 'font shape' || \ completion_method == 'font encoding' || \ completion_method == 'todo options' || \ completion_method == 'missingfigure options' || \ completion_method == 'inputfiles' || \ completion_method == 'includegraphics' let column = nr+2 call complete(column,completions) "{{{3 abbreviations elseif completion_method == 'abbreviations' let col=match(l, '^.*\zs=')+1 call complete(col, completions) let column=col "{{{3 labels elseif completion_method == 'labels' let col=match(l, '\%(.\|\\\%(eq\)\=ref\)*\\\(eq\)\=ref\s*{\zs\S*$')+1 call complete(col, completion_dict) let column=col return '' " {{{3 bibitems elseif !normal_mode && completion_method == 'bibitems' if exists("completion_dict") " for bibtex, biblatex call complete(col+1,completion_dict) let column=col+1 else " for thebibliography environment call complete(col+1,completion_list) let column=col+1 endif " {{{3 commands, tikzcpicture commands elseif !normal_mode && (completion_method == 'command' || completion_method == 'tikzpicture commands') " We are not completing greek letters, but we add them if cbegin is " one. call extend(completion_list, g:atp_greek_letters) if count(completion_list, cbegin) >= 1 " Add here brackets - somebody might want to " close a bracket after \nu and not get \numberwithin{ (which is " rarely used). let b:comp_method = "brackets in commands" if (!normal_mode && index(g:atp_completion_active_modes, 'brackets') != -1 ) || \ (normal_mode && index(g:atp_completion_active_modes_normal_mode, 'brackets') != -1 ) let bracket=atplib#complete#GetBracket(append, g:atp_bracket_dict) if bracket != "0" && bracket != "" let completions = extend([cbegin.bracket], completions) endif endif call add(completions, cbegin) endif call complete(o+1,completions) let column=o+1 " {{{3 tikzpicture keywords elseif !normal_mode && (completion_method == 'tikzpicture keywords') let t=match(l,'\zs\<\w*$') " in case '\zs\<\w*$ is empty if t == -1 let t=col(".") endif call complete(t+1,completions) let column=t+1 let b:tc_return="tikzpicture keywords" " {{{3 tikzpicture colors elseif !normal_mode && (completion_method == 'tikzpicture colors') call complete(color_nr+2, completions) let column=color_nr+2 " {{{3 package and document class options elseif !normal_mode && ( completion_method == 'package options' || completion_method == 'documentclass options' \ || completion_method == 'environment options' ) let col=len(matchstr(l,'^.*\\\%(documentclass\|usepackage\)\[.*,\ze')) if col==0 let col=len(matchstr(l,'^.*\\\%(documentclass\|usepackage\)\[\ze')) endif call complete(col+1, completions) let column = col+1 " {{{3 command values elseif !normal_mode && ( completion_method == 'command values' ) if l !~ '\\renewcommand{[^}]*}{[^}]*$' " let col=max([len(matchstr(l, '.*'.command_pat.'\ze')), len(matchstr(l, '.*'.command_pat.'\%([^}]\|{[^}]*}\)*,\ze'))]) let col=max([len(matchstr(l, '.*\\\w\+\%({\%([^}]\|{[^}]*}\)*}\)*{\ze')), len(matchstr(l, '.*\\\w\+\%({\%([^}]\|{[^}]*}\)*}\)*{\%([^}]\|{[^}]*}\)*,\ze'))]) else let col=len(matchstr(l, '.*\\renewcommand{[^}]*}{\ze')) endif call complete(col+1, completions) let column = col+1 " {{{3 package and document class options values elseif !normal_mode && (completion_method == 'package options values') let col=len(matchstr(l,'\\\%(documentclass\|usepackage\)\[.*=\%({[^}]*,\|{\)\?\ze')) if col==0 let col=len(matchstr(l,'\\\%(documentclass\|usepackage\)\[\ze')) endif call complete(col+1, completions) let column = col+1 else let column = col(".") endif " If the completion method was a command (probably in a math mode) and " there was no completion, check if environments are closed. " {{{3 Final call of CloseLastEnvrionment / CloseLastBracket let len=len(completions) let matched_word = strpart(getline(line(".")), column-1, pos_saved[2]-column) let g:matched_word = matched_word let g:column = column let g:pos_saved = copy(pos_saved) if len == 0 && (!count(['package', 'bibfiles', 'bibstyles', 'inputfiles'], completion_method) || a:expert_mode == 1 ) || len == 1 let b:comp_method .= " final" if count(['command', 'tikzpicture commands', 'tikzpicture keywords', 'command values'], completion_method) && \ (len == 0 || len == 1 && completions[0] =~ '^\\\='. begin . '$' ) let filter = 'strpart(getline("."), 0, col(".") - 1) =~ ''\\\@', 'bnW') " Check Brackets let b:comp_method .= " brackets: 1" let cl_return = atplib#complete#GetBracket(append, g:atp_bracket_dict) " If the bracket was closed return. if cl_return != "0" let g:time_TabCompletion=reltimestr(reltime(time)) return cl_return endif " Check inline math: if atplib#complete#CheckClosed_math('texMathZoneV') || \ atplib#complete#CheckClosed_math('texMathZoneW') || \ atplib#complete#CheckClosed_math('texMathZoneX') || \ b:atp_TexFlavor == 'plaintex' && atplib#complete#CheckClosed_math('texMathZoneY') let zone = 'texMathZoneVWXY' " DEBUG call atplib#complete#CloseLastEnvironment(append, 'math') " Check environments: else let env_opened= searchpairpos('\\begin','','\\end','bnW','searchpair("\\\\begin{".matchstr(getline("."),"\\\\begin{\\zs[^}]*\\ze}"),"","\\\\end{".matchstr(getline("."),"\\\\begin{\\zs[^}]*\\ze}"),"nW")',max([1,(line(".")-g:atp_completion_limits[2])])) let env_name = matchstr(strpart(getline(env_opened[0]), env_opened[1]-1), '\\begin\s*{\zs[^}]*\ze}') let zone = env_name " DEBUG if env_opened != [0, 0] call atplib#complete#CloseLastEnvironment('a', 'environment', env_name, env_opened) endif endif " DEBUG if exists("zone") let b:tc_return =" close_env end " . zone let b:comp_method.=' close_env end ' . zone call atplib#Log("TabCompletion.log", "b:comp_method.=".b:comp_method) else let b:tc_return=" close_env end" let b:comp_method.=' close_env end' call atplib#Log("TabCompletion.log", "b:comp_method=".b:comp_method) endif elseif len == 0 && \ completion_method != 'labels' && \ completion_method != 'bibitems' \ || len == 1 && get(completions, 0, "") == matched_word || \ completion_method != 'brackets' && \ completion_method != 'labels' && \ completion_method != 'bibitems' && \ completion_method != 'bibfiles' && \ completion_method != 'close environments' && \ completion_method != 'algorithmic' && \ completion_method != 'abbreviations' && \ completion_method != 'command' && \ completion_method != 'command values' && \ completion_method != 'tikzpicture' && \ completion_method != 'tikzpicture commands' && \ completion_method != 'tikzpicture keywords' && \ completion_method != 'package options' && \ completion_method != 'documentclass' && \ completion_method != 'documentclass options' && \ completion_method != 'environment_names' && \ completion_method != 'environment options' && \ completion_method != 'todo options' && \ completion_method != 'missingfigure options' " elseif completion_method == 'package' || " \ completion_method == 'environment_names' || " \ completion_method == 'font encoding' || " \ completion_method == 'font family' || " \ completion_method == 'font series' || " \ completion_method == 'font shape' || " \ completion_method == 'bibstyles' || " \ completion_method == 'bibfiles' let b:tc_return='close_bracket end' let b:comp_method .= " brackets: 2" let g:time_TabCompletion=reltimestr(reltime(time)) return atplib#complete#GetBracket(append, g:atp_bracket_dict) endif endif "}}}3 let g:time_TabCompletion=reltimestr(reltime(time)) return '' "}}}2 endfunction catch /E127:/ endtry " }}}1 " vim:fdm=marker:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/fontpreview.vim [[[1 433 " Title: Vim library for ATP filetype plugin. " Author: Marcin Szamotulski " Email: mszamot [AT] gmail [DOT] com " Note: This file is a part of Automatic Tex Plugin for Vim. " URL: https://launchpad.net/automatictexplugin " Language: tex " Font Preview Functions: " These functions search for fd files and show them in a buffer with filetype " 'fd_atp'. There are additional function for this filetype written in " fd_atp.vim ftplugin. Distributed with atp. "{{{1 atplib#fontpreview#FdSearch "([,]) " There are two methods: " 0 - match fd file names ( ":t" filename modifier) <- the default one " 1 - match fd file path function! atplib#fontpreview#FdSearch(...) if a:0 == 0 let pattern = "" let method = 0 else let pattern = ( a:0 >= 1 ? a:1 : "" ) let method = ( a:0 >= 2 ? a:2 : 0 ) endif " let g:method = method " let g:pattern = pattern " Find fd file let path = substitute(substitute(system("kpsewhich -show-path tex"),'!!','','g'),'\/\/\+','\/','g') let path = substitute(path,':\|\n',',','g') let fd = split(globpath(path,"**/*.fd"),'\n') let g:fd = copy(fd) " Match for l:pattern let fd_matches=[] if method == 0 call filter(fd, 'fnamemodify(v:val, ":t") =~ pattern') else call filter(fd, 'v:val =~ pattern') endif return fd endfunction "{{{1 atplib#fontpreview#FontSearch " atplib#fontpreview#FontSearch(method,[]) " method = "" match for name of fd file " method = "!" match against whole path function! atplib#fontpreview#FontSearch(method,...) let l:method = ( a:method == "!" ? 1 : 0 ) let l:pattern = ( a:0 ? a:1 : "" ) let s:fd_matches=atplib#fontpreview#FdSearch(l:pattern, l:method) " Open Buffer and list fd files " set filetype to fd_atp let l:tmp_dir=tempname() call mkdir(l:tmp_dir) let l:fd_bufname="fd_list " . l:pattern let l:openbuffer="32vsplit! +setl\\ nospell\\ ft=fd_atp ". fnameescape(l:tmp_dir . "/" . l:fd_bufname ) let g:fd_matches=[] if len(s:fd_matches) > 0 echohl WarningMsg echomsg "[ATP:] found " . len(s:fd_matches) . " files." echohl None " wipe out the old buffer and open new one instead if buflisted(fnameescape(l:tmp_dir . "/" . l:fd_bufname)) silent exe "bd! " . bufnr(fnameescape(l:tmp_dir . "/" . l:fd_bufname)) endif silent exe l:openbuffer " make l:tmp_dir available for this buffer. " let b:tmp_dir=l:tmp_dir cd /tmp map q :bd " print the lines into the buffer let l:i=0 call setline(1,"FONT DEFINITION FILES:") for l:fd_file in s:fd_matches " we put in line the last directory/fd_filename: " this is what we cut: let l:path=fnamemodify(l:fd_file,":h:h") let l:fd_name=substitute(l:fd_file,"^" . l:path . '/\?','','') " call setline(line('$')+1,fnamemodify(l:fd_file,":t")) call setline(line('$')+1,l:fd_name) call add(g:fd_matches,l:fd_file) let l:i+=1 endfor call append('$', ['', 'maps:', \ 'p Preview font ', \ 'P Preview font+tex file', \ ' Show Fonts in fd file', \ ' Open fd file', \ 'q "bd!"', \ '', \ 'Note: p/P works in visual mode']) silent w setlocal nomodifiable setlocal ro else echohl WarningMsg if !l:method echomsg "[ATP:] no fd file found, try :FontSearch!" else echomsg "[ATP:] no fd file found." endif echohl None endif endfunction "{{{1 atplib#fontpreview#Fd_completion /not needed/ " if !exists("*atplib#Fd_completion") " function! atplib#fontpreview#Fd_completion(A,C,P) " " " Find all files " let l:path=substitute(substitute(system("kpsewhich -show-path tex"),'!!','','g'),'\/\/\+','\/','g') " let l:path=substitute(l:path,':\|\n',',','g') " let l:fd=split(globpath(l:path,"**/*.fd"),"\n") " let l:fd=map(l:fd,'fnamemodify(v:val,":t:r")') " " let l:matches=[] " for l:fd_file in l:fd " if l:fd_file =~ a:A " call add(l:matches,l:fd_file) " endif " endfor " return l:matches " endfunction " endif " {{{1 atplib#fontpreview#OpenFdFile /not working && not needed?/ " function! atplib#fontpreview#OpenFdFile(name) " let l:path=substitute(substitute(system("kpsewhich -show-path tex"),'!!','','g'),'\/\/\+','\/','g') " let l:path=substitute(l:path,':\|\n',',','g') " let b:path=l:path " let l:fd=split(globpath(l:path,"**/".a:name.".fd"),"\n") " let l:fd=map(l:fd,'fnamemodify(v:val,":t:r")') " let b:fd=l:fd " execute "split +setl\\ ft=fd_atp " . l:fd[0] " endfunction "{{{1 atplib#fontpreview#Preview " keep_tex=1 open the tex file of the sample file, otherwise it is deleted (at " least from the buffer list). " To Do: fd_file could be a list of fd_files which we would like to see, every " font should be done after \pagebreak[4] " if a:fd_files=['buffer'] it means read the current buffer (if one has opened " an fd file). function! atplib#fontpreview#Preview(fd_files,keep_tex) if a:fd_files != ["buffer"] let l:fd_files={} for l:fd_file in a:fd_files call extend(l:fd_files,{fd_file : readfile(l:fd_file)}) endfor else let l:fd_files={bufname("%"):getline(1,"$")} endif unlet l:fd_file let l:declare_command='\C\%(DeclareFontShape\%(WithSizes\)\?\|sauter@\%(tt\)\?family\|EC@\%(tt\)\?family\|krntstexmplfamily\|HFO@\%(tt\)\?family\)' let b:declare_command=l:declare_command let l:font_decl_dict={} for l:fd_file in a:fd_files call extend(l:font_decl_dict, {l:fd_file : [ ]}) for l:line in l:fd_files[l:fd_file] if l:line =~ '\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}' call add(l:font_decl_dict[l:fd_file],l:line) endif endfor endfor let l:tmp_dir=tempname() call mkdir(expand(l:tmp_dir)) if a:fd_files == ["buffer"] " WINDOWS NOT COMPATIBLE let l:testfont_file=l:tmp_dir . "/" . fnamemodify(bufname("%"),":t:r") . ".tex" else " the name could be taken from the pattern " or join(map(keys(deepcopy(a:fd_files)),'substitute(fnamemodify(v:val,":t:r"),".fd$","","")'),'_') " though it can be quite a long name. let l:testfont_file=l:tmp_dir . "/" . fnamemodify(a:fd_files[0],":t:r") . ".tex" endif " WINDOWS NOT COMPATIBLE " call system("touch " . l:testfont_file) let l:fd_bufnr=bufnr("%") let s:text="On November 14, 1885, Senator \\& Mrs.~Leland Stanford called \ together at their San Francisco mansion the 24~prominent men who had \ been chosen as the first trustees of The Leland Stanford Junior University. \ They handed to the board the Founding Grant of the University, which they \ had executed three days before.\\\\ \ (!`THE DAZED BROWN FOX QUICKLY GAVE 12345--67890 JUMPS!)" " let l:text="On November 14, 1885, Senator \\& Mrs.~Leland Stanford called " \ together at their San Francisco mansion the 24~prominent men who had " \ been chosen as the first trustees of The Leland Stanford Junior University. " \ They handed to the board the Founding Grant of the University, which they " \ had executed three days before. This document---with various amendments, " \ legislative acts, and court decrees---remains as the University's charter. " \ In bold, sweeping language it stipulates that the objectives of the University " \ are ``to qualify students for personal success and direct usefulness in life; " \ and to promote the public welfare by exercising an influence in behalf of " \ humanity and civilization, teaching the blessings of liberty regulated by " \ law, and inculcating love and reverence for the great principles of " \ government as derived from the inalienable rights of man to life, liberty, " \ and the pursuit of happiness.''\\ " \ (!`THE DAZED BROWN FOX QUICKLY GAVE 12345--67890 JUMPS!)\\par}} " \ \\def\\\moretext{?`But aren't Kafka's Schlo{\\ss} and {\\AE}sop's {\\OE}uvres " \ often na{\\"\\i}ve vis-\\`a-vis the d{\\ae}monic ph{\\oe}nix's official r\\^ole " \ in fluffy souffl\\'es? } " \ \\moretext" if a:fd_files == ["buffer"] let l:openbuffer="edit " else let l:openbuffer="topleft split!" endif execute l:openbuffer . " +setlocal\\ ft=tex\\ modifiable\\ noro " . l:testfont_file " Clear the file (if one has a skeleton file it will be removed.) normal! ggdG let b:atp_ProjectScript = 0 map q :bd! call setline(1,'\documentclass{article}') call setline(2,'\oddsidemargin=0pt') call setline(3,'\textwidth=450pt') call setline(4,'\textheight=700pt') call setline(5,'\topmargin=-10pt') call setline(6,'\headsep=0pt') call setline(7,'\begin{document}') let l:i=8 let l:j=1 let l:len_font_decl_dict=len(l:font_decl_dict) let b:len_font_decl_dict=l:len_font_decl_dict for l:fd_file in keys(l:font_decl_dict) if l:j == 1 call setline(l:i,'\textsc\textbf{\Large Fonts from the file '.l:fd_file.'}\\[2em]') let l:i+=1 else " call setline(l:i,'\pagebreak[4]') call setline(l:i,'\vspace{4em}') call setline(l:i+1,'') call setline(l:i+2,'\textsc\textbf{\Large Fonts from the file '.l:fd_file.'}\\[2em]') let l:i+=3 endif let l:len_font_decl=len(l:font_decl_dict[l:fd_file]) let b:match=[] for l:font in l:font_decl_dict[l:fd_file] " SHOW THE FONT ENCODING, FAMILY, SERIES and SHAPE if matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{\zs[^#}]*\ze}\s*{[^#}]*}') == "b" || \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{\zs[^#}]*\ze}\s*{[^#}]*}') == "bx" let b:show_font='\noindent{\large \textit{Font Encoding}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{\zs[^#}]*\ze}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}') . '}' . \ ' \textit{Font Family}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^}#]*}\s*{\zs[^#}]*\ze}\s*{[^#}]*}\s*{[^#}]*}') . '}' . \ ' \textit{Font Series}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{\zs[^#}]*\ze}\s*{[^#}]*}') . '}' . \ ' \textit{Font Shape}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{\zs[^#}]*\ze}') . '}}\\[2pt]' else let b:show_font='\noindent{\large \textbf{Font Encoding}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{\zs[^#}]*\ze}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}') . '}' . \ ' \textbf{Font Family}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^}#]*}\s*{\zs[^#}]*\ze}\s*{[^#}]*}\s*{[^#}]*}') . '}' . \ ' \textbf{Font Series}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{\zs[^#}]*\ze}\s*{[^#}]*}') . '}' . \ ' \textbf{Font Shape}: \textsf{' . \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{\zs[^#}]*\ze}') . '}}\\[2pt]' endif call setline(l:i,b:show_font) let l:i+=1 " CHANGE THE FONT call setline(l:i,'{' . substitute( \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}'), \ l:declare_command,'usefont','') . \ '\selectfont') " WRITE SAMPLE TEXT call add(b:match,matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}')) let l:i+=1 " END if l:j= 1 ? a:1 : "" ) let l:keep_tex = ( a:0 >= 2 ? a:2 : 0 ) if filereadable(a:fd_file) let l:fd_file=a:fd_file else " Find fd file if a:fd_file !~ '.fd\s*$' let l:fd_file=a:fd_file.".*.fd" else let l:fd_file=a:fd_file endif let l:fd=atplib#fontpreview#FdSearch(a:fd_file, l:method) let g:fd=l:fd if !empty(l:enc) call filter(l:fd, "fnamemodify(v:val, ':t') =~ '^' . l:enc") endif if len(l:fd) == 0 if !l:method echo "FD file not found. Try :FontPreview!" else echo "FD file not found." endif return elseif len(l:fd) == 1 let l:fd_file_list=l:fd else let l:i=1 for l:f in l:fd echo l:i." ".substitute(f,'^'.fnamemodify(f,":h:h").'/\?','','') let l:i+=1 endfor let l:choice=input('Which fd file? ') if l:choice == "" return endif let l:choice_list=split(l:choice,',') let b:choice_list=l:choice_list " if there is 1-4 --> a list of 1,2,3,4 let l:new_choice_list=[] for l:ch in l:choice_list if l:ch =~ '^\d\+$' call add(l:new_choice_list,l:ch) elseif l:ch =~ '^\d\+\s*-\s*\d\+$' let l:b=matchstr(l:ch,'^\d\+') let l:e=matchstr(l:ch,'\d\+$') let l:k=l:b while l:k<=l:e call add(l:new_choice_list,l:k) let l:k+=1 endwhile endif endfor let b:new_choice_list=l:new_choice_list let l:fd_file_list=map(copy(l:new_choice_list),'get(l:fd,(v:val-1),"")') let l:fd_file_list=filter(l:fd_file_list,'v:val != ""') " let l:fd_file=get(l:fd,l:choice-1,"return") if len(l:fd_file_list) == 0 return endif endif endif call atplib#fontpreview#Preview(l:fd_file_list,l:keep_tex) endfunction " {{{1 atplib#fontpreview#ShowFonts function! atplib#fontpreview#ShowFonts_vim(fd_file) let l:declare_command='\C\%(DeclareFontShape\%(WithSizes\)\?\|sauter@\%(tt\)\?family\|EC@\%(tt\)\?family\|krntstexmplfamily\|HFO@\%(tt\)\?family\)' let l:font_decl=[] for l:line in readfile(a:fd_file) if l:line =~ '\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}' call add(l:font_decl,l:line) endif endfor let l:font_commands=[] for l:font in l:font_decl call add(l:font_commands,substitute( \ matchstr(l:font,'\\'.l:declare_command.'\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}'), \ l:declare_command,'usefont','')) endfor return l:font_commands endfunction function! atplib#fontpreview#ShowFonts_py(fd_file) python << END import vim, re file=vim.eval("a:fd_file") try: file_o=open(file, "r") file_l=file_o.readlines() declare_pat=re.compile('(?:DeclareFontShape(?:WithSizes)?|sauter@(?:tt)?family|EC@(?:tt)?family|krntstexmplfamily|HFO@(?:tt)?family)') font_pat=re.compile('(\\\\(?:DeclareFontShape(?:WithSizes)?|sauter@(?:tt)?family|EC@(?:tt)?family|krntstexmplfamily|HFO@(?:tt)?family)\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*}\s*{[^#}]*})') font_commands=[] for line in file_l: if re.search(declare_pat, line): font_cmd=re.search(font_pat, line) if font_cmd: font=font_cmd.group(0) font=re.sub(declare_pat, 'usefont', font) font_commands.append(font) vim.command("let s:return_ShowFonts_py="+str(font_commands)) except IOError: vim.command("let s:return_ShowFonts_py=[]") END return map(s:return_ShowFonts_py, "substitute(v:val, '^\\', '', '')") endfunction function! atplib#fontpreview#ShowFonts(fd_file) if has("python") return atplib#fontpreview#ShowFonts_py(a:fd_file) else return atplib#fontpreview#ShowFonts(a:fd_file) endif endfunction " }}}1 " vim:fdm=marker:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/helpfunctions.vim [[[1 214 " Author: Marcin Szamotulski " Description: This file contains help commands and variables (for mappings used by ATP) " Note: This file is a part of Automatic Tex Plugin for Vim. " Language: tex " Last Change: " {{{1 Help Math IMAPS function! atplib#helpfunctions#HelpMathIMaps() if exists("g:no_plugin_maps") || exists("g:no_atp_maps") echomsg "[ATP:] ATP maps are turned off" return '' endif let g:help_mathimaps = '' \."\n MATH IMAPS" \."\n has value g:atp_imap_leader_1" \."\n ".g:atp_imap_leader_1."a \\alpha ".g:atp_imap_leader_1."b \\beta" \."\n ".g:atp_imap_leader_1."g \\gamma ".g:atp_imap_leader_1."d \\delta" \."\n ".g:atp_imap_leader_1."e \\epsilon ".g:atp_imap_leader_1."ve \\varepsilon" \."\n ".g:atp_imap_leader_1."z \\zeta ".g:atp_imap_leader_1."h \\eta" \."\n ".g:atp_imap_leader_1."o \\theta ".g:atp_imap_leader_1."vo \\vartheta" \."\n ".g:atp_imap_leader_1."i \\iota ".g:atp_imap_leader_1."k \\kappa" \."\n ".g:atp_imap_leader_1."l \\lambda ".g:atp_imap_leader_1."m \\mu" \."\n ".g:atp_imap_leader_1."n \\nu ".g:atp_imap_leader_1."x \\xi" \."\n ".g:atp_imap_leader_1."p \\pi ".g:atp_imap_leader_1."r \\rho" \."\n ".g:atp_imap_leader_1."s \\sigma ".g:atp_imap_leader_1."vs \\varsigma" \."\n ".g:atp_imap_leader_1."t \\tau ".g:atp_imap_leader_1."u \\upsilon" \."\n ".g:atp_imap_leader_1."f \\phi ".g:atp_imap_leader_1."c \\chi" \."\n ".g:atp_imap_leader_1."y \\psi ".g:atp_imap_leader_1."w \\omega" \."\n" \."\n ".g:atp_imap_leader_1."G \\Gamma ".g:atp_imap_leader_1."D \\Delta" \."\n ".g:atp_imap_leader_1."Z \\mathrm{Z} ".g:atp_imap_leader_1."O \\Theta" \."\n ".g:atp_imap_leader_1."L \\Lambda ".g:atp_imap_leader_1."M \\Mu" \."\n ".g:atp_imap_leader_1."N \\Nu ".g:atp_imap_leader_1."P \\Pi" \."\n ".g:atp_imap_leader_1."S \\Sigma ".g:atp_imap_leader_1."U \\Upsilon" \."\n ".g:atp_imap_leader_1."F \\Phi ".g:atp_imap_leader_1."Y \\Psi" \."\n ".g:atp_imap_leader_1."W \\Omega" \."\n" \."\n ".g:atp_imap_leader_1."+ \\bigcup ".g:atp_imap_leader_1."- \\setminus" \."\n ".g:atp_infty_leader."8 \\infty ".g:atp_imap_leader_1."& \\wedge" \."\n ". "^^ ^{} ". "__ _{}" \."\n ".g:atp_imap_leader_3."m \\(\\) ".g:atp_imap_leader_3."M \\[\\] has value g:atp_imap_leader_3" return g:help_mathimaps endfunction silent call atplib#helpfunctions#HelpMathIMaps() " {{{1 Help Environment IMAPS function! atplib#helpfunctions#HelpEnvIMaps() if exists("g:no_plugin_maps") || exists("g:no_atp_maps") echomsg "[ATP:] ATP maps are turned off" return '' endif let g:help_envimaps = '' \."\n ENVIRONMENT IMAPS" \."\n has value g:atp_imap_leader_3" \."\n ".(g:atp_imap_begin != "" ? g:atp_imap_leader_3.g:atp_imap_begin." \\begin{} " : "" ).(g:atp_imap_end != "" ? g:atp_imap_leader_3.g:atp_imap_end." \\end{}" : "") \."\n ".(g:atp_imap_theorem != "" ? g:atp_imap_leader_3.g:atp_imap_theorem." theorem " : "" ).(g:atp_imap_definition != "" ? g:atp_imap_leader_3.g:atp_imap_definition." definition" : "") \."\n ".(g:atp_imap_proposition != "" ? g:atp_imap_leader_3.g:atp_imap_proposition." proposition " : "").(g:atp_imap_lemma != "" ? g:atp_imap_leader_3.g:atp_imap_lemma." lemma" : "") \."\n ".(g:atp_imap_remark != "" ? g:atp_imap_leader_3.g:atp_imap_remark." remark " : "").(g:atp_imap_corollary != "" ? g:atp_imap_leader_3.g:atp_imap_corollary." corollary" : "") \."\n ".(g:atp_imap_proof != "" ? g:atp_imap_leader_3.g:atp_imap_proof." proof " : "").(g:atp_imap_example != "" ? g:atp_imap_leader_3.g:atp_imap_example." example" : "") \."\n ".(g:atp_imap_note != "" ? g:atp_imap_leader_3.g:atp_imap_note." note " : "") \."\n" \."\n ".(g:atp_imap_enumerate != "" ? g:atp_imap_leader_3.g:atp_imap_enumerate." enumerate " : "").(g:atp_imap_itemize != "" ? g:atp_imap_leader_3.g:atp_imap_itemize." itemize" : "") \."\n ".(g:atp_imap_item != "" ? g:atp_imap_leader_3.g:atp_imap_item." \\item" : "") \."\n" \.(g:atp_imap_align != "" ? "\n ".g:atp_imap_leader_3.g:atp_imap_align." align " : "").(g:atp_imap_equation != "" ? g:atp_imap_leader_3.g:atp_imap_equation." equation" : "") \."\n" \."\n ".(g:atp_imap_flushleft != "" ? g:atp_imap_leader_3.g:atp_imap_flushleft." flushleft " : "").(g:atp_imap_flushright != "" ? g:atp_imap_leader_3.g:atp_imap_flushright." flushright" : "") \."\n ".(g:atp_imap_center != "" ? g:atp_imap_leader_3.g:atp_imap_center." center" : "") \."\n" \.(g:atp_imap_tikzpicture != "" ? "\n ".g:atp_imap_leader_3.g:atp_imap_tikzpicture." tikzpicture" : "") \."\n" \."\n ".(g:atp_imap_frame != "" ? g:atp_imap_leader_3.g:atp_imap_frame." frame " : "").(g:atp_imap_letter != "" ? g:atp_imap_leader_3.g:atp_imap_letter." letter" : "" ) return g:help_envimaps endfunction " {{{1 Help VMaps function! atplib#helpfunctions#HelpVMaps() if exists("g:no_plugin_maps") || exists("g:no_atp_maps") echomsg "[ATP:] ATP maps are turned off" return '' endif let l:atp_vmap_text_font_leader = ( exists("maplocalleader") && g:atp_vmap_text_font_leader == "" ? maplocalleader : g:atp_vmap_text_font_leader ) let l:atp_vmap_environment_leader = ( exists("maplocalleader") && g:atp_vmap_environment_leader == "" ? maplocalleader : g:atp_vmap_environment_leader ) let l:atp_vmap_bracket_leader = ( exists("maplocalleader") && g:atp_vmap_bracket_leader == "" ? maplocalleader : g:atp_vmap_bracket_leader ) let l:atp_vmap_big_bracket_leader = ( exists("maplocalleader") && g:atp_vmap_big_bracket_leader =~ "" ? substitute(g:atp_vmap_big_bracket_leader, '', maplocalleader, '') : g:atp_vmap_big_bracket_leader ) let g:help_vmaps = '' \."\n has value g:atp_vmap_text_font_leader" \."\n KEYMAP TEXT MODE MATH MODE" \."\n ".l:atp_vmap_text_font_leader."rm \\textrm{} \\mathrm{}" \."\n ".l:atp_vmap_text_font_leader."em \\emph{} \\mathit{}" \."\n ".l:atp_vmap_text_font_leader."it \\textit{} \\mathit{}" \."\n ".l:atp_vmap_text_font_leader."sf \\textsf{} \\mathsf{}" \."\n ".l:atp_vmap_text_font_leader."tt \\texttt{} \\mathtt{}" \."\n ".l:atp_vmap_text_font_leader."bf \\textbf{} \\mathbf{}" \."\n ".l:atp_vmap_text_font_leader."bb \\textbf{} \\mathbb{}" \."\n ".l:atp_vmap_text_font_leader."bb \\textbf{} \\mathbb{}" \."\n ".l:atp_vmap_text_font_leader."sl \\textsl{}" \."\n ".l:atp_vmap_text_font_leader."sc \\textsc{}" \."\n ".l:atp_vmap_text_font_leader."up \\textup{}" \."\n ".l:atp_vmap_text_font_leader."md \\textmd{}" \."\n ".l:atp_vmap_text_font_leader."un \\underline{} \\underline{}" \."\n ".l:atp_vmap_text_font_leader."ov \\overline{} \\overline{}" \."\n ".l:atp_vmap_text_font_leader."no \\textnormal{} \\mathnormal{}" \."\n ".l:atp_vmap_text_font_leader."cal \\mathcal{}" \."\n " \."\n MODE INDEPENDENT VMAPS:" \."\n has value g:atp_vmap_environment_leader" \."\n ".l:atp_vmap_environment_leader."C wrap in center environment" \."\n ".l:atp_vmap_environment_leader."L wrap in flushleft environment" \."\n ".l:atp_vmap_environment_leader."R wrap in flushright environment" \."\n ".l:atp_vmap_environment_leader."E wrap in equation environment" \."\n ".l:atp_vmap_environment_leader."A wrap in align environment" \."\n " \."\n has value g:atp_vmap_bracket_leader" \."\n ".l:atp_vmap_bracket_leader."( (:) ".l:atp_vmap_bracket_leader.") (:)" \."\n ".l:atp_vmap_bracket_leader."[ [:] ".l:atp_vmap_bracket_leader."] [:]" \."\n ".l:atp_vmap_bracket_leader."{ {:} ".l:atp_vmap_bracket_leader."} {:}" \."\n ".l:atp_vmap_bracket_leader."\\{ \\{:\\} ".l:atp_vmap_bracket_leader."\\} \\{:\\}" \."\n m \\(:\\) M \\[:\\] " \."\n " \."\n has value g:atp_vmap_big_bracket_leader" \."\n ".l:atp_vmap_big_bracket_leader."( \\left(:\\right) ".l:atp_vmap_big_bracket_leader.") \\left(:\\right)" \."\n ".l:atp_vmap_big_bracket_leader."[ \\left[:\\right] ".l:atp_vmap_big_bracket_leader."] \\left[:\\right]" \."\n ".l:atp_vmap_big_bracket_leader."{ \\left{:\\right} ".l:atp_vmap_big_bracket_leader."} \\left{:\\right}" \."\n ".l:atp_vmap_big_bracket_leader."\\{ \\left\\{:\\right\\} ".l:atp_vmap_big_bracket_leader."\\} \\left\\{:\\right\\}" \."\n " \."\n ".l:atp_vmap_text_font_leader."f \\usefont{".g:atp_font_encoding."}{}{}{}\\selectfont" return g:help_vmaps endfunction " {{{1 Help IMaps " function! atplib#helpfunctions#HelpIMaps() " let tc_imap = maparg(" ", 'i') =~# 'atplib#complete#TabCompletion' ? '' : " \ maparg(" ", 'i') =~# 'atplib#complete#TabCompletion' ? '' : "" " let netc_imap = tc_imap == "" ? "" : tc_imap == "" ? "" : "" " let g:help_imaps = '' " \."\n has value g:atp_vmap_text_font_leader" " \."\n ".tc_imap." "."Completion (expert mode)" " \."\n ".netc_imap." "."Completion (non-expert mode)" " endfunction " silent call atplib#helpfunctions#HelpIMaps() " command! -buffer HelpIMaps :echo atplib#helpfunctions#HelpIMaps() " }}}1 function! atplib#helpfunctions#MapSearch(bang,rhs_pattern,...) let mode = ( a:0 >= 1 ? a:1 : '' ) let more = &more setl nomore redir => maps exe "silent ".mode."map" redir end let &l:more = more let list = split(maps, "\n") let rhs_list = ( a:bang == "" ? map(copy(list), 'matchstr(v:val, ''.\s\+\S\+\s\+\zs.*'')') : \ map(copy(list), 'matchstr(v:val, ''.\s\+\zs\S\+\s\+.*'')') ) if a:bang == "!" let pure_rhs_list = map(copy(list), 'matchstr(v:val, ''.\s\+\S\+\s\+\zs.*'')') else let pure_rhs_list = rhs_list endif if mode == 'i' let j=0 for entry in g:atp_imap_greek_letters \ +g:atp_imap_math_misc \ +g:atp_imap_diacritics \ +g:atp_imap_environments \ +g:atp_imap_math \ +g:atp_imap_fonts let entry_tab = substitute(entry[4], "\t", '', 'g') let entry_tab = substitute(entry_tab, "", '', 'g') if index(pure_rhs_list, entry_tab) == -1 && \ index(pure_rhs_list, "*".entry_tab) == -1 && \ index(pure_rhs_list, "@".entry_tab) == -1 && \ index(pure_rhs_list, "*@".entry_tab) == -1 " Debug: let j+=1 let space = join(map(range(max([12-len(entry[2].entry[3]),1])), "' '"), "") call add(list, 'i '.entry[2].entry[3].space.entry_tab) if a:bang == "" call add(rhs_list, entry_tab) else call add(rhs_list, 'i '.entry[2].entry[3].space.entry_tab) endif endif endfor endif let i = 0 let i_list = [] for rhs in rhs_list if rhs =~? a:rhs_pattern call add(i_list, i) endif let i+=1 endfor let found_maps = [] for i in i_list call add(found_maps, list[i]) endfor if len(found_maps) > 0 echo join(found_maps, "\n") else echohl WarningMsg echo "No such map" echohl None endif endfunction " vim:fdm=marker:tw=85:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/motion.vim [[[1 1795 " Author: Marcin Szamotulski " Description: This file contains motion and highlight functions of ATP. " Note: This file is a part of Automatic Tex Plugin for Vim. " Language: tex " Last Change: " All table of contents stuff: variables, functions and commands. " {{{1 Table Of Contents "--Make TOC ----------------------------- " This makes sense only for latex documents. " " Notes: Makeing toc from aux file: " + is fast " + one gets correct numbers " - one doesn't get line numbers " / the title might be modified thus one can not make a pattern " which works in all situations, while this is important for " :DeleteSection command / " " {{{2 atplib#motion#find_toc_lines function! atplib#motion#find_toc_lines() let toc_lines_nr=[] let toc_lines=[] let pos_saved=getpos(".") let pos=[0,1,1,0] keepjumps call setpos(".",pos) " Pattern: let j=0 for section in keys(g:atp_sections) if j == 0 let pattern=g:atp_sections[section][0] . '' else let pattern=pattern . '\|' . g:atp_sections[section][0] endif let j+=1 endfor " Searching Loop: let line=search(pattern, 'W') while line call add(toc_lines_nr, line) let line=search(pattern, 'W') endwhile keepjumps call setpos(".", pos_saved) for line in toc_lines_nr call add(toc_lines, getline(line)) endfor return toc_lines endfunction " {{{2 atplib#motion#maketoc " this will store information: " { 'linenumber' : ['chapter/section/..', 'sectionnumber', 'section title', '0/1=not starred/starred'] } function! atplib#motion#maketoc(filename) let toc={} " if the dictinary with labels is not defined, define it if !exists("t:atp_labels") let t:atp_labels = {} endif let texfile = [] " getbufline reads only loaded buffers, unloaded can be read from file. let bufname = fnamemodify(a:filename,":t") try let texfile = ( bufexists(bufname) ? getbufline("^" . bufname . "$","1","$") : readfile(a:filename) ) catch /E484:/ echohl Warning echo "File " . a:filename . " not readable." echohl None endtry let texfile_copy = deepcopy(texfile) let true = 1 let bline = 0 " We are not removing the preambule any more. let i = 1 " set variables for chapter/section numbers for section in keys(g:atp_sections) let ind{section} = 0 endfor " make a filter let j = 0 let biblatex = ( atplib#search#SearchPackage("biblatex") ) " When \usepackge{biblatex} do not search for \bibliography{} commands -- they are placed in ther preambule. let key_list = ( biblatex ? filter(keys(g:atp_sections), "v:val != 'bibliography'") : keys(g:atp_sections) ) for section in key_list let filter = ( j == 0 ? g:atp_sections[section][0] . '' : filter . '\|' . g:atp_sections[section][0] ) let j+=1 endfor let s:filtered = filter(deepcopy(texfile), 'v:val =~ filter') let line_number = -1 for line in s:filtered let line_number+=1 for section in keys(g:atp_sections) if line =~ g:atp_sections[section][0] if line !~ '^\s*\\\@ empty set, but with " \chapter{title} --> title, solution: the name of " 'Abstract' will be plased, as we know what we have " matched let title = line " This is an attempt to join consecutive lines iff the title is spanned " through more than one line. " s:filtered doesn't is not the same as texfile!!! " we should use texfile, but for this we need to know the true line numbers, " they should be around though. " let open=count(split(title, '\zs'), '{') " let closed=count(split(title, '\zs'), '}') " let i=0 " if open!=closed " echomsg "XXXXXXX" " echomsg title " endif " while open!=closed && line_number+i+2<=len(s:filtered) " echomsg i." ".s:filtered[line_number+i] " let i+=1 " let open+=count(split(s:filtered[line_number+i], '\zs'), '{') " let closed+=count(split(s:filtered[line_number+i], '\zs'), '}') " let title.=" ".substitute(s:filtered[line_number+i], '^\s*', '', '') " endwhile " test if it is a starred version. let star=0 if g:atp_sections[section][1] != 'nopattern' && line =~ g:atp_sections[section][1] let star=1 else let star=0 endif " Problem: If there are two sections with the same title, this " does't work: let idx = index(texfile,line) call remove(texfile, idx) let i = idx let tline = i+bline+1 let bline +=1 " Find Title: let start = stridx(title,'{')+1 let title = strpart(title,start) " we are looking for the maching '}' let l:count = 1 let i=-1 while i<=len(title) let i+=1 if strpart(title,i,1) == '{' let l:count+=1 elseif strpart(title,i,1) == '}' let l:count-=1 endif if l:count == 0 break endif endwhile let title = strpart(title,0,i) let title = substitute(title, '[{}]\|\\titlefont\|\\hfill\=\|\\hrule\|\\[vh]space\s*{[^}]\+}', '', 'g') " Section Number: " if it is not starred version add one to the section number " or it is not an abstract if star == 0 if !(section == 'chapter' && title =~ '^\cabstract$') let ind{section}+=1 endif endif if section == 'part' let indchapter = 0 let indsection = 0 let indsubsection = 0 let indsubsubsection = 0 elseif section == 'chapter' let indsection = 0 let indsubsection = 0 let indsubsubsection = 0 elseif section == 'section' || section == 'frame' let indsubsection = 0 let indsubsubsection = 0 elseif section == 'subsection' let indsubsubsection = 0 endif " Find Short Title: let shorttitle=line let start=stridx(shorttitle,'[')+1 if start == 0 let shorttitle='' else let shorttitle=strpart(shorttitle,start) " we are looking for the maching ']' let l:count=1 let i=-1 while i<=len(shorttitle) let i+=1 if strpart(shorttitle,i,1) == '[' let l:count+=1 elseif strpart(shorttitle,i,1) == ']' let l:count-=1 endif if l:count==0 break endif endwhile let shorttitle = strpart(shorttitle,0,i) endif "ToDo: if section is bibliography (using bib) then find the first " empty line: if section == "bibliography" && line !~ '\\begin\s*{\s*thebibliography\s*}' && !biblatex let idx = tline-1 while texfile_copy[idx] !~ '^\s*$' let idx-= 1 endwhile " " We add 1 as we want the first non blank line, and one more " " 1 as we want to know the line number not the list index " " number: let tline=idx+1 endif " Add results to the dictionary: if biblatex && section != "bibliography" || !biblatex call extend(toc, { tline : [ section, ind{section}, title, star, shorttitle] }) endif endif endif endfor endfor " if exists("t:atp_toc") " call extend(t:atp_toc, { a:filename : toc }, "force") " else " let t:atp_toc = { a:filename : toc } " endif " return t:atp_toc return { a:filename : toc } endfunction " {{{2 atplib#motion#buflist if !exists("t:atp_toc_buflist") let t:atp_toc_buflist=[] endif function! atplib#motion#buflist() " this names are used in TOC and passed to atplib#motion#maketoc, which " makes a dictionary whose keys are the values of name defined " just below: if !exists("t:atp_toc_buflist") let t:atp_toc_buflist = [] endif let name=resolve(fnamemodify(bufname("%"),":p")) " add an entry to the list t:atp_toc_buflist if it is not there. if bufname("") =~ ".tex" && index(t:atp_toc_buflist,name) == -1 call add(t:atp_toc_buflist,name) endif return t:atp_toc_buflist endfunction " {{{2 tplib#motion#RemoveFromBufList function! atplib#motion#RemoveFromToC(file) if a:file == "" let g:debug = 1 if exists("b:atp_MainFile") let list = filter(copy(t:atp_toc_buflist), "v:val != fnamemodify(b:atp_MainFile, ':p')") else let list = copy(t:atp_toc_buflist) endif if len(list) >= 2 let i=1 for f in list echo "(" . i . ") " . f let i+=1 endfor let which=input("Which file to remove (press for none)") if which == "" let g:debug=3 return endif let which=t:atp_toc_buflist[which-1] elseif exists("b:atp_MainFile") && len(list) == 1 let which=get(list,0,"") else return endif else let which = fnamemodify(a:file, ":p") endif if which != "" silent! call remove(t:atp_toc_buflist,index(t:atp_toc_buflist, which)) silent! call remove(t:atp_toc,which) endif let winnr=winnr() if index(map(tabpagebuflist(), 'bufname(v:val)'), '__ToC__') != -1 call atplib#motion#TOC("!", 0) endif exe winnr."wincmd w" endfunction function! atplib#motion#RemoveFromToCComp(A, B, C) return join(t:atp_toc_buflist,"\n") endfunction " {{{2 atplib#motion#showtoc function! atplib#motion#showtoc(toc) " this is a dictionary of line numbers where a new file begins. let cline=line(".") " " Open new window or jump to the existing one. " " Remember the place from which we are coming: " let t:atp_bufname=bufname("") " let t:atp_winnr=winnr() these are already set by TOC() let bname="__ToC__" let tocwinnr=bufwinnr(bufnr("^".bname."$")) if tocwinnr != -1 " Jump to the existing window. exe tocwinnr . " wincmd w" silent exe "%delete _" else " Open new window if its width is defined (if it is not the code below " will put toc in the current buffer so it is better to return. if !exists("t:toc_window_width") let t:toc_window_width = g:atp_toc_window_width endif let toc_winnr=bufwinnr(bufnr("__Labels__")) if toc_winnr == -1 let openbuffer="keepalt " . t:toc_window_width . "vsplit +setl\\ wiw=15\\ buftype=nowrite\\ nobuflisted\\ tabstop=1\\ filetype=toc_atp\\ nowrap __ToC__" else exe toc_winnr."wincmd w" let l:openbuffer= "keepalt above split +setl\\ buftype=nowrite\\ nobuflisted\\ tabstop=1\\ filetype=toc_atp\\ nowrap __ToC__" endif keepalt silent exe openbuffer " We are setting the address from which we have come. silent call atplib#setwindow() endif let number=1 " this is the line number in ToC. " number is a line number relative to the file listed in ToC. " the current line number is linenumber+number " there are two loops: one over linenumber and the second over number. let numberdict = {} let s:numberdict = numberdict unlockvar b:atp_Toc let b:atp_Toc = {} " this variable will be used to set the cursor position in ToC. for openfile in keys(a:toc) call extend(numberdict, { openfile : number }) let part_on=0 let chap_on=0 let chnr=0 let secnr=0 let ssecnr=0 let sssecnr=0 let path=fnamemodify(bufname(""),":p:h") for line in keys(a:toc[openfile]) if a:toc[openfile][line][0] == 'chapter' let chap_on=1 break elseif a:toc[openfile][line][0] == 'part' let part_on=1 endif endfor let sorted = sort(keys(a:toc[openfile]), "atplib#CompareNumbers") let len = len(sorted) " write the file name in ToC (with a full path in paranthesis) call setline(number,fnamemodify(openfile,":t") . " (" . fnamemodify(openfile,":p:h") . ")") call extend(b:atp_Toc, { number : [ openfile, 1 ]}) let number+=1 for line in sorted call extend(b:atp_Toc, { number : [ openfile, line ] }) let lineidx=index(sorted,line) let nlineidx=lineidx+1 if nlineidx< len(sorted) let nline=sorted[nlineidx] else let nline=line("$") endif let lenght=len(line) if lenght == 0 let showline=" " elseif lenght == 1 let showline=" " . line elseif lenght == 2 let showline=" " . line elseif lenght == 3 let showline=" " . line elseif lenght == 4 let showline=" " . line elseif lenght>=5 let showline=line endif " Print ToC lines. if a:toc[openfile][line][0] == 'abstract' || a:toc[openfile][line][2] =~ '^\cabstract$' call setline(number, showline . "\t" . " " . "Abstract" ) elseif a:toc[openfile][line][0] =~ 'bibliography\|references' call setline (number, showline . "\t" . " " . a:toc[openfile][line][2]) elseif a:toc[openfile][line][0] == 'part' let partnr=a:toc[openfile][line][1] let nr=partnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','') endif if a:toc[openfile][line][4] != '' " call setline (number, showline . "\t" . nr . " " . a:toc[openfile][line][4]) call setline (number, showline . "\t" . " " . a:toc[openfile][line][4]) else " call setline (number, showline . "\t" . nr . " " . a:toc[openfile][line][2]) call setline (number, showline . "\t" . " " . a:toc[openfile][line][2]) endif elseif a:toc[openfile][line][0] == 'chapter' let chnr=a:toc[openfile][line][1] let nr=chnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','') endif if a:toc[openfile][line][4] != '' call setline (number, showline . "\t" . nr . " " . a:toc[openfile][line][4]) else call setline (number, showline . "\t" . nr . " " . a:toc[openfile][line][2]) endif elseif a:toc[openfile][line][0] == 'section' || a:toc[openfile][line][0] == 'frame' let secnr=a:toc[openfile][line][1] if chap_on let nr=chnr . "." . secnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','g') endif if a:toc[openfile][line][4] != '' call setline (number, showline . "\t\t" . nr . " " . a:toc[openfile][line][4]) else call setline (number, showline . "\t\t" . nr . " " . a:toc[openfile][line][2]) endif else let nr=secnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','g') endif if a:toc[openfile][line][4] != '' call setline (number, showline . "\t" . nr . " " . a:toc[openfile][line][4]) else call setline (number, showline . "\t" . nr . " " . a:toc[openfile][line][2]) endif endif elseif a:toc[openfile][line][0] == 'subsection' let ssecnr=a:toc[openfile][line][1] if chap_on let nr=chnr . "." . secnr . "." . ssecnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','g') endif if a:toc[openfile][line][4] != '' call setline (number, showline . "\t\t\t" . nr . " " . a:toc[openfile][line][4]) else call setline (number, showline . "\t\t\t" . nr . " " . a:toc[openfile][line][2]) endif else let nr=secnr . "." . ssecnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','g') endif if a:toc[openfile][line][4] != '' call setline (number, showline . "\t\t" . nr . " " . a:toc[openfile][line][4]) else call setline (number, showline . "\t\t" . nr . " " . a:toc[openfile][line][2]) endif endif elseif a:toc[openfile][line][0] == 'subsubsection' let sssecnr=a:toc[openfile][line][1] if chap_on let nr=chnr . "." . secnr . "." . sssecnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','g') endif if a:toc[openfile][line][4] != '' call setline(number, a:toc[openfile][line][0] . "\t\t\t" . nr . " " . a:toc[openfile][line][4]) else call setline(number, a:toc[openfile][line][0] . "\t\t\t" . nr . " " . a:toc[openfile][line][2]) endif else let nr=secnr . "." . ssecnr . "." . sssecnr if a:toc[openfile][line][3] "if it is stared version let nr=substitute(nr,'.',' ','g') endif if a:toc[openfile][line][4] != '' call setline (number, showline . "\t\t" . nr . " " . a:toc[openfile][line][4]) else call setline (number, showline . "\t\t" . nr . " " . a:toc[openfile][line][2]) endif endif else let nr="" endif let number+=1 endfor endfor " set the cursor position on the correct line number. " first get the line number of the begging of the ToC of t:atp_bufname " (current buffer) " let t:numberdict=numberdict "DEBUG " t:atp_bufname is the full path to the current buffer. let num = get(numberdict, t:atp_bufname, 'no_number') if num == 'no_number' " call atplib#motion#TOC("") return endif let sorted = sort(keys(a:toc[t:atp_bufname]), "atplib#CompareNumbers") let t:sorted = sorted for line in sorted if cline>=line let num+=1 endif keepjumps call setpos('.',[bufnr(""),num,1,0]) endfor " Help Lines: if search(' jump and close', 'nW') == 0 call append('$', [ '', \ '_ set', \ ' jump', \ ' jump and close', \ 's jump and split', \ 'y or c yank label', \ 'p paste label', \ 'q close', \ 'zc fold section[s]', \ ":'<,'>Fold", \ ':YankSection', \ ':DeleteSection', \ ':PasteSection[!]', \ ':SectionStack', \ ':Undo' ]) endif lockvar 3 b:atp_Toc endfunction " {{{2 atplib#motion#ToCbufnr() " This function returns toc buffer number if toc window is not open returns -1. function! atplib#motion#ToCbufnr() return index(map(tabpagebuflist(), 'bufname(v:val)'), '__ToC__') endfunction " atplib#motion#UpdateToCLine {{{2 function! atplib#motion#UpdateToCLine(...) if !g:atp_UpdateToCLine return endif let toc_bufnr = atplib#motion#ToCbufnr() let check_line = (a:0>=1 ? a:1 : -1) if toc_bufnr == -1 || check_line != -1 && \ getline(line(".")+check_line) !~# '\\\%(part\|chapter\|\%(sub\)\{0,2}section\)\s*{' return endif let cline = line(".") let cbufnr = bufnr("") let cwinnr = bufwinnr("") exe toc_bufnr."wincmd w" let num = get(s:numberdict, t:atp_bufname, 'no_number') if num == 'no_number' exe cwinnr."wincmd w" return endif let sorted = sort(keys(t:atp_toc[t:atp_bufname]), "atplib#CompareNumbers") for line in sorted if cline>=line let num+=1 endif keepjumps call setpos('.',[bufnr(""),num,1,0]) call atplib#tools#CursorLine() endfor let eventignore=&eventignore set eventignore+=BufEnter exe cwinnr."wincmd w" let &eventignore=eventignore endfunction " This is User Front End Function " atplib#motion#TOC {{{2 function! atplib#motion#TOC(bang,...) " skip generating t:atp_toc list if it exists and if a:0 != 0 if &l:filetype != 'tex' && &l:filetype != 'toc_atp' echoerr "Wrong 'filetype'. This command works only for latex documents." return endif if a:0 == 0 call atplib#motion#buflist() endif " for each buffer in t:atp_toc_buflist (set by atplib#motion#buflist) if ( a:bang == "!" || !exists("t:atp_toc") ) let t:atp_toc = {} for buffer in t:atp_toc_buflist " let b:atp_toc=atplib#motion#maketoc(buffer) call extend(t:atp_toc, atplib#motion#maketoc(buffer)) endfor endif call atplib#motion#showtoc(t:atp_toc) endfunction nnoremap ATP_TOC :call atplib#motion#TOC("") " This finds the name of currently eddited section/chapter units. " {{{2 atplib#motion#NearestSection " This function finds the section name of the current section unit with " respect to the dictionary a:section={ 'line number' : 'section name', ... } " it returns the [ section_name, section line, next section line ] function! atplib#motion#NearestSection(section) let cline=line('.') let sorted=sort(keys(a:section), "atplib#CompareNumbers") let x=0 while x=1 && x < len(sorted) let section_name=a:section[sorted[x-1]] return [section_name, sorted[x-1], sorted[x]] elseif x>=1 && x >= len(sorted) let section_name=a:section[sorted[x-1]] return [section_name,sorted[x-1], line('$')] elseif x<1 && x < len(sorted) " if we are before the first section return the empty string return ['','0', sorted[x]] elseif x<1 && x >= len(sorted) return ['', '0', line('$')] endif endfunction " {{{2 atplib#motion#ctoc function! atplib#motion#ctoc() if &l:filetype != 'tex' " TO DO: " if exists(g:tex_flavor) " if g:tex_flavor != "latex" " echomsg "CTOC: Wrong 'filetype'. This function works only for latex documents." " endif " endif " Set the status line once more, to remove the CTOC() function. call ATPStatus(0,0) return [] endif " resolve the full path: let t:atp_bufname=resolve(fnamemodify(bufname("%"),":p")) " if t:atp_toc(t:atp_bufname) exists use it otherwise make it if !exists("t:atp_toc") || !has_key(t:atp_toc, t:atp_bufname) if !exists("t:atp_toc") let t:atp_toc={} endif silent call extend(t:atp_toc, atplib#motion#maketoc(t:atp_bufname)) endif " l:count where the preambule ends let buffer=getbufline(bufname("%"),"1","$") let i=0 let line=buffer[0] while line !~ '\\begin\s*{document}' && i < len(buffer) let line=buffer[i] if line !~ '\\begin\s*{document}' let i+=1 endif endwhile " if we are before the '\\begin{document}' line: if line(".") <= i let return=['Preambule'] return return endif let chapter={} let section={} let subsection={} for key in keys(t:atp_toc[t:atp_bufname]) if t:atp_toc[t:atp_bufname][key][0] == 'chapter' " return the short title if it is provided if t:atp_toc[t:atp_bufname][key][4] != '' call extend(chapter, {key : t:atp_toc[t:atp_bufname][key][4]},'force') else call extend(chapter, {key : t:atp_toc[t:atp_bufname][key][2]},'force') endif elseif t:atp_toc[t:atp_bufname][key][0] == 'section' " return the short title if it is provided if t:atp_toc[t:atp_bufname][key][4] != '' call extend(section, {key : t:atp_toc[t:atp_bufname][key][4]},'force') else call extend(section, {key : t:atp_toc[t:atp_bufname][key][2]},'force') endif elseif t:atp_toc[t:atp_bufname][key][0] == 'subsection' " return the short title if it is provided if t:atp_toc[t:atp_bufname][key][4] != '' call extend(subsection, {key : t:atp_toc[t:atp_bufname][key][4]},'force') else call extend(subsection, {key : t:atp_toc[t:atp_bufname][key][2]},'force') endif endif endfor " Remove $ from chapter/section/subsection names to save the space. let chapter_name=substitute(atplib#motion#NearestSection(chapter)[0],'\$\|\\(\|\\)','','g') let chapter_line=atplib#motion#NearestSection(chapter)[1] let chapter_nline=atplib#motion#NearestSection(chapter)[2] let section_name=substitute(atplib#motion#NearestSection(section)[0],'\$\|\\(\|\\)','','g') let section_line=atplib#motion#NearestSection(section)[1] let section_nline=atplib#motion#NearestSection(section)[2] " let b:section=atplib#motion#NearestSection(section) " DEBUG let subsection_name=substitute(atplib#motion#NearestSection(subsection)[0],'\$\|\\(\|\\)','','g') let subsection_line=atplib#motion#NearestSection(subsection)[1] let subsection_nline=atplib#motion#NearestSection(subsection)[2] " let b:ssection=atplib#motion#NearestSection(subsection) " DEBUG let names = [ chapter_name ] if (section_line+0 >= chapter_line+0 && section_line+0 <= chapter_nline+0) || chapter_name == '' call add(names, section_name) elseif subsection_line+0 >= section_line+0 && subsection_line+0 <= section_nline+0 call add(names, subsection_name) endif return names endfunction " Labels Front End Finction. The search engine/show function are in autoload/atplib.vim script " library. " {{{1 atplib#motion#Labels " a:bang = "!" do not regenerate labels if not necessary function! atplib#motion#Labels(bang) let t:atp_bufname = bufname("%") let error = ( exists("b:atp_TexReturnCode") ? b:atp_TexReturnCode : 0 ) let atp_MainFile = atplib#FullPath(b:atp_MainFile) " Generate the dictionary with labels if a:bang == "" || ( a:bang == "!" && !exists("t:atp_labels") ) || \ ( a:bang == "!" && exists("t:atp_labels") && get(t:atp_labels, atp_MainFile, []) == [] ) let [ t:atp_labels, b:ListOfFiles ] = atplib#tools#generatelabels(atp_MainFile, 1) endif " Show the labels in seprate window call atplib#tools#showlabels([ t:atp_labels, map(extend([b:atp_MainFile], copy(b:ListOfFiles)), 'atplib#FullPath(v:val)')]) if error echohl WarningMsg redraw echomsg "[ATP:] the compelation contains errors, aux file might be not appriopriate for labels window." echohl None endif endfunction nnoremap ATP_Labels :call atplib#motion#Labels("") " atplib#motion#GotoLabel {{{1 " a:bang = "!" do not regenerate labels if not necessary " This is developed for one tex project in a vim. function! atplib#motion#GotoLabel(bang,...) let alabel = ( a:0 == 0 ? "" : a:1 ) let atp_MainFile = atplib#FullPath(b:atp_MainFile) " Generate the dictionary with labels if a:bang == "" || ( a:bang == "!" && ( !exists("b:ListOfFiles") || !exists("t:atp_labels") ) ) let [ t:atp_labels, b:ListOfFiles ] = atplib#tools#generatelabels(atp_MainFile, 1) endif let matches = [] for file in keys(t:atp_labels) if index(b:ListOfFiles, fnamemodify(file, ":t")) != -1 || index(b:ListOfFiles, file) != -1 || file == atplib#FullPath(b:atp_MainFile) for label in t:atp_labels[file] if label[1] =~ alabel || label[2] =~ '^'.alabel call add(matches, extend([file], label)) endif endfor endif endfor if len(matches) == 0 redraw echohl WarningMsg echomsg "[ATP:] no matching label" echohl None return 1 elseif len(matches) == 1 let file=matches[0][0] let line=matches[0][1] else " if len(keys(filter(copy(b:TypeDict), 'v:val == "input"'))) == 0 let mlabels=map(copy(matches), "[(index(matches, v:val)+1).'.', v:val[2],v:val[3]]") " else " Show File from which label comes " The reason to not use this is as follows: " it only matters for project files, which probably have many " labels, so it's better to make the list as concise as possible " let mlabels=map(copy(matches), "[(index(matches, v:val)+1).'.', v:val[2], v:val[3], fnamemodify(v:val[0], ':t')]") " let file=1 " endif echohl Title echo "Which label to choose?" echohl None " let mlabels= ( file ? extend([[' nr', 'LABEL', 'LABEL NR', 'FILE']], mlabels) : extend([[' nr', 'LABEL', 'LABEL NR']], mlabels) ) let g:mlabels=copy(mlabels) for row in atplib#FormatListinColumns(atplib#Table(mlabels, [1,2]),2) echo join(row) endfor let nr = input("Which label to choose? type number and press ")-1 if nr < 0 || nr >= len(matches) return endif let file=matches[nr][0] let line=matches[nr][1] endif " Check if the buffer is loaded. if bufloaded(file) execute "b " . file call cursor(line,1) else execute "edit " . file call cursor(line,1) endif endfunction " atplib#motion#GotoLabelCompletion {{{1 function! atplib#motion#GotoLabelCompletion(ArgLead, CmdLine, CursorPos) let atp_MainFile = atplib#FullPath(b:atp_MainFile) " Generate the dictionary with labels (only if it doesn't exist) if !exists("t:atp_labels") || t:atp_labels == {} || !exists("b:ListOfFiles") || a:CmdLine !~# '^GotoLabel!' let [ t:atp_labels, b:ListOfFiles ] = atplib#tools#generatelabels(atp_MainFile, 1) " It would be nice to delete the ! from the cmdline after this step. There are " only getcmdline(), getcmdpos() and setcmdpos() functions available. let cmd_line=substitute(getcmdline(), "GotoLabel!", "GotoLabel", "") endif let labels=[] for file in keys(t:atp_labels) if index(b:ListOfFiles, fnamemodify(file, ":t")) != -1 || index(b:ListOfFiles, file) != -1 || file == atplib#FullPath(b:atp_MainFile) call extend(labels, map(deepcopy(t:atp_labels)[file], 'v:val[1]')) call extend(labels, map(deepcopy(t:atp_labels)[file], 'v:val[2]')) endif endfor let g:labels=copy(labels) call filter(labels, "v:val !~ '^\s*$' && v:val =~ a:ArgLead ") return map(labels, "v:val.'\\>'") endfunction " atplib#motion#LatexTags {{{1 function! atplib#motion#LatexTags(bang) let hyperref_cmd = ( atplib#search#SearchPackage("hyperref") ? " --hyperref " : "" ) if has("clientserver") let servername = " --servername ".v:servername." " let progname = " --progname ".v:progname." " else let servername = "" let progname = "" endif let bibtags = ( a:bang == "" ? " --bibtags " : "" ) " Write file (disable project file): let project=b:atp_ProjectScript let b:atp_ProjectScript=0 silent! write let b:atp_ProjectScript=project let latextags=split(globpath(&rtp, "ftplugin/ATP_files/latextags.py"), "\n")[0] let files=join( \ map([b:atp_MainFile]+filter(copy(keys(b:TypeDict)), "b:TypeDict[v:val] == 'input'"), \ 'atplib#FullPath(v:val)') \ , ";") if len(filter(copy(keys(b:TypeDict)), "b:TypeDict[v:val] == 'bib'")) >= 1 let bibfiles=join(filter(copy(keys(b:TypeDict)), "b:TypeDict[v:val] == 'bib'"), ";") let bib= " --bibfiles ".shellescape(bibfiles) else let bib= " --bibtags_env " endif let dir = expand("%:p:h") if atplib#search#SearchPackage("biblatex") let cite = " --cite biblatex " elseif atplib#search#SearchPackage("natbib") let cite = " --cite natbib " else let cite = " " endif let cmd=g:atp_Python." ".shellescape(latextags). \ " --files ".shellescape(files). \ " --auxfile ".shellescape(fnamemodify(atplib#FullPath(b:atp_MainFile), ":r").".aux"). \ " --dir ".shellescape(dir). \ bib . cite . \ hyperref_cmd . servername . progname . bibtags . " &" if g:atp_debugLatexTags let g:cmd=cmd endif call system(cmd) endfunction "{{{1 atplib#motion#GotoDestination function! atplib#motion#GotoNamedDestination(destination) if b:atp_Viewer !~ '^\s*xpdf\>' echomsg "[ATP:] this only works with Xpdf viewer." return 0 endif let cmd='xpdf -remote '.b:atp_XpdfServer.' -exec gotoDest\("'.a:destination.'"\)' call system(cmd) endfunction function! atplib#motion#FindDestinations() let files = [ b:atp_MainFile ] if !exists("b:TypeDict") call TreeOfFiles(b:atp_MainFile) endif for file in keys(b:TypeDict) if b:TypeDict[file] == 'input' call add(files, file) endif endfor let saved_loclist = getloclist(0) exe 'lvimgrep /\\hypertarget\>/gj ' . join(map(files, 'fnameescape(v:val)'), ' ') let dests = [] let loclist = copy(getloclist(0)) let g:loclist = loclist call setloclist(0, saved_loclist) for loc in loclist let destname = matchstr(loc['text'], '\\hypertarget\s*{\s*\zs[^}]*\ze}') call add(dests, destname) endfor return dests endfunction function! atplib#motion#CompleteDestinations(ArgLead, CmdLine, CursorPos) let dests=atplib#motion#FindDestinations() return join(dests, "\n") endfunction " Motion functions through environments and sections. " atplib#motion#GotoEnvironment {{{1 " which name is given as the argument. Do not wrap " around the end of the file. function! atplib#motion#GotoEnvironment(flag,count,...) " Options : let env_name = ( a:0 >= 1 && a:1 != "" ? a:1 : '[^}]*' ) if env_name == 'part' if a:flag =~ 'b' exe a:count.'PPart' return else exe a:count.'NPart' return endif elseif env_name == 'chapter' if a:flag =~ 'b' exe a:count.'PChap' return else exe a:count.'NChap' return endif elseif env_name == 'section' if a:flag =~ 'b' exe a:count.'PSec' return else exe a:count.'NSec' return endif elseif env_name == 'subsection' if a:flag =~ 'b' exe a:count.'PSSec' return else exe a:count.'NSSec' return endif elseif env_name == 'subsubsection' if a:flag =~ 'b' exe a:count.'PSSSec' return else exe a:count.'NSSSec' return endif endif let flag = a:flag " Set the search tool : " Set the pattern : if env_name == 'math' let pattern = '\m\%(\(\\\@ 1 " the 's' flag should be used only in the first search. let flag=substitute(flag, 's', '', 'g') endif if g:atp_mapNn let search_cmd = "S /" let search_cmd_e= "/ " . flag else let search_cmd = "silent! call search('" let search_cmd_e= "','" . flag . "')" endif execute search_cmd . pattern . search_cmd_e if a:flag !~# 'b' if getline(".")[col(".")-1] == "$" if ( get(split(getline("."), '\zs'), col(".")-1, '') == "$" && get(split(getline("."), '\zs'), col("."), '') == "$" ) "check $$ let rerun = !atplib#complete#CheckSyntaxGroups(['texMathZoneY'], line("."), col(".")+1 ) elseif get(split(getline("."), '\zs'), col(".")-1, '') == "$" "check $ let rerun = !atplib#complete#CheckSyntaxGroups(['texMathZoneX', 'texMathZoneY'], line("."), col(".") ) endif if rerun silent! execute search_cmd . pattern . search_cmd_e endif endif else " a:flag =~# 'b' if getline(".")[col(".")-1] == "$" if ( get(split(getline("."), '\zs'), col(".")-1, '') == "$" && get(split(getline("."), '\zs'), col(".")-2, '') == "$" ) "check $$ let rerun = atplib#complete#CheckSyntaxGroups(['texMathZoneY'], line("."), col(".")-3 ) elseif get(split(getline("."), '\zs'), col(".")-1, '') == "$" "check $ let rerun = atplib#complete#CheckSyntaxGroups(['texMathZoneX', 'texMathZoneY'], line("."), col(".")-2 ) endif if rerun silent! execute search_cmd . pattern . search_cmd_e endif endif endif endfor call atplib#motion#UpdateToCLine() silent! call histadd("search", pattern) silent! let @/ = pattern return "" endfunction " atplib#motion#GotoFrame {{{1 function! atplib#motion#GotoFrame(f, count) let g:Count=a:count let lz=&lazyredraw set lazyredraw if a:f == "backward" call atplib#motion#GotoEnvironment('bsW', a:count, 'frame') else call atplib#motion#GotoEnvironment('sW', a:count, 'frame') endif normal! zt let &lz=lz endfunction nnoremap NextFrame :call atplib#motion#GotoFrame('forward', v:count1) nnoremap PreviousFrame :call atplib#motion#GotoFrame('backward', v:count1) " atplib#motion#JumptoEnvironment {{{1 " function! atplib#motion#GotoEnvironmentB(flag,count,...) " let env_name = (a:0 >= 1 && a:1 != "" ? a:1 : '[^}]*') " for i in range(1,a:count) " let flag = (i!=1?substitute(a:flag, 's', '', 'g'):a:flag) " call atplib#motion#GotoEnvironment(flag,1,env_name) " endfor " endfunction " Jump over current \begin and go to next one. " i.e. if on line =~ \begin => % and then search, else search function! atplib#motion#JumptoEnvironment(backward) call setpos("''", getpos(".")) let lazyredraw=&l:lazyredraw set lazyredraw if !a:backward let col = searchpos('\w*\>\zs', 'n')[1]-1 if strpart(getline(line(".")), 0, col) =~ '\\begin\>$' && \ strpart(getline(line(".")), col) !~ '^\s*{\s*document\s*}' exe "normal g%" endif call search('^\%([^%]\|\\%\)*\zs\\begin\>', 'W') else let found = search('^\%([^%]\|\\%\)*\\end\>', 'bcW') if getline(line(".")) !~ '^\%([^%]\|\\%\)*\\end\s*{\s*document\s*}' && found exe "normal %" elseif !found call search('^\%([^%]\|\\%\)*\zs\\begin\>', 'bW') endif endif let &l:lazyredraw=lazyredraw endfunction " atplib#motion#GotoSection {{{1 " The extra argument is a pattern to match for the " section title. The first, obsolete argument stands for: " part,chapter,section,subsection,etc. " This commands wrap around the end of the file. " with a:3 = 'vim' it uses vim search() function " with a:3 = 'atp' " the default is: " if g:atp_mapNn then use 'atp' " else use 'vim'. function! atplib#motion#GotoSection(bang, count, flag, secname, ...) let search_tool = ( a:0 >= 1 ? a:1 : ( g:atp_mapNn ? 'atp' : 'vim' ) ) let mode = ( a:0 >= 2 ? a:2 : 'n' ) let title_pattern = ( a:0 >= 3 ? a:3 : '' ) let pattern = ( empty(a:bang) ? '^\([^%]\|\\\@ 1 " the 's' flag should be used only in the first search. let flag=substitute(flag, 's', '', 'g') endif if search_tool == 'vim' call searchpos(bpat . pattern, flag) else execute "S /". bpat . pattern . "/ " . flag endif endfor call atplib#motion#UpdateToCLine() call histadd("search", pattern) let @/ = pattern endfunction function! atplib#motion#Env_compl(A,P,L) let envlist=sort(['algorithm', 'algorithmic', 'abstract', 'definition', 'equation', 'proposition', \ 'theorem', 'lemma', 'array', 'tikzpicture', \ 'tabular', 'table', 'align', 'alignat', 'proof', \ 'corollary', 'enumerate', 'examples\=', 'itemize', 'remark', \ 'notation', 'center', 'quotation', 'quote', 'tabbing', \ 'picture', 'math', 'displaymath', 'minipage', 'list', 'flushright', 'flushleft', \ 'frame', 'figure', 'eqnarray', 'thebibliography', 'titlepage', \ 'verbatim', 'verse', 'inlinemath', 'displayedmath', 'subequations', \ 'part', 'section', 'subsection', 'subsubsection' ]) let returnlist=[] for env in envlist if env =~ '^' . a:A call add(returnlist,env) endif endfor return returnlist endfunction function! atplib#motion#ggGotoSection(count,section) let mark = getpos("''") if a:section == "part" let secname = '\\part\>' call cursor(1,1) elseif a:section == "chapter" let secname = '\\\%(part\|chapter\)\>' if !search('\\part\>', 'bc') call cursor(1,1) endif elseif a:section == "section" let secname = '\\\%(part\|chapter\|section\)\>' if !search('\\chapter\>\|\\part\>', 'bc') call cursor(1,1) endif elseif a:section == "subsection" let secname = '\\\%(part\|chapter\|section\|subsection\)\>' if !search('\\section\>\|\\chapter\>\|\\part\>', 'bc') call cursor(1,1) endif elseif a:section == "subsubsection" let secname = '\\\%(part\|chapter\|section\|subsection\|subsubsection\)\>' if !search('\subsection\>\|\\section\>\|\\chapter\>\|\\part\>', 'bc') call cursor(1,1) endif endif call atplib#motion#UpdateToCLine() call atplib#motion#GotoSection("", a:count, 'Ws', secname) call setpos("''",mark) endfunction " atplib#motion#Input {{{1 function! atplib#motion#Input(flag) let pat = ( &l:filetype == "plaintex" ? '\\input\s*{' : '\%(\\input\>\|\\include\s*{\)' ) let @/ = '^\([^%]\|\\\@= 1 ? a:1 : strpart(getline("."), 0, col(".")) !~ '\(\\\@ method = "all" is used. let line = ( check_line ? getline(".") : "" ) if check_line let beg_line = strpart(line, 0,col(".")-1) " Find the begining columnt of the file name: let bcol = searchpos('\%({\|,\)', 'bn', line("."))[1] if bcol == 0 let bcol = searchpos('{', 'n', line("."))[1] endif " Find the end column of the file name let col = searchpos(',\|}', 'cn', line("."))[1] " Current column let cur_col = col(".") endif " This part will be omitted if check_line is 0 (see note above). " \usepackege{...,,...} if line =~ '\\usepackage' && g:atp_developer let method = "usepackage" let ext = '.sty' let fname = atplib#append_ext(strpart(getline("."), bcol, col-bcol-1), ext) let g:fname = fname let file = atplib#search#KpsewhichFindFile('tex', fname, '', 1) let file_l = [ file ] let message = "Pacakge: " let options = "" " \input{...}, \include{...} elseif line =~ '\\\(input\|include\)\s*{' let method = "input{" let ext = '.tex' " \input{} doesn't allow for {...,...} many file path. let fname = atplib#append_ext(strpart(getline("."), bcol, col-bcol-1), '.tex') " The 'file . ext' might be already a full path. if fnamemodify(fname, ":p") != fname let file_l = atplib#search#KpsewhichFindFile('tex', fname, g:atp_texinputs, -1, ':p', '^\(\/home\|\.\)', '\%(^\/usr\|kpsewhich\|texlive\|miktex\)') let file = get(file_l, 0, 'file_missing') else let file_l = [ fname ] let file = fname endif let message = "File: " let options = "" " \input /without {/ elseif line =~ '\\input\s*{\@!' let method = "input" let fname = atplib#append_ext(matchstr(getline(line(".")), '\\input\s*\zs\f*\ze'), '.tex') let file_l = atplib#search#KpsewhichFindFile('tex', fname, g:atp_texinputs, -1, ':p', '^\(\/home\|\.\)', '\%(^\/usr\|kpsewhich\|texlive\)') let file = get(file_l, 0, "file_missing") let options = ' +setl\ ft=' . &l:filetype " \documentclass{...} elseif line =~ '\\documentclass' && g:atp_developer let method = "documentclass" let saved_pos = getpos(".") call cursor(line("."), 1) call search('\\documentclass\zs', 'cb', line(".")) let bcol = searchpos('{', 'c', line("."))[1] execute "normal %" let ecol = col(".") call cursor(saved_pos[0], saved_pos[1]) let classname = strpart(getline("."), bcol, ecol-bcol-1) let fname = atplib#append_ext(classname, '.cls') let file = atplib#search#KpsewhichFindFile('tex', fname, g:atp_texinputs, 1, ':p') let file_l = [ file ] let options = "" elseif line =~ '\\RequirePackage' && g:atp_developer let method = "requirepackage" let ext = '.sty' let fname = atplib#append_ext(strpart(getline("."), bcol, col-bcol-1), ext) let g:fname = fname let file = atplib#search#KpsewhichFindFile('tex', fname, g:atp_texinputs, 1, ':p') let file_l = [ file ] let options = ' +setl\ ft=' . &l:filetype else " If not over any above give a list of input files to open, like " EditInputFile let method = "all" call extend(file_l, [ atp_MainFile ], 0) call extend(level_d, { atp_MainFile : 0 }) endif let g:file_l = copy(file_l) let g:method = method let g:line = line if len(file_l) > 1 && file =~ '^\s*$' if method == "all" let msg = "Which file to edit?" else let msg = "Found many files. Which file to use?" endif let mods = method == 'all' ? ":t" : ":p" " It is better to start numbering from 0, " then 0 - is the main file " 1 - is the first chapter, and so on. let i = 0 let input_l = [] for f in file_l if exists("level_d") let space = "" if g:atp_RelativePath exe "lcd " . fnameescape(b:atp_ProjectDir) let level = get(level_d,fnamemodify(f, ':.'), get(level_d, f, 1)) exe "lcd " . fnameescape(cwd) else exe "lcd " . fnameescape(b:atp_ProjectDir) let level = get(level_d,f, get(level_d,fnamemodify(f, ':.'), 1)) exe "lcd " . fnameescape(cwd) endif for j in range(level) let space .= " " endfor else space = "" endif call add(input_l, "(" . i . ") " . space . fnamemodify(f, mods)) let i+=1 endfor " Ask the user which file to edit: redraw let g:input_l = copy(input_l) if len([ msg ] + input_l) < &l:lines for f in [ msg ] + input_l " echo highlighted message if matchstr(f, '(\d\+)\s*\zs.*$') == expand("%:t") echohl CursorLine elseif f == msg echohl Title endif echo f if matchstr(f, '(\d\+)\s*\zs.*$') == expand("%:t") || f == msg echohl None endif endfor let choice = input("Type number and (empty cancels): ") if choice != "" let choice += 1 endif elseif for line in [ msg ] + input_l if line == msg echohl Title endif echo line echohl None endfor echohl MoreMsg let choice = input("Type number and (empty cancels): ") echohl None if choice != "" let choice += 1 endif endif " Remember: 0 == "" returns 1! " char2nr("") = 0 " nr2char(0) = "" if choice == "" exe "lcd " . fnameescape(cwd) return endif if choice < 1 || choice > len(file_l) if choice < 1 || choice > len(file_l) echo "\n" echoerr "Choice out of range." endif exe "lcd " . fnameescape(cwd) return endif let file = file_l[choice-1] let fname = file elseif file !~ '^\s*$' let file = atplib#FullPath(file) let fname = file endif " DEBUG " let g:fname = fname " let g:file = file " let g:file_l = file_l " let g:choice = choice if !exists("file") exe "lcd " . fnameescape(cwd) return endif if file != "file_missing" && filereadable(file) && ( !exists("choice") || exists("choice") && choice != 0 ) " Inherit tex flavour. " So that bib, cls, sty files will have their file type (bib/plaintex). let filetype = &l:filetype let old_file = expand("%:p") execute "edit ".edit_args." ".escape(find_args, '\')." ".fnameescape(file) call RestoreProjectVariables(projectVarDict) if &l:filetype =~ 'tex$' && file =~ '\.tex$' && &l:filetype != filetype let &l:filetype = filetype endif " Set the main file variable and pass the TreeOfFiles variables to the new " buffer. if exists("b:atp_ErrorFormat") unlockvar b:atp_ErrorFormat endif return file else echohl ErrorMsg redraw if file != "file_missing" && exists("fname") echo "File \'".fname."\' not found." else echo "Missing file." endif echohl None exe "lcd " . fnameescape(cwd) return file endif endfunction catch /E127:/ endtry function! atplib#motion#GotoFileComplete(ArgLead, CmdLine, CursorPos) let bang = ( a:CmdLine =~ '^\w*!' ? '!' : '') if bang == "!" || !exists("b:TreeOfFiles") || !exists("b:ListOfFiles") || !exists("b:TypeDict") || !exists("b:LevelDict") let [tree_d, file_l, type_d, level_d ] = TreeOfFiles(atp_MainFile) else let [tree_d, file_l, type_d, level_d ] = deepcopy([ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ]) endif if index(file_l, b:atp_MainFile) == -1 || index(file_l, fnamemodify(b:atp_MailFile, ":p")) == -1 call add(file_l, b:atp_MainFile) endif return filter(file_l, "v:val =~ a:ArgLead") endfunction " atplib#motion#SkipComment {{{1 " a:flag=fb (f-forward, b-backward) " f works like ]* " b workd like [* " Note: the 's' search flag is passed by the associated commands. " This can be extended: " (1) skip empty lines between comments function! atplib#motion#SkipComment(flag, mode, ...) let flag = ( a:flag =~ 'b' ? 'b' : '' ) let nr = ( a:flag =~ 'b' ? -1 : 1 ) call search('^\zs\s*%', flag) call cursor(line("."), ( nr == -1 ? 1 : len(getline(line("."))))) let line = getline(line(".")) " find previous line let pline_nr=min([line("$"), max([1,line(".")+nr])]) let pline = getline(pline_nr) while pline =~ '^\s*%' call cursor(line(".")+nr, ( nr == -1 ? 1 : len(getline(line(".")+nr)))) let pline_nr=min([line("$"), max([1,line(".")+nr])]) let pline = getline(pline_nr) endwhile if a:mode == 'n' && ( !g:atp_VimCompatible || g:atp_VimCompatible =~? '\' ) if a:flag =~# 'b' call cursor(line(".")-1,1) else call cursor(line(".")+1,1) endif endif if a:mode == 'v' let end_pos = [ line("."), col(".") ] " Go where visual mode started exe "normal `" . ( nr == 1 ? '<' : '>' ) exe "normal " . visualmode() call cursor(end_pos) endif endfunction " Syntax motion " {{{1 atplib#motion#TexSyntaxMotion function! atplib#motion#TexSyntaxMotion(forward, how, ...) " If the function is used in imap. let in_imap = ( a:0 >= 1 ? a:1 : 0 ) let whichwrap = split(&l:whichwrap, ',') if !count(whichwrap, 'l') setl ww+=l endif if !count(whichwrap, 'h') setl ww+=h endif " before we use let line=line(".") if in_imap && len(getline(".")) > col(".") let col = col(".")+1 else let col = col(".") endif " execute "normal l" let step = ( a:forward > 0 ? "l" : "h" ) let synstack = map(synstack(line, col), 'synIDattr( v:val, "name")') let synstackh = map(synstack(line, max([1, col-1])), 'synIDattr( v:val, "name")') let DelimiterCount = count(synstack, 'Delimiter') let ScriptCount = count(synstack, 'texSuperscript') + count(synstack, 'texSubscript') let ScriptsCount = count(synstack, 'texSuperscripts') + count(synstack, 'texSubscripts') let StatementCount = count(synstack, 'texStatement') let StatementCounth = count(synstackh, 'texStatement') && col(".") > 1 let SectionCount = count(synstack, 'texSection') let TypeStyleCount = count(synstack, 'texTypeStyle') let TypeStyleCounth = count(synstackh, 'texTypeStyle') && col(".") > 1 let MathTextCount = count(synstack, 'texMathText') let MathTextCounth = count(synstackh, 'texMathText') && col(".") > 1 let RefZoneCount = count(synstack, 'texRefZone') let RefZoneCounth = count(synstackh, 'texRefZone') && col(".") > 1 let RefOptionCount = count(synstack, 'texRefOption') let RefOptionCounth = count(synstackh, 'texRefOption') && !count(synstackh, 'Delimiter') && col(".") > 1 let CiteCount = count(synstack, 'texCite') let CiteCounth = count(synstackh, 'texCite') && !count(synstackh, 'Delimiter') && col(".") > 1 let MatcherCount = count(synstack, 'texMatcher') let MatcherCounth = count(synstackh, 'texMatcher') && !count(synstackh, 'Delimiter') && col(".") > 1 let MathMatcherCount = count(synstack, 'texMathMatcher') let MathMatcherCounth = count(synstackh, 'texMathMatcher') && !count(synstackh, 'Delimiter') && col(".") > 1 let SectionNameCount = count(synstack, 'texSectionName') let SectionNameCounth = count(synstackh, 'texSectionName') && !count(synstackh, 'Delimiter') && col(".") > 1 let SectionMarkerCount = count(synstack, 'texSectionMarker') let SectionModifierCount = count(synstack, 'texSectionModifier') let SectionModifierCounth = count(synstackh, 'texSectionModifier') && !count(synstackh, 'Delimiter') && col(".") > 1 " let MathZonesCount = len(filter(copy(synstack), 'v:val =~ ''^texMathZone[A-Z]''')) " let g:col = col(".") " let g:line = line(".") if DelimiterCount let syntax = [ 'Delimiter' ] elseif StatementCount && StatementCounth && step == "h" let syntax = [ 'texStatement' ] elseif StatementCount && step != "h" let syntax = [ 'texStatement' ] elseif SectionCount let syntax = [ 'texSection' ] elseif ScriptCount if a:how == 1 let syntax = [ 'texSuperscript', 'texSubscript'] else let syntax = [ 'texSuperscripts', 'texSubscripts'] endif elseif TypeStyleCount && TypeStyleCounth && step == "h" let syntax = [ 'texTypeStyle' ] elseif TypeStyleCount && step != "h" let syntax = [ 'texTypeStyle' ] elseif RefZoneCount && RefZoneCounth && step == "h" let syntax = [ 'texRefZone' ] elseif RefZoneCount && step != "h" let syntax = [ 'texRefZone' ] elseif RefOptionCount && RefOptionCounth && step == "h" let syntax = [ 'texRefOption' ] elseif RefOptionCount && step != "h" let syntax = [ 'texRefOption' ] elseif CiteCount && CiteCounth && step == "h" let syntax = [ 'texCite' ] elseif CiteCount && step != "h" let syntax = [ 'texCite' ] elseif MatcherCount && MatcherCounth && step == "h" let syntax = [ 'texMatcher' ] elseif MatcherCount && step != "h" let syntax = [ 'texMatcher' ] elseif MathMatcherCount && MathMatcherCounth && step == "h" let syntax = [ 'texMathMatcher' ] elseif MathMatcherCount && step != "h" let syntax = [ 'texMathMatcher' ] elseif SectionNameCount && SectionNameCounth && step == "h" let syntax = [ 'texSectionName' ] elseif SectionNameCount && step != "h" let syntax = [ 'texSectionName' ] elseif SectionMarkerCount let syntax = [ 'texSectionMarker' ] elseif SectionModifierCount && SectionModifierCounth && step == "h" let syntax = [ 'texSectionModifier' ] elseif SectionModifierCount && step != "h" let syntax = [ 'texSectionModifier' ] elseif MathTextCount && MathTextCounth && step == "h" let syntax = [ 'texMathText' ] elseif MathTextCount && step != "h" let syntax = [ 'texMathText' ] " elseif MathZonesCount " This might be slow " but we might change 'normal l' to 'normal w' " let syntax = [ 'texMathZoneA', 'texMathZoneB', 'texMathZoneC', 'texMathZoneD', 'texMathZoneE', 'texMathZoneF', 'texMathZoneG', 'texMathZoneH', 'texMathZoneI', 'texMathZoneJ', 'texMathZoneK', 'texMathZoneL', 'texMathZoneT', 'texMathZoneV', 'texMathZoneW', 'texMathZoneX', 'texMathZoneY' ] else " Go after first Delimiter let i=0 let DelimiterCount = count(synstack, 'Delimiter') while !DelimiterCount exe "normal " . step let synstack = map(synstack(line("."), col(".")), 'synIDattr( v:val, "name")') let DelimiterCount = count(synstack, 'Delimiter') if i == 1 let DelimiterCount = 0 endif let i+=1 endwhile if in_imap normal a endif return "Delimiter motion" endif let true = 0 for syn in syntax let true += count(synstack, syn) endfor let initial_count = true while true >= initial_count let true = 0 execute "normal " . step let synstack = map(synstack(line("."), col(".")), 'synIDattr( v:val, "name")') for syn in syntax let true += count(synstack, syn) endfor endwhile while getline(".")[col(".")] =~ '^{\|}\|(\|)\|\[\|\]$' exe "normal l" endwhile if getline(".")[col(".")-2] == "{" exe "normal h" endif let &l:whichwrap = join(whichwrap, ',') if in_imap normal a " else " normal l endif if step == "l" && syntax == [ 'Delimiter' ] normal h endif endfunction " ctrl-j motion " atplib#motion#JMotion {{{1 " New motion function! atplib#motion#JMotion(flag) " Note: pattern to match only commands which do not have any arguments: " '\(\\\w\+\>\s*{\)\@!\\\w\+\>' let line = getline(".") if a:flag !~# 'b' let pline = strpart(line, col(".")-1) if pline =~ '[{]*}{' call search('{.', 'e') return endif else let pline = strpart(line, 0, col(".")) if pline =~ '}{' call search('}{', 'b') normal! h return endif endif if a:flag !~# 'b' let pattern = '\%(\]\zs\|{\zs\|}\zs\|(\zs\|)\zs\|\[\zs\|\]\zs\|\$\zs\|^\zs\s*$\|\(\\\w\+\>\s*{\)\@!\\\w\+\>\zs\)' else let pattern = '\%(\]\|{\|}\|(\|)\|\[\|\]\|\$\|^\s*$\|\(\\\w\+\>\s*{\)\@!\\\w\+\>\)' endif if getline(line(".")) =~ '&' let pattern = '\%(&\s*\zs\|^\s*\zs\)\|' . pattern endif " let g:col = col(".") " sometimes this doesn't work - in normal mode go to " end of line and press 'a' - then col(".") is not working! " let g:let = getline(line("."))[col(".")-1] " let g:con = getline(line("."))[col(".")-1] =~ '\%(\$\|{\|}\|(\|)\|\[\|\]\)' && col(".") < len(getline(line("."))) if getline(line("."))[col(".")-1] =~ '\%(\$\|{\|}\|(\|)\|\[\|\]\)' && a:flag !~# 'b' if col(".") == len(getline(line("."))) execute "normal a " else call cursor(line("."), col(".")+1) endif return else call search(pattern, a:flag) " In the imaps we use 'a' for the backward move and 'i' for forward move! let condition = getline(line("."))[col(".")-1] =~ '\%(\$\|{\|}\|(\|)\|\[\|\]\)' if a:flag !~# 'b' && col(".") == len(getline(line("."))) && condition " Add a space at the end of line and move there execute "normal a " endif endif endfunction " }}}1 " atplib#motion#ParagraphNormalMotion {{{1 function! atplib#motion#ParagraphNormalMotion(backward,count) let g:count = a:count." ".a:backward if a:backward != "b" for i in range(1,a:count) call search('\(^\(\n\|\s\)*\n\s*\zs\S\|\zs\\par\>\|\%'.line("$").'l$\)', 'W') endfor else for i in range(1,a:count) call search('\(^\(\n\|\s\)*\n\s*\zs\S\|\zs\\par\>\|^\%1l\)', 'Wb') endfor endif endfunction nmap ParagraphNormalMotionForward :call atplib#motion#ParagraphNormalMotion('', v:count1) nmap ParagraphNormalMotionBackward :call atplib#motion#ParagraphNormalMotion('b', v:count1) " atplib#motion#StartVisualMode {{{1 function! atplib#motion#StartVisualMode(mode) let g:atp_visualstartpos = getpos(".") if a:mode ==# 'v' normal! v elseif a:mode ==# 'V' normal! V elseif a:mode ==# 'cv' exe "normal! \" endif endfunction " atplib#motion#ParagraphVisualMotion {{{1 function! atplib#motion#ParagraphVisualMotion(backward,count) let cond = !atplib#CompareCoordinates(g:atp_visualstartpos[1:2],getpos("'>")[1:2]) " let g:pos = string(g:atp_visualstartpos)." ".string(getpos("'<"))." ".string(getpos("'>"))." ".cond let bpos = g:atp_visualstartpos if a:backward != "b" if cond call cursor(getpos("'<")[1:2]) else call cursor(getpos("'>")[1:2]) endif for i in range(1,a:count) let epos = searchpos('\(^\(\n\|\s\)*\n\ze\|\(\_s*\)\=\\par\>\|\%'.line("$").'l$\)', 'Wn') endfor else if cond call cursor(getpos("'<")[1:2]) else call cursor(getpos("'>")[1:2]) endif for i in range(1,a:count) let epos = searchpos('\(^\(\n\|\s\)*\n\ze\|\(\_s*\)\=\\par\>\|^\%1l\ze\)', 'Wnb') endfor endif call cursor(bpos[1:2]) exe "normal ".visualmode() call cursor(epos) endfunction vmap ParagraphVisualMotionForward :call atplib#motion#ParagraphVisualMotion('',v:count1) vmap ParagraphVisualMotionBackward :call atplib#motion#ParagraphVisualMotion('b',v:count1) " vim:fdm=marker:tw=85:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/search.vim [[[1 2290 " Author: Marcin Szamotulski " Description: This file provides searching tools of ATP. " Note: This file is a part of Automatic Tex Plugin for Vim. " Language: tex " Last Change:Tue Sep 06, 2011 at 03:18 +0100 " Make a dictionary of definitions found in all input files. " {{{ atplib#search#make_defi_dict_vim " Comparing with ]D, ]d, ]i, ]I vim maps this function deals with multiline " definitions. " " The output dictionary is of the form: " { input_file : [ [begin_line, end_line], ... ] } " a:1 = buffer name to search in for input files " a:3 = 1 skip searching for the end_line " " ToDo: it is possible to check for the end using searchpairpos, but it " operates on a list not on a buffer. function! atplib#search#make_defi_dict_vim(bang,...) let atp_MainFile = atplib#FullPath(b:atp_MainFile) let bufname = a:0 >= 1 ? a:1 : atp_MainFile " pattern to match the definitions this function is also used to fine " \newtheorem, and \newenvironment commands let pattern = a:0 >= 2 ? a:2 : '\\def\|\\newcommand' let preambule_only = ( a:bang == "!" ? 0 : 1 ) " this is still to slow! let only_begining = ( a:0 >= 3 ? a:3 : 0 ) let defi_dict={} let inputfiles=atplib#search#FindInputFiles(bufname) let input_files=[] " TeX: How this work in TeX files. for inputfile in keys(inputfiles) if inputfiles[inputfile][0] != "bib" && ( !preambule_only || inputfiles[inputfile][0] == "preambule" ) call add(input_files, inputfiles[inputfile][2]) endif endfor let input_files=filter(input_files, 'v:val != ""') if !count(input_files, atp_MainFile) call extend(input_files,[ atp_MainFile ]) endif if len(input_files) > 0 for inputfile in input_files let defi_dict[inputfile]=[] " do not search for definitions in bib files "TODO: it skips lines somehow. let ifile=readfile(inputfile) " search for definitions let lnr=1 while (lnr <= len(ifile) && (!preambule_only || ifile[lnr-1] !~ '\\begin\s*{document}')) let match=0 let line=ifile[lnr-1] if substitute(line,'\\\@,) function! atplib#search#make_defi_dict_py(bang,...) let atp_MainFile = atplib#FullPath(b:atp_MainFile) let bufname = a:0 >= 1 ? a:1 : atp_MainFile " Not tested let pattern = a:0 >= 2 ? a:2 : '\\def\|\\newcommand' " Not implemeted let preambule_only= a:bang == "!" ? 0 : 1 let g:preambule_only=preambule_only let only_begining = a:0 >= 3 ? a:3 : 0 let g:only_begining=only_begining if a:bang == "!" || !exists("b:TreeOfFiles") " Update the cached values: let [ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ] = TreeOfFiles(atp_MainFile) endif let [ Tree, List, Type_Dict, Level_Dict ] = deepcopy([ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ]) python << ENDPYTHON import re, subprocess, os, glob def preambule_end(file): # find linenr where preambule ends, # file is list of lines nr=1 for line in file: if re.search('\\\\begin\s*{\s*document\s*}', line): return nr nr+=1 return 0 pattern=vim.eval("pattern") type_dict=vim.eval("b:TypeDict") main_file=vim.eval("atp_MainFile") if int(vim.eval("preambule_only")) != 0: preambule_only=True files=[main_file] for f in type_dict.keys(): if type_dict[f] == "preambule": files.append(f) main_file_ob=open(main_file, 'r') main_file_l=main_file_ob.read().split("\n") main_file_ob.close() preambule_end=preambule_end(main_file_l) else: preambule_only=False files=[main_file] files.extend(vim.eval("b:ListOfFiles")) if vim.eval("only_begining") != "0": only_begining=True else: only_begining=False def isnonempty(string): if str(string) == "": return False else: return True if pattern == "": pat=".*" else: pat=pattern # Does the no comment work? pattern=re.compile('^(?:[^%]|\\\\%)*(?:\\\\def|\\\\(?:re)?newcommand\s*{|\\\\providecommand\s*{|\\\\(?:re)?newenvironment\s*{|\\\\(?:re)?newtheorem\s*{|\\\\definecolor\s*{)') defi_dict={} for file in files: defi_dict[file]=[] lnr=1 file_ob=open(file, 'r') file_l=file_ob.read().split("\n") file_ob.close() while lnr <= len(file_l) and ( preambule_only and ( file == main_file and lnr <= preambule_end or file != main_file ) or not preambule_only): line=file_l[lnr-1] if re.search(pattern, line): # add: no search in comments. b_lnr = lnr if not only_begining: _open = len(re.findall("({)", line)) _close = len(re.findall("(})", line)) while _open != _close: lnr+=1 line = file_l[lnr-1] _open += len(re.findall("({)", line)) _close += len(re.findall("(})", line)) e_lnr = lnr defi_dict[file].append([ b_lnr, e_lnr ]) else: defi_dict[file].append([ b_lnr, b_lnr ]) lnr += 1 else: lnr+=1 vim.command("let s:defi_dict_py="+str(defi_dict)) vim.command("let g:defi_dict_py="+str(defi_dict)) ENDPYTHON return s:defi_dict_py endfunction "}}} "{{{ atplib#search#LocalCommands_vim " a:1 = pattern " a:2 = "!" => renegenerate the input files. function! atplib#search#LocalCommands_vim(...) " let time = reltime() let pattern = a:0 >= 1 && a:1 != '' ? a:1 : '\\def\>\|\\newcommand\>\|\\newenvironment\|\\newtheorem\|\\definecolor\|' \ . '\\Declare\%(RobustCommand\|FixedFont\|TextFontCommand\|MathVersion\|SymbolFontAlphabet' \ . '\|MathSymbol\|MathDelimiter\|MathAccent\|MathRadical\|MathOperator\)' \ . '\|\\SetMathAlphabet\>' let bang = a:0 >= 2 ? a:2 : '' let atp_MainFile = atplib#FullPath(b:atp_MainFile) " Makeing lists of commands and environments found in input files if bang == "!" || !exists("b:TreeOfFiles") " Update the cached values: let [ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ] = TreeOfFiles(atp_MainFile) endif let [ Tree, List, Type_Dict, Level_Dict ] = deepcopy([ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ]) let saved_loclist = getloclist(0) " I should scan the preambule separately! " This will make the function twice as fast! silent! execute "lvimgrep /".pattern."/j " . fnameescape(atp_MainFile) for file in List if get(Type_Dict, file, 'no_file') == 'preambule' silent! execute "lvimgrepadd /".pattern."/j " . fnameescape(file) endif endfor let loclist = getloclist(0) call setloclist(0, saved_loclist) let atp_LocalCommands = [] let atp_LocalEnvironments = [] let atp_LocalColors = [] for line in loclist " the order of pattern is important if line['text'] =~ '^[^%]*\\definecolor' " color name let name=matchstr(line['text'], \ '\\definecolor\s*{\s*\zs[^}]*\ze\s*}') let type="Colors" elseif line['text'] =~ '^[^%]*\%(\\def\>\|\\newcommand\)' " definition name let name= '\' . matchstr(line['text'], '\\def\\\zs[^{]*\ze{\|\\newcommand{\?\\\zs[^\[{]*\ze}') let name=substitute(name, '\(#\d\+\)\+\s*$', '', '') let name.=(line['text'] =~ '\\def\\\w\+#[1-9]\|\\newcommand{[^}]*}\[[1-9]\]' ? '{' : '') if name =~ '#\d\+' echo line['text'] echo name endif let type="Commands" " definition " let def=matchstr(line['text'], " \ '^\%(\\def\\[^{]*{\zs.*\ze}\|\\newcommand\\[^{]*{\zs.*\ze}\)') elseif line['text'] =~ '^[^%]*\%(\\Declare\%(RobustCommand\|FixedFont\|TextFontCommand\|MathVersion\|SymbolFontAlphabet' \ . '\|MathSymbol\|MathDelimiter\|MathAccent\|MathRadical\|MathOperator\)\>\|\\SetMathAlphabet\)' let name=matchstr(line['text'], \ '\%(\\Declare\%(RobustCommand\|FixedFont\|TextFontCommand\|MathVersion\|SymbolFontAlphabet' \ . '\|MathSymbol\|MathDelimiter\|MathAccent\|MathRadical\|MathOperator\)\|\\SetMathAlphabet\)\s*{\s*\zs[^}]*\ze\s*}') let type="Commands" elseif line['text'] =~ '^[^%]*\%(\\newenvironment\|\\newtheorem\)' " environment name let name=matchstr(line['text'], \ '^[^%]*\\\%(newtheorem\*\?\|newenvironment\)\s*{\s*\zs[^}]*\ze\s*}') let type="Environments" endif if exists("name") && name != '' && name != '\' if count(atp_Local{type}, name) == 0 call add(atp_Local{type}, name) endif endif endfor let b:atp_LocalCommands = atp_LocalCommands let b:atp_LocalEnvironments = atp_LocalEnvironments let b:atp_LocalColors = atp_LocalColors return [ atp_LocalEnvironments, atp_LocalCommands, atp_LocalColors ] endfunction "}}} " {{{ atplib#search#LocalCommands_py function! atplib#search#LocalCommands_py(write, ...) let time=reltime() " The first argument pattern is not implemented " but it should be a python regular expression let bang = a:0 >= 2 ? a:2 : '' let atp_MainFile = atplib#FullPath(b:atp_MainFile) let pwd = getcwd() exe "cd ".fnameescape(b:atp_ProjectDir) if a:write call atplib#write() endif " Makeing lists of commands and environments found in input files if bang == "!" || !exists("b:TreeOfFiles") " Update the cached values: let [ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ] = TreeOfFiles(atp_MainFile) endif let [ Tree, List, Type_Dict, Level_Dict ] = deepcopy([ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ]) " Note: THIS CODE IS ONLY NEEDED WHEN PWD is different than the TreeOfFiles was " called! There is an option to store full path in ATP, then this is not needed. let files = [] for file in b:ListOfFiles if get(b:TypeDict, file, "") == "input" || get(b:TypeDict, file, "") == "preambule" if filereadable(file) call add(files, file) else " This makes it really slow when the files are missing. let file=atplib#search#KpsewhichFindFile("tex", file) if file != "" call add(files, file) endif endif endif endfor python << END import re, vim pattern=re.compile('\s*(?:\\\\(?Pdef)(?P\\\\[^#{]*)|(?:\\\\(?Pnewcommand)|\\\\(?Pnewenvironment)|\\\\(?Pnewtheorem\*?)|\\\\(?Pdefinecolor)|\\\\(?PDeclare)(?:RobustCommand|FixedFont|TextFontCommand|MathVersion|SymbolFontAlphabet|MathSymbol|MathDelimiter|MathAccent|MathRadical|MathOperator)\s*{|\\\\(?PSetMathAlphabet))\s*{(?P[^}]*)})') files=[vim.eval("atp_MainFile")]+vim.eval("files") localcommands =[] localcolors =[] localenvs =[] for file in files: lnr=1 if os.path.exists(file): try: file_ob=open(file, 'r') file_l=file_ob.read().split("\n") file_ob.close() for line in file_l: m=re.match(pattern, line) if m: if m.group('def'): if re.search('\\\\def\\\\\w+#[1-9]', line): localcommands.append(m.group('def_c')+'{') else: localcommands.append(m.group('def_c')) elif m.group('nc') or m.group('dec') or m.group('sma'): if re.search('\\\\newcommand\s*{[^}]*}\s*\[[1-9]\]\s*{', line): localcommands.append(m.group('arg')+'{') else: localcommands.append(m.group('arg')) elif m.group('nt') or m.group('env'): localenvs.append(m.group('arg')) elif m.group('col'): localcolors.append(m.group('arg')) except IOError: pass vim.command("let atp_LocalCommands="+str(localcommands)) vim.command("let atp_LocalEnvironments="+str(localenvs)) vim.command("let atp_LocalColors="+str(localcolors)) END if exists("atp_LocalCommands") let b:atp_LocalCommands=map(atp_LocalCommands, 'substitute(v:val, ''\\\\'', ''\'', '''')') else let b:atp_LocalCommands=[] endif if exists("atp_LocalColors") let b:atp_LocalColors=map(atp_LocalColors, 'substitute(v:val, ''\\\\'', ''\'', '''')') else let b:atp_LocalColors=[] endif if exists("atp_LocalEnvironments") let b:atp_LocalEnvironments=map(atp_LocalEnvironments, 'substitute(v:val, ''\\\\'', ''\'', '''')') else let b:atp_LocalEnvironments=[] endif let g:time_LocalCommands_py=reltimestr(reltime(time)) exe "cd ".fnameescape(pwd) return [ b:atp_LocalEnvironments, b:atp_LocalCommands, b:atp_LocalColors ] endfunction "}}} " atplib#search#LocalAbbreviations {{{ function! atplib#search#LocalAbbreviations() if !exists("b:atp_LocalEnvironments") let no_abbrev= ( exists('g:atp_no_local_abbreviations') ? g:atp_no_local_abbreviations : -1 ) let g:atp_no_local_abbreviations = 1 call LocalCommands(0) if no_abbrev == -1 unlet g:atp_no_local_abbreviations else let g:atp_no_local_abbreviations = no_abbrev endif endif for env in b:atp_LocalEnvironments if !empty(maparg(g:atp_iabbrev_leader.env.g:atp_iabbrev_leader, "i", 1)) " silent echomsg "abbreviation " . g:atp_iabbrev_leader.env.g:atp_iabbrev_leader . " exists." continue endif if exists("g:atp_abbreviate_".env) execute "iabbrev ".g:atp_iabbrev_leader.env.g:atp_iabbrev_leader." \\begin{".env."}".get(g:atp_abbreviate_{env}, 0, "")."\\end{".env."}".get(g:atp_abbreviate_{env}, 1, "O") else execute "iabbrev ".g:atp_iabbrev_leader.env.g:atp_iabbrev_leader." \\begin{".env."}\\end{".env."}O" endif endfor endfunction "}}} " Search for Definition in the definition dictionary (atplib#search#make_defi_dict). "{{{ atplib#search#Dsearch function! atplib#search#Dsearch(bang,...) call atplib#write() let time = reltime() let o_pattern = a:0 >= 1 ? matchstr(a:1, '\/\=\zs.*[^\/]\ze\/\=') : '' let pattern = '\%(\\def\|\\\%(re\)\=newcommand\s*{\=\|\\providecommand\s*{\=\|\\\%(re\)\=newenvironment\s*{\|\\\%(re\)\=newtheorem\s*{\|\\definecolor\s*{\)\s*\\\=\w*\zs'.o_pattern let preambule_only = ( a:bang == "!" ? 0 : 1 ) let atp_MainFile = atplib#FullPath(b:atp_MainFile) if has("python") let defi_dict = atplib#search#make_defi_dict_py(a:bang, atp_MainFile, pattern) else let defi_dict = atplib#search#make_defi_dict_vim(a:bang, atp_MainFile, pattern) endif if len(defi_dict) > 0 " wipe out the old buffer and open new one instead if bufloaded("DefiSearch") exe "silent bd! " . bufnr("DefiSearch") endif if !exists("b:atp_MainFile") || !exists("b:atp_ProjectDir") " Note: I should write a function to read just one variable from " project file. LoadProjectScript endif setl syntax=tex let defi_list = [] let g:defi_list = defi_list let signs = [] let g:signs = signs for inputfile in keys(defi_dict) let ifile = readfile(inputfile) for l:range in defi_dict[inputfile] " This respects the options 'smartcase' and 'ignorecase'. let case = ( &l:smartcase && &l:ignorecase && pattern =~ '\u' ? 'noignorecase' : ( &l:ignorecase ? 'ignorecase' : 'noignorecase' )) let condition = ( case == "noignorecase" ? ifile[l:range[0]-1] =~# pattern : ifile[l:range[0]-1] =~? pattern ) if condition " print the lines into defi_list let i=0 let c=0 " add an empty line if the definition is longer than one line if l:range[0] != l:range[1] call add(defi_list, '') let i+=1 endif while c <= l:range[1]-l:range[0] let line=l:range[0]+c call add(defi_list, ifile[line-1]) if c == 0 cal add(signs, len(defi_list)) endif let i+=1 let c+=1 endwhile endif endfor endfor if len(defi_list) == 0 redraw echohl ErrorMsg if a:bang == "!" echomsg "[ATP:] definition not found." else echomsg "[ATP:] definition not found in the preambule, try with a bang ! to search beyond." endif echohl None return endif " open new buffer let window_height= min([g:atp_DsearchMaxWindowHeight, len(defi_list)]) let openbuffer=" +setl\\ buftype=nofile\\ nospell\\ nornu\\ nonu " . fnameescape("DefiSearch") if g:vertical == 1 let openbuffer="keepalt vsplit " . openbuffer else let openbuffer="keepalt rightbelow ".window_height."split " . openbuffer endif silent exe openbuffer call setline(1, defi_list) if getline(line(".")) =~ '^\s*$' normal! dd call map(signs, 'v:val-1') endif if o_pattern != "" call matchadd('Search', ( &l:ignorecase ? '\c' : '\C' ) .o_pattern) let @/=o_pattern endif setl syntax=tex setl readonly map q :bd " Place signs: if has("signs") sign unplace * for i in signs exe 'sign define '.i.' text=>>' exe 'sign place '.i.' line='.i.' name='.i.' file='.expand('%:p') endfor endif else redraw echohl ErrorMsg if a:bang == "!" echomsg "[ATP:] definition not found." else echomsg "[ATP:] definition not found in the preambule, try with a bang ! to search beyond." endif echohl None endif let g:source_time_DSEARCH=reltimestr(reltime(time)) endfunction function! atplib#search#DsearchComp(ArgLead, CmdLine, CursorPos) if !exists("b:atp_LocalCommands") LocalCommands endif let list=[] call extend(list, b:atp_LocalCommands) call extend(list, b:atp_LocalColors) call extend(list, b:atp_LocalEnvironments) call filter(list, 'v:val =~ a:ArgLead') call map(list, 'escape(v:val, ''\*'')') return sort(list) endfunction "}}} " Search in tree and return the one level up element and its line number. " {{{ atplib#search#SearchInTree " Before running this function one has to set the two variables " s:branch/s:branch_line to 0. " the a:tree variable should be something like: " a:tree = { b:atp_MainFile, [ TreeOfFiles(b:atp_MainFile)[0], 0 ] } " necessary a rooted tree! " This function remaps keys of dictionary. function! atplib#search#MapDict(dict) let new_dict = {} for key in keys(a:dict) let new_key = fnamemodify(key, ":p") let new_dict[new_key] = a:dict[key] endfor return new_dict endfunction function! atplib#search#SearchInTree(tree, branch, what) if g:atp_debugSIT exe "redir! > ".g:atp_TempDir."/SearchInTree.log" silent! echo "___SEARCH_IN_TREE___" silent! echo "a:branch=". a:branch silent! echo "a:what=" . a:what endif if g:atp_debugSIT >= 2 silent! echo "a:tree=" . string(a:tree) endif " let branch = a:tree[a:branch][0] if a:branch =~ '^\s*\/' let cwd = getcwd() exe "lcd " . fnameescape(b:atp_ProjectDir) let branchArg = ( g:atp_RelativePath ? fnamemodify(a:branch, ":.") : a:branch ) let branchArgN = ( !g:atp_RelativePath ? fnamemodify(a:branch, ":.") : a:branch ) let whatArg = ( g:atp_RelativePath ? fnamemodify(a:what, ":.") : a:what ) let whatArgN = ( !g:atp_RelativePath ? fnamemodify(a:what, ":.") : a:what ) if g:atp_debugSIT silent! echo "*** cwd=" . getcwd() . " b:atp_ProjectDir= " . b:atp_ProjectDir . " " . fnamemodify(a:branch, ":.") . " " . a:branch endif exe "lcd " . fnameescape(cwd) else let branchArg = ( g:atp_RelativePath ? a:branch : atplib#FullPath(a:branch) ) let branchArgN = ( !g:atp_RelativePath ? a:branch : atplib#FullPath(a:branch) ) let whatArg = ( g:atp_RelativePath ? a:what : atplib#FullPath(a:what) ) let whatArgN = ( !g:atp_RelativePath ? a:what : atplib#FullPath(a:what) ) endif if g:atp_debugSIT silent! echo "branchArg=" . branchArg . " branchArgN=" . branchArgN silent! echo "whatArg=" . whatArg . " whatArgN=" . whatArgN endif let branch = get(a:tree, branchArg , get(a:tree, branchArgN, ['NO_BRANCH']))[0] if count(keys(branch), whatArg) || count(keys(branch), whatArgN) " The following variable is used as a return value in " RecursiveSearch! let g:ATP_branch = branchArg let g:ATP_branch_line = get(branch, whatArg, get(branch, whatArgN, ['', 'ERROR']))[1] if g:atp_debugSIT silent! echo "g:ATP_branch=" . g:ATP_branch . " g:ATP_branch_line=" . g:ATP_branch_line redir END endif return branchArg else for new_branch in keys(branch) call atplib#search#SearchInTree(branch, new_branch, whatArg) endfor endif if g:atp_debugSIT redir END endif return endfunction " }}} " Search in all input files recursively. " {{{ Recursive Search " " Variables are used to pass them to next runs (this function calls it self) " a:main_file = b:atp_MainFile " a:start_file = expand("%:p") /this variable will not change untill the " last instance/ " a:tree = make_tree => make a tree " = any other value => use { a:main_file : [ b:TreeOfFiles, 0] } " a:cur_branch = expand("%") /this will change whenever we change a file/ " a:call_nr = number of the call " a:wrap_nr = if hit top/bottom a:call=0 but a:wrap_nr+=1 " a:winsaveview = winsaveview(0) to resotre the view if the pattern was not found " a:bufnr = bufnr("%") to come back to begining buffer if pattern not found " a:strftime = strftime(0) to compute the time " a:pattern = pattern to search " a:1 = flags: 'bcewWs' " a:2 is not not used: " a:2 = goto = DOWN_ACCEPT / Must not be used by the end user/ " 0/1 1=DOWN_ACCEPT " " g:atp_debugRS if 1 sets debugging messages which are appended to '/tmp/ATP_rs_debug' " you can :set errorfile=/tmp/ATP_rs_debug " and :set efm=.* " if 2 show time " log file : /tmp/ATP_rs_debug " {{{ atplib#search#RecursiveSearch function let g:atp_swapexists = 0 try function! atplib#search#RecursiveSearch(main_file, start_file, maketree, tree, cur_branch, call_nr, wrap_nr, winsaveview, bufnr, strftime, vim_options, cwd, pattern, ... ) let main_file = g:atp_RelativePath ? atplib#RelativePath(a:main_file, b:atp_ProjectDir) : a:main_file let time0 = reltime() " set and restore some options: " foldenable (unset to prevent opening the folds :h winsaveview) " comeback to the starting buffer if a:call_nr == 1 && a:wrap_nr == 1 if a:vim_options == { 'no_options' : 'no_options' } let vim_options = { 'hidden' : &l:hidden, \ 'foldenable' : &l:foldenable, \ 'autochdir' : &l:autochdir } else let vim_options = a:vim_options endif let &l:hidden = 1 let &l:foldenable = 0 let &l:autochdir = 0 if a:cwd == 'no_cwd' let cwd = getcwd() else let cwd = a:cwd endif exe "lcd " . fnameescape(b:atp_ProjectDir) " This makes it work faster when the input files were not yet opened by vim " some of them will not be shown to the user. " syntax off filetype off " there are many errors in /tmp/ATP_rs_debug file due to this which are not " important. else let vim_options = a:vim_options let cwd = a:cwd endif " Redirect debuggin messages: if g:atp_debugRS if a:wrap_nr == 1 && a:call_nr == 1 exe "redir! > ".g:atp_TempDir."/RecursiveSearch.log" else exe "redir! >> ".g:atp_TempDir."/RecursiveSearch.log" endif silent echo "________________" silent echo "Args: a:pattern:".a:pattern." call_nr:".a:call_nr. " wrap_nr:".a:wrap_nr . " cwd=" . getcwd() endif let flags_supplied = a:0 >= 1 ? a:1 : "" if flags_supplied =~# 'p' let flags_supplied = substitute(flags_supplied, 'p', '', 'g') echohl WarningMsg echomsg "[ATP:] searching flag 'p' is not supported, filtering it out." echohl None endif if a:maketree == 'make_tree' if g:atp_debugRS silent echo "*** Makeing Tree ***" endif let tree_of_files = TreeOfFiles(main_file)[0] else if g:atp_debugRS silent echo "*** Using Tree ***" endif let tree_of_files = a:tree endif let tree = { main_file : [ tree_of_files, 0 ] } if a:cur_branch != "no cur_branch " let cur_branch = a:cur_branch else let cur_branch = main_file endif if g:atp_debugRS > 1 silent echo "TIME0:" . reltimestr(reltime(time0)) endif let pattern = a:pattern let flags_supplied = substitute(flags_supplied, '[^bcenswWS]', '', 'g') " Add pattern to the search history if a:call_nr == 1 call histadd("search", a:pattern) let @/ = a:pattern endif " Set up searching flags let flag = flags_supplied if a:call_nr > 1 let flag = flags_supplied !~# 'c' ? flags_supplied . 'c' : flags_supplied endif let flag = substitute(flag, 'w', '', 'g') . 'W' let flag = flag !~# 'n' ? substitute(flag, 'n', '', 'g') . 'n' : flag let flag = substitute(flag, 's', '', 'g') if flags_supplied !~# 'b' " forward searching flag for input files: let flag_i = flags_supplied !~# 'c' ? flags_supplied . 'c' : flags_supplied else let flag_i = substitute(flags_supplied, 'c', '', 'g') endif let flag_i = flag_i !~# 'n' ? flag_i . 'n' : flag_i let flag_i = substitute(flag_i, 'w', '', 'g') . 'W' let flag_i = substitute(flag_i, 's', '', 'g') if g:atp_debugRS silent echo " flags_supplied:".flags_supplied." flag:".flag." flag_i:".flag_i." a:1=".(a:0 != 0 ? a:1 : "") endif " FIND PATTERN: let cur_pos = [line("."), col(".")] " We filter out the 's' flag which should be used only once " as the flags passed to next atplib#search#RecursiveSearch()es are based on flags_supplied variable " this will work. let s_flag = flags_supplied =~# 's' ? 1 : 0 let flags_supplied = substitute(flags_supplied, 's', '', 'g') if s_flag call setpos("''", getpos(".")) endif keepjumps let pat_pos = searchpos(pattern, flag) if g:atp_debugRS > 1 silent echo "TIME1:" . reltimestr(reltime(time0)) endif " FIND INPUT PATTERN: " (we do not need to search further than pat_pos) if pat_pos == [0, 0] let stop_line = flag !~# 'b' ? line("$") : 1 else let stop_line = pat_pos[0] endif keepjumps let input_pos = searchpos('\m^[^%]*\\input\s*{', flag_i . 'n', stop_line ) if g:atp_debugRS > 1 silent echo "TIME2:" . reltimestr(reltime(time0)) endif if g:atp_debugRS silent echo "Positions: ".string(cur_pos)." ".string(pat_pos)." ".string(input_pos)." in branch: ".cur_branch."#".expand("%:p") . " stop_line: " . stop_line endif " Down Accept: " the current value of down_accept let DOWN_ACCEPT = a:0 >= 2 ? a:2 : 0 " the value of down_accept in next turn let down_accept = getline(input_pos[0]) =~ pattern || input_pos == [0, 0] ? 1 : 0 " if g:atp_debugRS " silent echo "DOWN_ACCEPT=" . DOWN_ACCEPT . " down_accept=" . down_accept " endif " Decide what to do: accept the pattern, go to higher branch, go to lower " branch or say Pattern not found if flags_supplied !~# 'b' " FORWARD " cur < pat <= input if atplib#CompareCoordinates(cur_pos,pat_pos) && atplib#CompareCoordinates_leq(pat_pos, input_pos) let goto_s = 'ACCEPT' " cur == pat <= input elseif cur_pos == pat_pos && atplib#CompareCoordinates_leq(pat_pos, input_pos) " this means that the 'flag' variable has to contain 'c' or the " wrapscan is on " ACCEPT if 'c' and wrapscan is off or there is another match below, " if there is not go UP. let wrapscan = ( flags_supplied =~# 'w' || &l:wrapscan && flags_supplied !~# 'W' ) if flag =~# 'c' let goto_s = 'ACCEPT' elseif wrapscan " if in wrapscan and without 'c' flag let goto_s = 'UP' else " this should not happen: cur == put can hold only in two cases: " wrapscan is on or 'c' is used. let goto_s = 'ERROR' endif " pat < cur <= input elseif atplib#CompareCoordinates(pat_pos, cur_pos) && atplib#CompareCoordinates_leq(cur_pos, input_pos) let goto_s = 'UP' " cur < input < pat elseif atplib#CompareCoordinates(cur_pos, input_pos) && atplib#CompareCoordinates(input_pos, pat_pos) let goto_s = 'UP' " cur < input == pat /we are looking for '\\input'/ elseif atplib#CompareCoordinates(cur_pos, input_pos) && input_pos == pat_pos let goto_s = 'ACCEPT' " input < cur <= pat (includes input = 0]) elseif atplib#CompareCoordinates(input_pos, cur_pos) && atplib#CompareCoordinates_leq(cur_pos, pat_pos) " cur == pat thus 'flag' contains 'c'. let goto_s = 'ACCEPT' " cur == input elseif cur_pos == input_pos let goto_s = 'UP' " cur < input < pat " input == 0 /there is no 'input' ahead - flag_i contains 'W'/ " /but there is no 'pattern ahead as well/ " at this stage: pat < cur (if not then input = 0 < cur <= pat was done above). elseif input_pos == [0, 0] if expand("%:p") == fnamemodify(main_file, ":p") " wrapscan if ( flags_supplied =~# 'w' || &l:wrapscan && flags_supplied !~# 'W' ) let new_flags = substitute(flags_supplied, 'w', '', 'g') . 'W' if a:wrap_nr <= 2 call cursor(1,1) if g:atp_debugRS silent echo " END 1 new_flags:" . new_flags redir END endif keepjumps call atplib#search#RecursiveSearch(main_file, a:start_file, "", tree_of_files, a:cur_branch, 1, a:wrap_nr+1, a:winsaveview, a:bufnr, a:strftime, vim_options, cwd, pattern, new_flags) return else let goto_s = "REJECT" " echohl ErrorMsg " echomsg 'Pattern not found: ' . a:pattern " echohl None endif else let goto_s = "REJECT" " echohl ErrorMsg " echomsg 'Pattern not found: ' . a:pattern " echohl None endif " if we are not in the main file go up. else let goto_s = "DOWN" endif else let goto_s = 'ERROR' endif else " BACKWARD " input <= pat < cur (pat != 0) if atplib#CompareCoordinates(pat_pos, cur_pos) && atplib#CompareCoordinates_leq(input_pos, pat_pos) && pat_pos != [0, 0] " input < pat if input_pos != pat_pos let goto_s = 'ACCEPT' " input == pat else let goto_s = 'UP' endif " input <= pat == cur (input != 0) /pat == cur => pat != 0/ elseif cur_pos == pat_pos && atplib#CompareCoordinates_leq(input_pos, pat_pos) && input_pos != [0, 0] " this means that the 'flag' variable has to contain 'c' or the " wrapscan is on let wrapscan = ( flags_supplied =~# 'w' || &l:wrapscan && flags_supplied !~# 'W' ) if flag =~# 'c' let goto_s = 'ACCEPT' elseif wrapscan " if in wrapscan and without 'c' flag let goto_s = 'UP' else " this should not happen: cur == put can hold only in two cases: " wrapscan is on or 'c' is used. let goto_s = 'ERROR' endif " input <= cur < pat (input != 0) elseif atplib#CompareCoordinates(cur_pos, pat_pos) && atplib#CompareCoordinates_leq(input_pos, cur_pos) && input_pos != [0, 0] let goto_s = 'UP' " pat < input <= cur (input != 0) elseif atplib#CompareCoordinates_leq(input_pos, cur_pos) && atplib#CompareCoordinates(pat_pos, input_pos) && input_pos != [0, 0] let goto_s = 'UP' " input == pat < cur (pat != 0) /we are looking for '\\input'/ elseif atplib#CompareCoordinates(input_pos, cur_pos) && input_pos == pat_pos && pat_pos != [0, 0] let goto_s = 'ACCEPT' " pat <= cur < input (pat != 0) elseif atplib#CompareCoordinates(cur_pos, input_pos) && atplib#CompareCoordinates_leq(pat_pos, cur_pos) && input_pos != [0, 0] " cur == pat thus 'flag' contains 'c'. let goto_s = 'ACCEPT' " cur == input elseif cur_pos == input_pos let goto_s = 'UP' " input == 0 /there is no 'input' ahead - flag_i contains 'W'/ " /but there is no 'pattern ahead as well/ " at this stage: cur < pat || pat=input=0 (if not then pat <= cur was done above, input=pat=0 is the " only posibility to be passed by the above filter). elseif input_pos == [0, 0] " I claim that then cur < pat or pat=0 if expand("%:p") == fnamemodify(main_file, ":p") " wrapscan if ( flags_supplied =~# 'w' || &l:wrapscan && flags_supplied !~# 'W' ) let new_flags = substitute(flags_supplied, 'w', '', 'g') . 'W' if a:wrap_nr <= 2 call cursor(line("$"), col("$")) if g:atp_debugRS silent echo " END 2 new_flags:".new_flags redir END endif keepjumps call atplib#search#RecursiveSearch(main_file, a:start_file, "", tree_of_files, a:cur_branch, 1, a:wrap_nr+1, a:winsaveview, a:bufnr, a:strftime, vim_options, cwd, pattern, new_flags) if g:atp_debugRS > 1 silent echo "TIME_END:" . reltimestr(reltime(time0)) endif return else let goto_s = "REJECT" " echohl ErrorMsg " echomsg 'Pattern not found: ' . a:pattern " echohl None endif else let goto_s = "REJECT" endif " if we are not in the main file go up. else let goto_s = "DOWN" " If using the following line DOWN_ACCEPT and down_accept " variables are not needed. This seems to be the best way. " There is no need to use this feature for " \input files. if pattern =~ '\\\\input' || pattern =~ '\\\\include' " if getline(input_pos[0]) =~ pattern || getline(".") =~ pattern let goto_s = "DOWN_ACCEPT" endif endif else let goto_s = 'ERROR' endif endif if g:atp_debugRS silent echo "goto_s:".goto_s endif if g:atp_debugRS >= 2 silent echo "TIME ***goto*** " . reltimestr(reltime(time0)) endif " When ACCEPTING the line: if goto_s == 'ACCEPT' keepjumps call setpos(".", [ 0, pat_pos[0], pat_pos[1], 0]) if flags_supplied =~# 'e' keepjumps call search(pattern, 'e', line(".")) endif "A Better solution must be found. " if &l:hlsearch " execute '2match Search /'.pattern.'/' " endif let time = matchstr(reltimestr(reltime(a:strftime)), '\d\+\.\d\d\d') . "sec." if a:wrap_nr == 2 && flags_supplied =~# 'b' redraw echohl WarningMsg echo "search hit TOP, continuing at BOTTOM " echohl None elseif a:wrap_nr == 2 redraw echohl WarningMsg echo "search hit BOTTOM, continuing at TOP " echohl None endif if g:atp_debugRS silent echo "FOUND PATTERN: " . a:pattern . " time " . time silent echo "" redir END endif " restore vim options if a:vim_options != { 'no_options' : 'no_options' } for option in keys(a:vim_options) execute "let &l:".option."=".a:vim_options[option] endfor endif exe "lcd " . fnameescape(cwd) " syntax enable filetype on filetype detect return " when going UP elseif goto_s == 'UP' call setpos(".", [ 0, input_pos[0], input_pos[0], 0]) " Open file and Search in it" " This should be done by kpsewhich: let file = matchstr(getline(input_pos[0]), '\\input\s*{\zs[^}]*\ze}') let file = atplib#append_ext(file, '.tex') let keepalt = ( @# == '' ? '' : 'keepalt' ) let open = flags_supplied =~ 'b' ? keepalt . ' edit + ' : keepalt.' edit +1 ' let swapfile = globpath(fnamemodify(file, ":h"), ( has("unix") ? "." : "" ) . fnamemodify(file, ":t") . ".swp") if !( a:call_nr == 1 && a:wrap_nr == 1 ) let open = "silent keepjumps " . open endif let projectVarDict = SaveProjectVariables() if g:atp_debugRS >= 3 silent echo "projectVarDict : " . string(projectVarDict) let g:projectVarDict = projectVarDict elseif g:atp_debugRS >= 2 let g:projectVarDict = projectVarDict endif if g:atp_debugRS >= 2 silent echo "TIME ***goto UP before open*** " . reltimestr(reltime(time0)) endif " ERROR: When opening for the first time there are two errors which " I cannot figure out. " OPEN: if empty(swapfile) || bufexists(file) if g:atp_debugRS >= 2 silent echo "Alternate (before open) " . bufname("#") endif silent! execute open . fnameescape(file) else echoerr "Recursive Search: swap file: " . swapfile . " exists. Aborting." return endif if g:atp_debugRS >= 2 exe "redir! >> ".g:atp_TempDir."/RecursiveSearch.log" silent echo "TIME ***goto UP after open*** " . reltimestr(reltime(time0)) endif call RestoreProjectVariables(projectVarDict) if g:atp_debugRS >= 2 silent echo "TIME ***goto UP restore variables *** " . reltimestr(reltime(time0)) endif if flags_supplied =~# 'b' call cursor(line("$"), col("$")) else call cursor(1,1) endif if g:atp_debugRS silent echo "In higher branch: " . file . " POS " line(".").":".col(".") silent echo "Open Command: '" . open . file . "'" silent echo "exist b:TreeOfFiles " . exists("b:TreeOfFiles") silent echo "flags_supplied: " . flags_supplied endif if g:atp_debugRS >= 2 silent echo "Alternate (after open) " . bufname("#") endif if g:atp_debugRS >= 2 silent echo "TIME_END: " . reltimestr(reltime(time0)) endif let flag = flags_supplied =~ 'W' ? flags_supplied : flags_supplied . 'W' if @# == '' keepjumps call atplib#search#RecursiveSearch(main_file, a:start_file, "", tree_of_files, expand("%:p"), a:call_nr+1, a:wrap_nr, a:winsaveview, a:bufnr, a:strftime, vim_options, cwd, pattern, flags_supplied, down_accept) else keepalt keepjumps call atplib#search#RecursiveSearch(main_file, a:start_file, "", tree_of_files, expand("%:p"), a:call_nr+1, a:wrap_nr, a:winsaveview, a:bufnr, a:strftime, vim_options, cwd, pattern, flags_supplied, down_accept) endif if g:atp_debugRS redir END endif return " when going DOWN elseif goto_s == 'DOWN' || goto_s == 'DOWN_ACCEPT' " We have to get the element in the tree one level up + line number let g:ATP_branch = "nobranch" let g:ATP_branch_line = "nobranch_line" if g:atp_debugRS silent echo " SearchInTree Args " . expand("%:p") endif if g:atp_RelativePath call atplib#search#SearchInTree(l:tree, main_file, atplib#RelativePath(expand("%:p"), resolve(b:atp_ProjectDir))) else call atplib#search#SearchInTree(l:tree, main_file, expand("%:p")) endif if g:atp_debugRS silent echo " SearchInTree found " . g:ATP_branch . " g:ATP_branch_line=" . g:ATP_branch_line endif if g:ATP_branch == "nobranch" echohl ErrorMsg echomsg "[ATP:] this probably happend while searching for \\input, it is not yet supported, if not it is a bug" echohl None silent! echomsg "Tree=" . string(l:tree) silent! echomsg "MainFile " . main_file . " current_file=" . expand("%:p") silent! echomsg "Going to file : " . g:ATP_branch . " ( g:ATP_branch ) " " restore the window and buffer! let keepalt = ( @# == '' ? '' : 'keepalt' ) silent execute keepalt. " keepjumps edit #" . a:bufnr call winrestview(a:winsaveview) if g:atp_debugRS redir END endif return endif let next_branch = atplib#FullPath(g:ATP_branch) let swapfile = globpath(fnamemodify(next_branch, ":h"), ( has("unix") ? "." : "" ) . fnamemodify(next_branch, ":t") . ".swp") let keepalt = ( @# == '' ? '' : 'keepalt' ) if a:call_nr == 1 && a:wrap_nr == 1 let open = 'silent '.keepalt.' edit +'.g:ATP_branch_line." ".fnameescape(next_branch) else let open = 'silent keepjumps '.keepalt.' edit +'.g:ATP_branch_line." ".fnameescape(next_branch) endif if g:atp_debugRS >= 2 silent echo "TIME ***goto DOWN before open*** " . reltimestr(reltime(time0)) endif let projectVarDict = SaveProjectVariables() if empty(swapfile) || bufexists(next_branch) if g:atp_debugRS >= 2 silent echo "Alternate (before open) " . bufname("#") endif silent! execute open else echoerr "Recursive Search: swap file: " . swapfile . " exists. Aborting." return endif if g:atp_debugRS >= 2 silent echo "TIME ***goto DOWN after open*** " . reltimestr(reltime(time0)) endif call RestoreProjectVariables(projectVarDict) if g:atp_debugRS >= 2 silent echo "TIME ***goto DOWN restore project variables *** " . reltimestr(reltime(time0)) endif " call cursor(g:ATP_branch_line, 1) if flags_supplied !~# 'b' keepjumps call search('\m\\input\s*{[^}]*}', 'e', line(".")) endif if g:atp_debugRS silent echo "In lower branch: " . g:ATP_branch . " branch_line=" . g:ATP_branch_line. " POS " . line(".") . ":" . col(".") silent echo "Open Command '" . open . "'" silent echo "exist b:TreeOfFiles " . exists("b:TreeOfFiles") silent echo "flags_supplied: " . flags_supplied endif if g:atp_debugRS >= 2 silent echo "Alternate (after open) " . bufname("#") endif if g:atp_debugRS > 1 silent echo "TIME_END: " . reltimestr(reltime(time0)) endif unlet g:ATP_branch unlet g:ATP_branch_line " let flag = flags_supplied =~ 'W' ? flags_supplied : flags_supplied . 'W' if goto_s == 'DOWN' if @# == '' keepjumps call atplib#search#RecursiveSearch(main_file, a:start_file, "", tree_of_files, expand("%:p"), a:call_nr+1, a:wrap_nr, a:winsaveview, a:bufnr, a:strftime, vim_options, cwd, pattern, flags_supplied) else keepalt keepjumps call atplib#search#RecursiveSearch(main_file, a:start_file, "", tree_of_files, expand("%:p"), a:call_nr+1, a:wrap_nr, a:winsaveview, a:bufnr, a:strftime, vim_options, cwd, pattern, flags_supplied) endif endif " when REJECT elseif goto_s == 'REJECT' echohl ErrorMsg echomsg "[ATP:] pattern not found" echohl None if g:atp_debugRS > 1 silent echo "TIME_END:" . reltimestr(reltime(time0)) endif " restore the window and buffer! " it is better to remember bufnumber let keepalt = ( @# == '' ? '' : 'keepalt' ) silent execute "keepjumps ".keepalt." edit #" . a:bufnr call winrestview(a:winsaveview) if g:atp_debugRS silent echo "" redir END endif " restore vim options if a:vim_options != { 'no_options' : 'no_options' } for option in keys(a:vim_options) execute "let &l:".option."=".a:vim_options[option] endfor endif exe "lcd " . fnameescape(cwd) " syntax enable filetype on filetype detect return " when ERROR elseif echohl ErrorMsg echomsg "[ATP:] this is a bug in ATP." echohl None " restore vim options if a:vim_options != { 'no_options' : 'no_options' } for option in keys(a:vim_options) execute "let &l:".option."=".a:vim_options[option] endfor endif exe "lcd " . fnameescape(cwd) " syntax enable filetype on filetype detect " restore the window and buffer! let keepalt = ( @# == '' ? '' : 'keepalt' ) silent execute "keepjumps ".keepalt." edit #" . a:bufnr call winrestview(a:winsaveview) return endif endfunction catch /E127:/ endtry " }}} " User interface to atplib#search#RecursiveSearch function. " atplib#search#GetSearchArgs {{{ " This functionn returns arguments from - a list [ pattern, flag ] " It allows to pass arguments to atplib#search#Search in a similar way to :vimgrep, :ijump, ... function! atplib#search#GetSearchArgs(Arg,flags) if a:Arg =~ '^\/' let pattern = matchstr(a:Arg, '^\/\zs.*\ze\/') let flag = matchstr(a:Arg, '\/.*\/\s*\zs['.a:flags.']*\ze\s*$') elseif a:Arg =~ '^\i' && a:Arg !~ '^\w' let pattern = matchstr(a:Arg, '^\(\i\)\zs.*\ze\1') let flag = matchstr(a:Arg, '\(\i\).*\1\s*\zs['.a:flags.']*\ze\s*$') else let pattern = matchstr(a:Arg, '^\zs\S*\ze') let flag = matchstr(a:Arg, '^\S*\s*\zs['.a:flags.']*\ze\s*$') endif return [ pattern, flag ] endfunction "}}} " {{{ Search() try function! atplib#search#Search(Bang, Arg) let atp_MainFile = atplib#FullPath(b:atp_MainFile) let [ pattern, flag ] = atplib#search#GetSearchArgs(a:Arg, 'bceswW') let g:pattern = pattern if pattern == "" echohl ErrorMsg echomsg "[ATP:] enclose the pattern with /.../" echohl None return endif if a:Bang == "!" || !exists("b:TreeOfFiles") call atplib#search#RecursiveSearch(atp_MainFile, expand("%:p"), 'make_tree', '', expand("%:p"), 1, 1, winsaveview(), bufnr("%"), reltime(), { 'no_options' : 'no_options' }, 'no_cwd', pattern, flag) else call atplib#search#RecursiveSearch(atp_MainFile, expand("%:p"), '', deepcopy(b:TreeOfFiles), expand("%:p"), 1, 1, winsaveview(), bufnr("%"), reltime(), { 'no_options' : 'no_options' }, 'no_cwd', pattern, flag) endif endfunction catch /E127: Cannot redefine function/ endtry " }}} function! atplib#search#ATP_ToggleNn(...) " {{{ let on = ( a:0 >=1 ? ( a:1 == 'on' ? 1 : 0 ) : !g:atp_mapNn ) let g:on = on if !on silent! nunmap n silent! nunmap N silent! aunmenu LaTeX.Toggle\ Nn\ [on] let g:atp_mapNn = 0 nmenu 550.79 &LaTeX.Toggle\ &Nn\ [off]:ToggleNn :ToggleNn imenu 550.79 &LaTeX.Toggle\ &Nn\ [off]:ToggleNn :ToggleNna tmenu LaTeX.Toggle\ Nn\ [off] atp maps to n,N. echomsg "[ATP:] vim nN maps" else silent! nmap n RecursiveSearchn silent! nmap N RecursiveSearchN silent! aunmenu LaTeX.Toggle\ Nn\ [off] let g:atp_mapNn = 1 nmenu 550.79 &LaTeX.Toggle\ &Nn\ [on]:ToggleNn :ToggleNn imenu 550.79 &LaTeX.Toggle\ &Nn\ [on]:ToggleNn :ToggleNna tmenu LaTeX.Toggle\ Nn\ [on] n,N vim normal commands. echomsg "[ATP:] atp nN maps" endif endfunction function! atplib#search#SearchHistCompletion(ArgLead, CmdLine, CursorPos) let search_history=[] let hist_entry = histget("search") let nr = 0 while hist_entry != "" call add(search_history, hist_entry) let nr -= 1 let hist_entry = histget("search", nr) endwhile return filter(search_history, "v:val =~# '^'.a:ArgLead") endfunction "}}} "}}} " These are only variables and front end functions for Bib Search Engine of ATP. " Search engine is define in autoload/atplib.vim script library. "{{{ Bibliography Search "-------------SEARCH IN BIBFILES ---------------------- " This function counts accurence of a:keyword in string a:line, " there are two methods keyword is a string to find (a:1=0)or a pattern to " match, the pattern used to is a:keyword\zs.* to find the place where to cut. " DEBUG: " command -buffer -nargs=* Count :echo atplib#count() " Front End Function " {{{ BibSearch " There are three arguments: {pattern}, [flags, [choose]] function! atplib#search#BibSearch(bang,...) " let pattern = a:0 >= 1 ? a:1 : "" " let flag = a:0 >= 2 ? a:2 : "" let time=reltime() let Arg = ( a:0 >= 1 ? a:1 : "" ) if Arg != "" let [ pattern, flag ] = atplib#search#GetSearchArgs(Arg, 'aetbjsynvpPNShouH@BcpmMtTulL') else let [ pattern, flag ] = [ "", ""] endif let b:atp_LastBibPattern = pattern " This cannot be set here. It is set later by atplib#bibsearch#showresults function. " let b:atp_LastBibFlags = flag let @/ = pattern if g:atp_debugBS exe "redir! > ".g:atp_TempDir."/Bibsearch.log" silent! echo "==========BibSearch==========================" silent! echo "b:BibSearch_pattern=" . pattern silent! echo "b:BibSearch bang=" . a:bang silent! echo "b:BibSearch flag=" . flag let g:BibSearch_pattern = pattern let g:BibSearch_bang = a:bang let g:BibSearch_flag = flag redir END endif if !exists("s:bibdict") || a:bang == "!" let s:bibdict={} if !exists("b:ListOfFiles") || !exists("b:TypeDict") || a:bang == "!" call TreeOfFiles(b:atp_MainFile) endif for file in b:ListOfFiles if b:TypeDict[file] == "bib" let s:bibdict[file]=readfile(file) endif endfor endif let b:atp_BibFiles=keys(s:bibdict) " let g:bibdict=s:bibdict if has("python") && g:atp_bibsearch == "python" call atplib#bibsearch#showresults( atplib#bibsearch#searchbib_py(pattern, keys(s:bibdict), a:bang), flag, pattern, s:bibdict) else call atplib#bibsearch#showresults( atplib#bibsearch#searchbib(pattern, s:bibdict, a:bang), flag, pattern, s:bibdict) endif let g:time_BibSearch=reltimestr(reltime(time)) endfunction " }}} "}}} " Other Searching Tools: " {{{1 atplib#search#KpsewhichGlobPath " a:format is the format as reported by kpsewhich --help " a:path path if set to "", then kpse which will find the path. " The default is what 'kpsewhich -show-path tex' returns " with "**" appended. " a:name can be "*" then finds all files with the given extension " or "*.cls" to find all files with a given extension. " a:1 modifiers (the default is ":t:r") " a:2 filters path names matching the pattern a:1 " a:3 filters out path names not matching the pattern a:2 " " Argument a:path was added because it takes time for kpsewhich to return the " path (usually ~0.5sec). ATP asks kpsewhich on start up " (g:atp_kpsewhich_tex) and then locks the variable (this will work " unless sb is reinstalling tex (with different personal settings, " changing $LOCALTEXMF) during vim session - not that often). " " Example: call atplib#search#KpsewhichGlobPath('tex', '', '*', ':p', '^\(\/home\|\.\)','\%(texlive\|kpsewhich\|generic\)') " gives on my system only the path of current dir (/.) and my localtexmf. " this is done in 0.13s. The long pattern is to " " atplib#search#KpsewhichGlobPath({format}, {path}, {expr=name}, [ {mods}, {pattern_1}, {pattern_2}]) function! atplib#search#KpsewhichGlobPath(format, path, name, ...) " let time = reltime() let modifiers = a:0 == 0 ? ":t:r" : a:1 if a:path == "" let path = substitute(substitute(system("kpsewhich -show-path ".a:format ),'!!','','g'),'\/\/\+','\/','g') let path = substitute(path,':\|\n',',','g') let path_list = split(path, ',') let idx = index(path_list, '.') if idx != -1 let dot = remove(path_list, index(path_list,'.')) . "," else let dot = "" endif call map(path_list, 'v:val . "**"') let path = dot . join(path_list, ',') else let path = a:path endif " If a:2 is non zero (if not given it is assumed to be 0 for compatibility " reasons) if get(a:000, 1, 0) != "0" let path_list = split(path, ',') call filter(path_list, 'v:val =~ a:2') let path = join(path_list, ',') endif if get(a:000, 2, 0) != "0" let path_list = split(path, ',') call filter(path_list, 'v:val !~ a:3') let path = join(path_list, ',') endif let list = split(globpath(path, a:name),"\n") call map(list, 'fnamemodify(v:val, modifiers)') return list endfunction " }}}1 " {{{1 atplib#search#KpsewhichFindFile " the arguments are similar to atplib#KpsewhichGlob except that the a:000 list " is shifted: " a:1 = path " if set to "" then kpsewhich will find the path. " a:2 = count (as for findfile()) " when count < 0 returns a list of all files found " a:3 = modifiers " a:4 = positive filter for path (see KpsewhichGLob a:1) " a:5 = negative filter for path (see KpsewhichFind a:2) " " needs +path_extra vim feature " " atp#KpsewhichFindFile({format}, {expr=name}, [{path}, {count}, {mods}, {pattern_1}, {pattern_2}]) function! atplib#search#KpsewhichFindFile(format, name, ...) " Unset the suffixadd option let saved_sua = &l:suffixesadd let &l:sua = "" " let time = reltime() let path = a:0 >= 1 ? a:1 : "" let l:count = a:0 >= 2 ? a:2 : 0 let modifiers = a:0 >= 3 ? a:3 : "" " This takes most of the time! if path == "" let path = substitute(substitute(system("kpsewhich -show-path ".a:format ),'!!','','g'),'\/\/\+','\/','g') let path = substitute(path,':\|\n',',','g') let path_list = split(path, ',') let idx = index(path_list, '.') if idx != -1 let dot = remove(path_list, index(path_list,'.')) . "," else let dot = "" endif call map(path_list, 'v:val . "**"') let path = dot . join(path_list, ',') unlet path_list endif " If a:2 is non zero (if not given it is assumed to be 0 for compatibility " reasons) if get(a:000, 3, 0) != 0 let path_list = split(path, ',') call filter(path_list, 'v:val =~ a:4') let path = join(path_list, ',') endif if get(a:000, 4, 0) != 0 let path_list = split(path, ',') call filter(path_list, 'v:val !~ a:5') let path = join(path_list, ',') endif if l:count >= 1 let result = findfile(a:name, path, l:count) elseif l:count == 0 let result = findfile(a:name, path) elseif l:count < 0 let result = findfile(a:name, path, -1) endif if l:count >= 0 && modifiers != "" let result = fnamemodify(result, modifiers) elseif l:count < 0 && modifiers != "" call map(result, 'fnamemodify(v:val, modifiers)') endif let &l:sua = saved_sua return result endfunction " }}}1 " atplib#search#SearchPackage {{{1 " " This function searches if the package in question is declared or not. " Returns the line number of the declaration or 0 if it was not found. " " It was inspired by autex function written by Carl Mueller, math at carlm e4ward c o m " and made work for project files using lvimgrep. " " This function doesn't support plaintex files (\\input{}) " ATP support plaintex input lines in a different way (but not that flexible " as this: for plaintex I use atplib#GrepPackageList on startup (only!) and " then match input name with the list). " " name = package name (tikz library name) " a:1 = stop line (number of the line \\begin{document} " a:2 = pattern matching the command (without '^[^%]*\\', just the name) " to match \usetikzlibrary{...,..., - function! atplib#search#SearchPackage(name,...) let atp_MainFile = atplib#FullPath(b:atp_MainFile) if !filereadable(atp_MainFile) silent echomsg "[ATP:] atp_MainFile : " . atp_MainFile . " is not readable " return endif let cwd = getcwd() if exists("b:atp_ProjectDir") && getcwd() != b:atp_ProjectDir exe "lcd " . fnameescape(b:atp_ProjectDir) endif if getbufvar("%", "atp_MainFile") == "" call SetProjectName() endif " let time = reltime() " if bufloaded("^" . a:file . "$") " let file=getbufline("^" . a:file . "$", "1", "$") " else " let file=readfile(a:filename) " endif if a:0 != 0 let stop_line = a:1 else if expand("%:p") == atp_MainFile let saved_pos=getpos(".") keepjumps call setpos(".", [0,1,1,0]) keepjumps let stop_line=search('\\begin\s*{\s*document\s*}','nW') else if &l:filetype == 'tex' let saved_loclist = getloclist(0) silent! execute '1lvimgrep /\\begin\s*{\s*document\s*}/j ' . fnameescape(atp_MainFile) let stop_line = get(get(getloclist(0), 0, {}), 'lnum', 0) call setloclist(0, saved_loclist) else let stop_line = 0 endif endif endif let com = a:0 >= 2 ? a:2 : 'usepackage\s*\%(\[[^\]]*\]\?\)\?' " If the current file is the atp_MainFile if expand("%:p") == atp_MainFile if !exists("saved_pos") let saved_pos=getpos(".") endif if stop_line != 0 keepjumps call setpos(".",[0,1,1,0]) keepjumps let ret = search('\C^[^%]*\\'.com."\s*{[^}]*".a:name,'ncW', stop_line) keepjump call setpos(".",saved_pos) exe "lcd " . fnameescape(cwd) return ret else keepjumps call setpos(".",[0,1,1,0]) keepjumps let ret = search('\C^[^%]*\\'.com."\s*{[^}]*".a:name,'ncW') keepjump call setpos(".", saved_pos) exe "lcd " . fnameescape(cwd) return ret endif " If the current file is not the mainfile else " Cache the Preambule / it is not changing so this is completely safe / if !exists("s:Preambule") let s:Preambule = readfile(atp_MainFile) if stop_line != 0 silent! call remove(s:Preambule, stop_line+1, -1) endif endif let lnum = 1 for line in s:Preambule if line =~ '^[^%]*\\'.com."\s*{[^}]*\C".a:name " echo reltimestr(reltime(time)) exe "lcd " . fnameescape(cwd) return lnum endif let lnum += 1 endfor endif " echo reltimestr(reltime(time)) " If the package was not found return 0 exe "lcd " . fnameescape(cwd) return 0 endfunction " }}}1 "{{{1 atplib#search#GrepPackageList " This function returns list of packages declared in the b:atp_MainFile (or " a:2). If the filetype is plaintex it returns list of all \input{} files in " the b:atp_MainFile. " I'm not shure if this will be OK for project files written in plaintex: Can " one declare a package in the middle of document? probably yes. So it might " be better to use TreeOfFiles in that case. " This takes =~ 0.02 s. This is too long to call it in complete#TabCompletion. function! atplib#search#GrepPackageList(...) " let time = reltime() let file = a:0 >= 2 ? a:2 : getbufvar("%", "atp_MainFile") let pat = a:0 >= 1 ? a:1 : '' if file == "" return [] endif let ftype = getbufvar(file, "&filetype") if pat == '' if ftype =~ '^\(ams\)\=tex$' let pat = '\\usepackage\s*\(\[[^]]*\]\)\=\s*{' elseif ftype == 'plaintex' let pat = '\\input\s*{' else " echoerr "ATP doesn't recognize the filetype " . &l:filetype . ". Using empty list of packages." return [] endif endif let saved_loclist = getloclist(0) try silent execute 'lvimgrep /^[^%]*'.pat.'/j ' . fnameescape(file) catch /E480:/ call setloclist(0, [{'text' : 'empty' }]) endtry let loclist = getloclist(0) call setloclist(0, saved_loclist) let pre = map(loclist, 'v:val["text"]') let pre_l = [] for line in pre let package_l = matchstr(line, pat.'\zs[^}]*\ze}') call add(pre_l, package_l) endfor " We make a string of packages separeted by commas and the split it " (compatibility with \usepackage{package_1,package_2,...}) let pre_string = join(pre_l, ',') let pre_list = split(pre_string, ',') call filter(pre_list, "v:val !~ '^\s*$'") " echo reltimestr(reltime(time)) return pre_list endfunction "{{{1 atplib#search#GrepPreambule function! atplib#search#GrepPreambule(pattern, ...) let saved_loclist = getloclist(0) let atp_MainFile = ( a:0 >= 1 ? a:1 : b:atp_MainFile ) let winview = winsaveview() exe 'silent! 1lvimgrep /^[^%]*\\begin\s*{\s*document\s*}/j ' . fnameescape(atp_MainFile) let linenr = get(get(getloclist(0), 0, {}), 'lnum', 'nomatch') if linenr == "nomatch" call setloclist(0, saved_loclist) return endif exe 'silent! lvimgrep /'.a:pattern.'\%<'.linenr.'l/jg ' . fnameescape(atp_MainFile) let matches = getloclist(0) call setloclist(0, saved_loclist) return matches endfunction " atplib#search#DocumentClass {{{1 function! atplib#search#DocumentClass(file) let saved_loclist = getloclist(0) try silent execute 'lvimgrep /\\documentclass/j ' . fnameescape(a:file) catch /E480:/ return 0 catch /E680:/ return 0 catch /E683:/ return 0 endtry let line = get(get(getloclist(0), 0, { 'text' : "no_document_class"}), 'text') call setloclist(0, saved_loclist) if line != 'no_document_class' return substitute(l:line,'.*\\documentclass\s*\%(\[.*\]\)\?{\(.*\)}.*','\1','') endif return 0 endfunction " }}}1 " Make a tree of input files. " {{{ atplib#search#TreeOfFiles_vim " this is needed to make backward searching. " It returns: " [ {tree}, {list}, {type_dict}, {level_dict} ] " where {tree}: " is a tree of files of the form " { file : [ subtree, linenr ] } " where the linenr is the linenr of \input{file} iline the one level up " file. " {list}: " is just list of all found input files (except the main file!). " {type_dict}: " is a dictionary of types for files in {list} " type is one of: preambule, input, bib. " " {flat} = 1 do not be recursive " {flat} = 0 the deflaut be recursive for input files (not bib and not preambule) " bib and preambule files are not added to the tree " {flat} = -1 include input and premabule files into the tree " " TreeOfFiles({main_file}, [{pattern}, {flat}, {run_nr}]) " debug file - /tmp/tof_log " a:main_file is the main file to start with function! atplib#search#TreeOfFiles_vim(main_file,...) " let time = reltime() let atp_MainFile = atplib#FullPath(b:atp_MainFile) if !exists("b:atp_OutDir") call atplib#common#SetOutDir(0, 1) endif let tree = {} " flat = do a flat search, i.e. fo not search in input files at all. let flat = a:0 >= 2 ? a:2 : 0 " This prevents from long runs on package files " for example babel.sty has lots of input files. if expand("%:e") != 'tex' return [ {}, [], {}, {} ] endif let run_nr = a:0 >= 3 ? a:3 : 1 let biblatex = 0 " Adjust g:atp_inputfile_pattern if it is not set right if run_nr == 1 let pattern = '^[^%]*\\\(input\s*{\=\|include\s*{' if '\subfile{' !~ g:atp_inputfile_pattern && atplib#search#SearchPackage('subfiles') let pattern .= '\|subfiles\s*{' endif let biblatex = atplib#search#SearchPackage('biblatex') if biblatex " If biblatex is present, search for bibliography files only in the " preambule. if '\addbibresource' =~ g:atp_inputfile_pattern || '\addglobalbib' =~ g:atp_inputfile_pattern || '\addsectionbib' =~ g:atp_inputfile_pattern || '\bibliography' =~ g:atp_inputfile_pattern echo "[ATP:] You might remove biblatex patterns from g:atp_inputfile_pattern if you use biblatex package." endif let biblatex_pattern = '^[^%]*\\\%(bibliography\s*{\|addbibresource\s*\%(\[[^]]*\]\)\?\s*{\|addglobalbib\s*\%(\[[^]]*\]\)\?\s*{\|addsectionbib\s*\%(\[[^]]*\]\)\?\s*{\)' else let pattern .= '\|bibliography\s*{' endif let pattern .= '\)' endif let pattern = a:0 >= 1 ? a:1 : g:atp_inputfile_pattern if g:atp_debugToF if exists("g:atp_TempDir") if run_nr == 1 exe "redir! > ".g:atp_TempDir."/TreeOfFiles.log" else exe "redir! >> ".g:atp_TempDir."/TreeOfFiles.log" endif endif endif if g:atp_debugToF silent echo run_nr . ") |".a:main_file."| expand=".expand("%:p") endif if run_nr == 1 let cwd = getcwd() exe "lcd " . fnameescape(b:atp_ProjectDir) endif let line_nr = 1 let ifiles = [] let list = [] let type_dict = {} let level_dict = {} let saved_llist = getloclist(0) if run_nr == 1 && &l:filetype =~ '^\(ams\)\=tex$' try silent execute 'lvimgrep /\\begin\s*{\s*document\s*}/j ' . fnameescape(a:main_file) catch /E480:/ endtry let end_preamb = get(get(getloclist(0), 0, {}), 'lnum', 0) call setloclist(0,[]) if biblatex try silent execute 'lvimgrep /'.biblatex_pattern.'\%<'.end_preamb.'l/j ' . fnameescape(a:main_file) catch /E480:/ endtry endif else let end_preamb = 0 call setloclist(0,[]) endif try silent execute "lvimgrepadd /".pattern."/jg " . fnameescape(a:main_file) catch /E480:/ " catch /E683:/ " let g:pattern = pattern " let g:filename = fnameescape(a:main_file) endtry let loclist = getloclist(0) call setloclist(0, saved_llist) let lines = map(loclist, "[ v:val['text'], v:val['lnum'], v:val['col'] ]") if g:atp_debugToF silent echo run_nr . ") Lines: " .string(lines) endif for entry in lines let [ line, lnum, cnum ] = entry " input name (iname) as appeared in the source file let iname = substitute(matchstr(line, pattern . '\(''\|"\)\=\zs\f\%(\f\|\s\)*\ze\1\='), '\s*$', '', '') if iname == "" && biblatex let iname = substitute(matchstr(line, biblatex_pattern . '\(''\|"\)\=\zs\f\%(\f\|\s\)*\ze\1\='), '\s*$', '', '') endif if g:atp_debugToF silent echo run_nr . ") iname=".iname endif if line =~ '{\s*' . iname let iname = substitute(iname, '\\\@\|\\addglobalbib\>\|\\addsectionbib\>\|\\addbibresource\>\)' let type = "bib" elseif lnum < end_preamb && run_nr == 1 let type = "preambule" else let type = "input" endif if g:atp_debugToF silent echo run_nr . ") type=" . type endif let inames = [] if type != "bib" let inames = [ atplib#append_ext(iname, '.tex') ] else let inames = map(split(iname, ','), "atplib#append_ext(v:val, '.bib')") endif if g:atp_debugToF silent echo run_nr . ") inames " . string(inames) endif " Find the full path only if it is not already given. for iname in inames let saved_iname = iname if iname != fnamemodify(iname, ":p") if type != "bib" let iname = atplib#search#KpsewhichFindFile('tex', iname, b:atp_OutDir . "," . g:atp_texinputs , 1, ':p', '^\%(\/home\|\.\)', '\(^\/usr\|texlive\|kpsewhich\|generic\|miktex\)') else let iname = atplib#search#KpsewhichFindFile('bib', iname, b:atp_OutDir . "," . g:atp_bibinputs , 1, ':p') endif endif if fnamemodify(iname, ":t") == "" let iname = expand(saved_iname, ":p") endif if g:atp_debugToF silent echo run_nr . ") iname " . string(iname) endif if g:atp_RelativePath let iname = atplib#RelativePath(iname, (fnamemodify(resolve(b:atp_MainFile), ":h"))) endif call add(ifiles, [ iname, lnum] ) call add(list, iname) call extend(type_dict, { iname : type } ) call extend(level_dict, { iname : run_nr } ) endfor endfor if g:atp_debugToF silent echo run_nr . ") list=".string(list) endif " Be recursive if: flat is off, file is of input type. if !flat || flat <= -1 for [ifile, line] in ifiles if type_dict[ifile] == "input" && flat <= 0 || ( type_dict[ifile] == "preambule" && flat <= -1 ) let [ ntree, nlist, ntype_dict, nlevel_dict ] = atplib#search#TreeOfFiles_vim(ifile, pattern, flat, run_nr+1) call extend(tree, { ifile : [ ntree, line ] } ) call extend(list, nlist, index(list, ifile)+1) call extend(type_dict, ntype_dict) call extend(level_dict, nlevel_dict) endif endfor else " Make the flat tree for [ ifile, line ] in ifiles call extend(tree, { ifile : [ {}, line ] }) endfor endif " Showing time takes ~ 0.013sec. " if run_nr == 1 " echomsg "TIME:" . join(reltime(time), ".") . " main_file:" . a:main_file " endif let [ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ] = deepcopy([ tree, list, type_dict, level_dict]) " restore current working directory if run_nr == 1 exe "lcd " . fnameescape(cwd) endif if g:atp_debugToF && run_nr == 1 silent! echo "========TreeOfFiles========================" silent! echo "TreeOfFiles b:ListOfFiles=" . string(b:ListOfFiles) redir END endif return [ tree, list, type_dict, level_dict ] endfunction "}}} " atplib#search#TreeOfFiles_py "{{{ function! atplib#search#TreeOfFiles_py(main_file) let time=reltime() let project_dir = getbufvar(a:main_file, 'atp_ProjectDir') python << END_PYTHON import vim, re, subprocess, os, glob filename=vim.eval('a:main_file') relative_path=vim.eval('g:atp_RelativePath') project_dir=vim.eval('project_dir') def vim_remote_expr(servername, expr): # Send to vim server, # expr must be well quoted: # vim_remote_expr('GVIM', "atplib#callback#TexReturnCode()") cmd=[options.progname, '--servername', servername, '--remote-expr', expr] subprocess.Popen(cmd, stdout=subprocess.PIPE).wait() def isnonempty(string): if str(string) == "": return False else: return True def scan_preambule(file, pattern): # scan_preambule for a pattern # file is list of lines for line in file: ret=re.search(pattern, line) if ret: return True elif re.search('\\\\begin\s*{\s*document\s*}', line): return False return False def preambule_end(file): # find linenr where preambule ends, # file is list of lines nr=1 for line in file: if re.search('\\\\begin\s*{\s*document\s*}', line): return nr nr+=1 return 0 def addext(string, ext): # the pattern is not matching .tex extension read from file. if not re.search("\."+ext+"$", string): return string+"."+ext else: return string def kpsewhich_path(format): # find fname of format in path given by kpsewhich, kpsewhich=subprocess.Popen(['kpsewhich', '-show-path', format], stdout=subprocess.PIPE) kpsewhich.wait() path=kpsewhich.stdout.read() path=re.sub("!!", "",path) path=re.sub("\/\/+", "/", path) path=re.sub("\n", "",path) path_list=path.split(":") return path_list def kpsewhich_find(file, path_list): results=[] for path in path_list: found=glob.glob(os.path.join(path, file)) results.extend(found) found=glob.glob(os.path.join(path, file)) results.extend(found) return results def scan_file(file, fname, pattern, bibpattern): # scan file for a pattern, return all groups, # file is a list of lines, matches_d={} matches_l=[] nr = 0 for line in file: nr+=1 match_all=re.findall(pattern, line) if len(match_all) > 0: for match in match_all: for m in match: if str(m) != "": m=addext(m, "tex") if not os.access(m, os.F_OK): try: m=kpsewhich_find(m, tex_path)[0] except IndexError: pass elif relative_path == "0": m=os.path.join(project_dir,m) if fname == filename and nr < preambule_end: matches_d[m]=[m, fname, nr, 'preambule'] matches_l.append(m) else: matches_d[m]=[m, fname, nr, 'input'] matches_l.append(m) match_all=re.findall(bibpattern, line) if len(match_all) > 0: for match in match_all: if str(match) != "": for m in match.split(','): m=addext(m, "bib") if not os.access(m, os.F_OK): m=kpsewhich_find(m, bib_path)[0] matches_d[m]=[m, fname, nr, 'bib'] matches_l.append(m) return [ matches_d, matches_l ] def tree(file, level, pattern, bibpattern): # files - list of file names to scan, try: file_ob = open(file, 'r') except IOError: if re.search('\.bib$', file): path=bib_path else: path=tex_path try: file=kpsewhich_find(file, path)[0] except IndexError: pass try: file_ob = open(file, 'r') except IOError: return [ {}, [], {}, {} ] file_l = file_ob.read().split("\n") file_ob.close() [found, found_l] =scan_file(file_l, file, pattern, bibpattern) t_list=[] t_level={} t_type={} t_tree={} for item in found_l: t_list.append(item) t_level[item]=level t_type[item]=found[item][3] i_list=[] for file in t_list: if found[file][3]=="input": i_list.append(file) for file in i_list: [ n_tree, n_list, n_type, n_level ] = tree(file, level+1, pattern, bibpattern) for f in n_list: t_list.append(f) t_type[f] =n_type[f] t_level[f] =n_level[f] t_tree[file] = [ n_tree, found[file][2] ] return [ t_tree, t_list, t_type, t_level ] try: mainfile_ob = open(filename, 'r') mainfile = mainfile_ob.read().split("\n") mainfile_ob.close() if scan_preambule(mainfile, re.compile('\\\\usepackage\s*\[.*\]\s*{\s*subfiles\s*}')): pat_str='^[^%]*(?:\\\\input\s+([\w_\-\.]*)|\\\\(?:input|include(?:only)?|subfiles)\s*{([^}]*)})' pattern=re.compile(pat_str) else: pat_str='^[^%]*(?:\\\\input\s+([\w_\-\.]*)|\\\\(?:input|include(?:only)?)\s*{([^}]*)})' pattern=re.compile(pat_str) bibpattern=re.compile('^[^%]*\\\\(?:bibliography|addbibresource|addsectionbib(?:\s*\[.*\])?|addglobalbib(?:\s*\[.*\])?)\s*{([^}]*)}') bib_path=kpsewhich_path('bib') tex_path=kpsewhich_path('tex') preambule_end=preambule_end(mainfile) # Make TreeOfFiles: [ tree_of_files, list_of_files, type_dict, level_dict]= tree(filename, 1, pattern, bibpattern) vim.command("let b:TreeOfFiles="+str(tree_of_files)) vim.command("let b:ListOfFiles="+str(list_of_files)) vim.command("let b:TypeDict="+str(type_dict)) vim.command("let b:LevelDict="+str(level_dict)) except IOError: vim.command("let b:TreeOfFiles={}") vim.command("let b:ListOfFiles=[]") vim.command("let b:TypeDict={}") vim.command("let b:LevelDict={}") END_PYTHON let g:time_TreeOfFiles_py=reltimestr(reltime(time)) endfunction "}}} " This function finds all the input and bibliography files declared in the source files (recursive). " {{{ atplib#search#FindInputFiles " Returns a dictionary: " { : [ 'bib', 'main file', 'full path' ] } " with the same format as the output of FindInputFiles " a:MainFile - main file (b:atp_MainFile) " a:1 = 0 [1] - use cached values of tree of files. function! atplib#search#FindInputFiles(MainFile,...) " let time=reltime() call atplib#write() let cached_Tree = a:0 >= 1 ? a:1 : 0 let saved_llist = getloclist(0) call setloclist(0, []) if cached_Tree && exists("b:TreeOfFiles") let [ TreeOfFiles, ListOfFiles, DictOfFiles, LevelDict ]= deepcopy([ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ]) else if &filetype == "plaintex" let flat = 1 else let flat = 0 endif let [ TreeOfFiles, ListOfFiles, DictOfFiles, LevelDict ]= TreeOfFiles(fnamemodify(a:MainFile, ":p"), g:atp_inputfile_pattern, flat) " Update the cached values: let [ b:TreeOfFiles, b:ListOfFiles, b:TypeDict, b:LevelDict ] = deepcopy([ TreeOfFiles, ListOfFiles, DictOfFiles, LevelDict ]) endif let AllInputFiles = keys(filter(copy(DictOfFiles), " v:val == 'input' || v:val == 'preambule' ")) let AllBibFiles = keys(filter(copy(DictOfFiles), " v:val == 'bib' ")) let b:AllInputFiles = deepcopy(AllInputFiles) let b:AllBibFiles = deepcopy(AllBibFiles) let b:atp_BibFiles = copy(b:AllBibFiles) " this variable will store unreadable bibfiles: let NotReadableInputFiles=[] " this variable will store the final result: let Files = {} for File in ListOfFiles let File_Path = atplib#FullPath(File) if filereadable(File) call extend(Files, \ { fnamemodify(File_Path,":t:r") : [ DictOfFiles[File] , fnamemodify(a:MainFile, ":p"), File_Path ] }) else " echo warning if a bibfile is not readable " echohl WarningMsg | echomsg "File " . File . " not found." | echohl None if count(NotReadableInputFiles, File_Path) == 0 call add(NotReadableInputFiles, File_Path) endif endif endfor let g:NotReadableInputFiles = NotReadableInputFiles " return the list of readable bibfiles " let g:time_FindInputFiles=reltimestr(reltime(time)) return Files endfunction function! atplib#search#UpdateMainFile() if b:atp_MainFile =~ '^\s*\/' let cwd = getcwd() exe "lcd " . fnameescape(b:atp_ProjectDir) let b:atp_MainFile = ( g:atp_RelativePath ? fnamemodify(b:atp_MainFile, ":.") : b:atp_MainFile ) exe "lcd " . fnameescape(cwd) else let b:atp_MainFile = ( g:atp_RelativePath ? b:atp_MainFile : atplib#FullPath(b:atp_MainFile) ) endif return endfunction "}}} " vim:fdm=marker:tw=85:ff=unix:noet:ts=8:sw=4:fdc=1 autoload/atplib/tools.vim [[[1 511 " Title: Vim library for ATP filetype plugin. " Author: Marcin Szamotulski " Email: mszamot [AT] gmail [DOT] com " Note: This file is a part of Automatic Tex Plugin for Vim. " URL: https://launchpad.net/automatictexplugin " Language: tex " Open Function: "{{{1 atplib#tools#Open " a:1 - pattern or a file name " a:1 is regarded as a filename if filereadable(pattern) is non " zero. function! atplib#tools#Open(bang, dir, TypeDict, ...) if a:dir == "0" echohl WarningMsg echomsg "You have to set g:atp_LibraryPath in your vimrc or atprc file." echohl None return endif let pattern = ( a:0 >= 1 ? a:1 : "") let file = filereadable(pattern) ? pattern : "" if file == "" if a:bang == "!" || !exists("g:atp_Library") let g:atp_Library = filter(split(globpath(a:dir, "*"), "\n"), 'count(keys(a:TypeDict), fnamemodify(v:val, ":e"))') let found = deepcopy(g:atp_Library) else let found = deepcopy(g:atp_Library) endif call filter(found, "fnamemodify(v:val, ':t') =~ pattern") " Resolve symlinks: call map(found, "resolve(v:val)") " Remove double entries: call filter(found, "count(found, v:val) == 1") if len(found) > 1 echohl Title echo "Found files:" echohl None let i = 1 for file in found if len(map(copy(found), "v:val =~ escape(fnamemodify(file, ':t'), '~') . '$'")) == 1 echo i . ") " . fnamemodify(file, ":t") else echo i . ") " . pathshorten(fnamemodify(file, ":p")) endif let i+=1 endfor let choice = input("Which file to open? ")-1 if choice == -1 return endif let file = found[choice] elseif len(found) == 1 let file = found[0] else echohl WarningMsg echomsg "[ATP:] Nothing found." echohl None return endif endif let ext = fnamemodify(file, ":e") let viewer = get(a:TypeDict, ext, 0) if viewer == '0' echomsg "\n" echomsg "[ATP:] filetype: " . ext . " is not supported, add an entry to g:atp_OpenTypeDict" return endif if viewer !~ '^\s*cat\s*$' && viewer !~ '^\s*g\=vim\s*$' && viewer !~ '^\s*edit\s*$' && viewer !~ '^\s*tabe\s*$' && viewer !~ '^\s*split\s*$' call system(viewer . " '" . file . "' &") elseif viewer =~ '^\s*g\=vim\s*$' || viewer =~ '^\s*tabe\s*$' exe "tabe " . fnameescape(file) setl nospell elseif viewer =~ '^\s*edit\s*$' || viewer =~ '^\s*split\s*$' exe viewer . " " . fnameescape(file) setl nospell elseif viewer == '^\s*cat\s*' redraw! echohl Title echo "cat '" . file . "'" echohl None echo system(viewer . " '" . file . "' &") endif " if fnamemodify(file, ":t") != "" && count(g:atp_open_completion, fnamemodify(file, ":t")) == 0 " call extend(g:atp_open_completion, [fnamemodify(file, ":t")], 0) " endif " This removes the hit Enter vim prompt. call feedkeys("") return endfunction "}}}1 " Labels Tools: GrepAuxFile, SrotLabels, generatelabels and showlabes. " {{{1 LABELS " the argument should be: resolved full path to the file: " resove(fnamemodify(bufname("%"),":p")) " {{{2 --------------- atplib#tools#GrepAuxFile " This function searches in aux file (actually it tries first ._aux file, " made by compile.py - this is because compile.py is copying aux file only if " there are no errors (for to not affect :Labels command) function! atplib#tools#GrepAuxFile(...) " Aux file to read: let base = ( a:0 >= 1 ? fnamemodify(a:1, ":r") : fnamemodify(b:atp_MainFile, ":r") ) let aux_filename = base."._aux" if !filereadable(aux_filename) let aux_filename = a:1 if !filereadable(a:1) && exists("b:atp_MainFile") let aux_filename = fnamemodify(atplib#FullPath(b:atp_MainFile), ":r") . "._aux" if !filereadable(aux_filename) let aux_filename = fnamemodify(atplib#FullPath(b:atp_MainFile), ":r") . ".aux" else echoerr "[ATP] aux file not found (atplib#tools#GrepAuxFile)." endif endif endif let tex_filename = fnamemodify(aux_filename, ":r") . ".tex" if !filereadable(aux_filename) " We should worn the user that there is no aux file " /this is not visible ! only after using the command 'mes'/ echohl WarningMsg echomsg "[ATP:] there is no aux file. Run ".b:atp_TexCompiler." first." echohl None return [] " CALL BACK is not working " I can not get output of: vim --servername v:servername --remote-expr v:servername " for v:servername " Here we should run latex to produce auxfile " echomsg "Running " . b:atp_TexCompiler . " to get aux file." " let labels = system(b:atp_TexCompiler . " -interaction nonstopmode " . atp_MainFile . " 1&>/dev/null 2>1 ; " . " vim --servername ".v:servername." --remote-expr 'atplib#tools#GrepAuxFile()'") " return labels endif " let aux_file = readfile(aux_filename) let saved_llist = getloclist(0) if bufloaded(aux_filename) exe "silent! bd! " . bufnr(aux_filename) endif try silent execute 'lvimgrep /\\newlabel\s*{/j ' . fnameescape(aux_filename) catch /E480:/ endtry let loc_list = getloclist(0) call setloclist(0, saved_llist) call map(loc_list, ' v:val["text"]') let labels = [] if g:atp_debugGAF let g:gaf_debug = {} endif " Equation counter depedns on the option \numberwithin{equation}{section} " /now this only supports article class. let equation = len(atplib#search#GrepPreambule('^\s*\\numberwithin{\s*equation\s*}{\s*section\s*}', tex_filename)) " for line in aux_file for line in loc_list if line =~ '\\newlabel\>' " line is of the form: " \newlabel{