Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions autoload/vimtex/options.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
34 changes: 17 additions & 17 deletions autoload/vimtex/state.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand All @@ -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)

Expand Down Expand Up @@ -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')
Expand Down
78 changes: 37 additions & 41 deletions doc/vimtex.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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~
Expand Down Expand Up @@ -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.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

document


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.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's good. Thanks!


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.
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious: directory descent is when we go into subdirectories, right? And directory ascent goes towards the root?

Copy link
Copy Markdown
Contributor Author

@shuber2 shuber2 Nov 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, ascent resp. descent in the directory tree, and (rooted) trees are typically drawn from the root downwards.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's what confuses me. A tree is naturally pointed upwards, but in these cases they are used downwards. 🤷🏻

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By "naturally" you mean biological trees? Yes. In computer science, however, trees are drawn with the root at the top, see https://en.wikipedia.org/wiki/Tree_(data_structure)

Or consider the tree shell command or file browsers.


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*
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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.

Expand Down