diff --git a/autoload/vimtex/options.vim b/autoload/vimtex/options.vim index 8f62d24121..e329694b8b 100644 --- a/autoload/vimtex/options.vim +++ b/autoload/vimtex/options.vim @@ -487,6 +487,7 @@ function! s:check_for_deprecated_options() abort " {{{1 \ 'g:vimtex_change_set_formatexpr', \ 'g:vimtex_change_toggled_delims', \ 'g:vimtex_compiler_callback_hooks', + \ 'g:vimtex_disable_recursive_main_file_detection', \ 'g:vimtex_env_complete_list', \ 'g:vimtex_fold_commands', \ 'g:vimtex_fold_commands_default', diff --git a/autoload/vimtex/state.vim b/autoload/vimtex/state.vim index f29713931c..9ef4b130a0 100644 --- a/autoload/vimtex/state.vim +++ b/autoload/vimtex/state.vim @@ -237,17 +237,15 @@ function! s:get_main() abort " {{{1 endif " Search for main file recursively through include specifiers - if !get(g:, 'vimtex_disable_recursive_main_file_detection', 0) - if &filetype ==# 'tex' - let l:candidate = s:get_main_choose(s:get_main_recurse()) - if !empty(l:candidate) - return [l:candidate, 'recursive search'] - endif - else - let l:candidate = s:get_main_choose(s:get_main_recurse_from_bib()) - if !empty(l:candidate) - return [l:candidate, 'recursive search (bib)'] - endif + if &filetype ==# 'tex' + let l:candidate = s:get_main_choose(s:get_main_recurse()) + if !empty(l:candidate) + return [l:candidate, 'recursive search'] + endif + else + let l:candidate = s:get_main_choose(s:get_main_recurse_from_bib()) + if !empty(l:candidate) + return [l:candidate, 'recursive search (bib)'] endif endif @@ -340,7 +338,7 @@ endfunction " }}}1 function! s:get_main_latexmain(file) abort " {{{1 - for l:cand in s:findfiles_recursive('*.latexmain', expand('%:p:h')) + for l:cand in s:globpathupwards('*.latexmain', expand('%:p:h')) let l:cand = fnamemodify(l:cand, ':p:r') if s:file_reaches_current(l:cand) return l:cand @@ -394,9 +392,9 @@ function! s:get_main_recurse(...) abort " {{{1 let l:re_filter1 = fnamemodify(l:file, ':t:r') let l:re_filter2 = g:vimtex#re#tex_input . '\s*\f*' . l:re_filter1 - " Search through candidates found recursively upwards in the directory tree + " Search through candidates found upwards in the directory tree let l:results = [] - for l:cand in s:findfiles_recursive('*.tex', fnamemodify(l:file, ':p:h')) + for l:cand in s:globpathupwards('*.tex', fnamemodify(l:file, ':p:h')) if index(l:tried[l:file], l:cand) >= 0 | continue | endif call add(l:tried[l:file], l:cand) @@ -420,9 +418,9 @@ function! s:get_main_recurse_from_bib() abort " {{{1 let l:re_filter1 = fnamemodify(l:file, ':t:r') let l:re_filter2 = g:vimtex#re#bib_input . '\s*\f*' . l:re_filter1 - " Search through candidates found recursively upwards in the directory tree + " Search through candidates found upwards in the directory tree let l:results = [] - for l:cand in s:findfiles_recursive('*.tex', fnamemodify(l:file, ':p:h')) + for l:cand in s:globpathupwards('*.tex', fnamemodify(l:file, ':p:h')) if index(l:tried[l:file], l:cand) >= 0 | continue | endif call add(l:tried[l:file], l:cand) @@ -523,7 +521,9 @@ function! s:file_reaches_current(file) abort " {{{1 endfunction " }}}1 -function! s:findfiles_recursive(expr, path) abort " {{{1 +function! s:globpathupwards(expr, path) abort " {{{1 + " Returns the list of files obtained by globpath(p, expr) with p going from + " path upwards in the directory tree. let l:path = a:path let l:dirs = l:path while l:path != fnamemodify(l:path, ':h') diff --git a/doc/vimtex.txt b/doc/vimtex.txt index d170933c1a..9afbd2f70f 100644 --- a/doc/vimtex.txt +++ b/doc/vimtex.txt @@ -323,23 +323,24 @@ VimTeX supports most multi-file documents and has several methods to locate the `main` document. Locating this file is very important, because the main file is the one that must be compiled. -The main method for locating the main file uses a recursive search algorithm -that should find the main LaTeX file in most cases (method 6 in the list -below). There are several alternative methods for specifying the main file -that can be more flexible and is relevant for certain work flows and use -cases. These alternative methods all require some explicit declaration of the -main file. Thus, these methods will be tried first, and the recursive search -is tried last if there are no explicit declarations that yield an appropriate -main LaTeX file candidate. +The default method for locating the main file uses a directory scan algorithm +that searches for a main LaTeX file, see method 6 below. It is expected to +work in the vast majority of cases. -The methods are tried in the following order: +There are several alternative methods for specifying the main file that can be +more flexible and are relevant for certain work flows and use cases. These +methods all require some explicit declaration of the main file and are +therefore tried prior to the directory scan. + +The complete list of methods in the order of priority is as follows and are +then described in more detail: 1. Buffer variable 2. TeX root directive 3. Subfiles package 4. File `.latexmain` specifier 5. Local `latexmkrc` file specifier (from `@default_files` option) - 6. Recursive search + 6. Directory scan *b:vimtex_main* Buffer variable~ @@ -447,34 +448,34 @@ Local latexmkrc file specifier~ Note: `@default_files` is a list of files, VimTeX will use the first entry that is found. -Recursive search~ - If no other method provides an appropriate candidate, then the recursive - search detects the main LaTeX file by searching for a file in the current - and parent directories that +Directory scan~ + If the above methods give no appropriate candidate for a main file of the + present file then a search for a suitable main file from the current + directory upwards is started. - 1. includes the present file (directly or indirectly), - 2. has a `\documentclass` line near the top of its parsed content, and - 3. contains `\begin{document}` in its parsed content. + To test whether a candidate tex file qualifies as a main file the following + happens: First, the candidate tex file is parsed and recursively expanded by + all tex files included. Then it is checked whether all of the following + three requirements are met in order to qualify as a main file for the + present file: - As long as a project follows these rules, the recursive search should work. - Notice, though, that the first point is important and is where the recursive - nature is implemented. There must be a "straight" inclusive line from the - main file to the present file. If not, then rule 1 is violated. + 1. It includes the present file, either directly or indirectly. + 2. The expanded content contains a `\documentclass` line near the top. + 3. The expanded content contains `\begin{document}`. - Let's consider a common construct that will fail: > + Note that the main file itself does not need to contain the `\documentclass` + line and `\begin{docment}`; it could instead stem from included tex files. - path1/main.tex - path2/chapter.tex -< - In this example, the main file does not live in the same folder or a parent - folder, and so the recursive search fails. + See details on |g:vimtex_include_indicators| for all commands that are + considered to include tex files by the parser for the recursive expansion. - In these cases where the recursive method fails, one may safely rely on the - TeX root directive as an alternative. + Note that no recursive directory descents are performed to find a main file. + That is, if the current file is `./B/chapter.tex` then `./A/main.tex` will not + be found as the main file, because the descent to subdirectory `./A/` is not + performed. - Note: In rare cases, such as if there are _very_ many tex files in the - directory tree, this method may be slow. One may therefore disable it - through the option |g:vimtex_disable_recursive_main_file_detection|. + In cases where automatic detection of the main file through the directory + scan fails, one may explicitly set up method 1 to 5 instead. ------------------------------------------------------------------------------ SUPPORT FOR TEX DIRECTIVES *vimtex-tex-directives* @@ -1493,15 +1494,6 @@ OPTIONS *vimtex-options* Default value: 500 -*g:vimtex_disable_recursive_main_file_detection* - In rare cases, the recursive method of finding the main file in multi file - projects may be slow. This might happen for instance when there are _very_ - many tex files in the directory tree that is searched. In such cases, one - may disable the recursive method by setting this variable to a nonzero - value. - - Default value: 0 - *g:vimtex_doc_handlers* With this option, one may specify a list of custom documentation handlers. The following pre-made handlers are available: @@ -6115,6 +6107,10 @@ The following changelog only logs particularly important changes, such as changes that break backwards compatibility. See the git log for the detailed changelog. +2022-11-06: Better main file detection algorithm~ +The detection whether a file is a main file has been improved. In course of +this *g:vimtex_disable_recursive_main_file_detection* has been removed. + 2021-10-25: Better inverse search~ Deprecate *g:vimtex_compiler_progname* as it is no longer necessary.