summaryrefslogtreecommitdiff
path: root/support/texlab/crates
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/crates')
-rw-r--r--support/texlab/crates/base-db/src/document.rs7
-rw-r--r--support/texlab/crates/base-db/src/semantics/tex.rs4
-rw-r--r--support/texlab/crates/base-db/src/workspace.rs21
-rw-r--r--support/texlab/crates/commands/Cargo.toml1
-rw-r--r--support/texlab/crates/commands/src/build.rs55
-rw-r--r--support/texlab/crates/commands/src/fwd_search.rs3
-rw-r--r--support/texlab/crates/symbols/src/workspace/sort.rs29
-rw-r--r--support/texlab/crates/test-utils/src/fixture.rs4
-rw-r--r--support/texlab/crates/texlab/Cargo.toml2
-rw-r--r--support/texlab/crates/texlab/benches/bench_main.rs5
-rw-r--r--support/texlab/crates/texlab/src/main.rs3
-rw-r--r--support/texlab/crates/texlab/src/server.rs95
-rw-r--r--support/texlab/crates/texlab/tests/lsp/text_document/completion.rs50
-rw-r--r--support/texlab/crates/texlab/tests/lsp/text_document/snapshots/lsp__text_document__completion__issue_885.snap18
14 files changed, 215 insertions, 82 deletions
diff --git a/support/texlab/crates/base-db/src/document.rs b/support/texlab/crates/base-db/src/document.rs
index cc1a0d44e5..8b6e07fb0f 100644
--- a/support/texlab/crates/base-db/src/document.rs
+++ b/support/texlab/crates/base-db/src/document.rs
@@ -1,14 +1,13 @@
use std::path::PathBuf;
use distro::Language;
-use rowan::TextSize;
use syntax::{bibtex, latex, BuildError};
use url::Url;
use crate::{
diagnostics::{self, Diagnostic},
semantics,
- util::LineIndex,
+ util::{LineCol, LineIndex},
Config,
};
@@ -26,7 +25,7 @@ pub struct Document {
pub text: String,
pub line_index: LineIndex,
pub owner: Owner,
- pub cursor: TextSize,
+ pub cursor: LineCol,
pub language: Language,
pub data: DocumentData,
pub diagnostics: Vec<Diagnostic>,
@@ -38,7 +37,7 @@ impl Document {
text: String,
language: Language,
owner: Owner,
- cursor: TextSize,
+ cursor: LineCol,
config: &Config,
) -> Self {
let dir = uri.join(".").unwrap();
diff --git a/support/texlab/crates/base-db/src/semantics/tex.rs b/support/texlab/crates/base-db/src/semantics/tex.rs
index 6e238737b0..46c805ba8a 100644
--- a/support/texlab/crates/base-db/src/semantics/tex.rs
+++ b/support/texlab/crates/base-db/src/semantics/tex.rs
@@ -92,10 +92,12 @@ impl Semantics {
}
let Some(path) = import.file().and_then(|path| path.key()) else { return };
+ let text = format!("{base_dir}{}", path.to_string());
+ let range = latex::small_range(&path);
self.links.push(Link {
kind: LinkKind::Tex,
- path: Span::from(&path),
+ path: Span { text, range },
base_dir: Some(base_dir),
});
}
diff --git a/support/texlab/crates/base-db/src/workspace.rs b/support/texlab/crates/base-db/src/workspace.rs
index 1872c33df1..581d93cfc3 100644
--- a/support/texlab/crates/base-db/src/workspace.rs
+++ b/support/texlab/crates/base-db/src/workspace.rs
@@ -5,11 +5,12 @@ use std::{
use distro::{Distro, Language};
use itertools::Itertools;
-use rowan::{TextRange, TextSize};
+use rowan::TextRange;
use rustc_hash::FxHashSet;
+use text_size::TextLen;
use url::Url;
-use crate::{graph, Config, Document, DocumentData, Owner};
+use crate::{graph, util::LineCol, Config, Document, DocumentData, Owner};
#[derive(Debug, Default)]
pub struct Workspace {
@@ -51,7 +52,7 @@ impl Workspace {
text: String,
language: Language,
owner: Owner,
- cursor: TextSize,
+ cursor: LineCol,
) {
log::debug!("Opening document {uri}...");
self.documents.remove(&uri);
@@ -74,19 +75,26 @@ impl Workspace {
Cow::Owned(text) => text,
};
- Ok(self.open(uri, text, language, owner, TextSize::default()))
+ Ok(self.open(uri, text, language, owner, LineCol { line: 0, col: 0 }))
}
pub fn edit(&mut self, uri: &Url, delete: TextRange, insert: &str) -> Option<()> {
let document = self.lookup(uri)?;
let mut text = document.text.clone();
+ let cursor = if delete.len() == text.text_len() {
+ let line = document.cursor.line.min(text.lines().count() as u32);
+ LineCol { line, col: 0 }
+ } else {
+ document.line_index.line_col(delete.start())
+ };
+
text.replace_range(std::ops::Range::<usize>::from(delete), insert);
self.open(
document.uri.clone(),
text,
document.language,
Owner::Client,
- delete.start(),
+ cursor,
);
Some(())
@@ -184,9 +192,10 @@ impl Workspace {
self.folders = folders;
}
- pub fn set_cursor(&mut self, uri: &Url, cursor: TextSize) -> Option<()> {
+ pub fn set_cursor(&mut self, uri: &Url, cursor: LineCol) -> Option<()> {
let mut document = self.lookup(uri)?.clone();
document.cursor = cursor;
+ self.documents.remove(&document);
self.documents.insert(document);
Some(())
}
diff --git a/support/texlab/crates/commands/Cargo.toml b/support/texlab/crates/commands/Cargo.toml
index ea7358364f..68d034675e 100644
--- a/support/texlab/crates/commands/Cargo.toml
+++ b/support/texlab/crates/commands/Cargo.toml
@@ -12,6 +12,7 @@ base-db = { path = "../base-db" }
bstr = "1.4.0"
crossbeam-channel = "0.5.8"
itertools = "0.10.5"
+libc = "0.2.144"
log = "0.4.17"
rowan = "0.15.11"
rustc-hash = "1.1.0"
diff --git a/support/texlab/crates/commands/src/build.rs b/support/texlab/crates/commands/src/build.rs
index 3d93601e39..47e156ef72 100644
--- a/support/texlab/crates/commands/src/build.rs
+++ b/support/texlab/crates/commands/src/build.rs
@@ -1,7 +1,7 @@
use std::{
io::{BufReader, Read},
path::{Path, PathBuf},
- process::{ExitStatus, Stdio},
+ process::{Child, Stdio},
thread::{self, JoinHandle},
};
@@ -64,7 +64,7 @@ impl BuildCommand {
})
}
- pub fn run(self, sender: Sender<String>) -> Result<ExitStatus, BuildError> {
+ pub fn spawn(self, sender: Sender<String>) -> Result<Child, BuildError> {
log::debug!(
"Spawning compiler {} {:#?} in directory {}",
self.program,
@@ -72,19 +72,56 @@ impl BuildCommand {
self.working_dir.display()
);
- let mut process = std::process::Command::new(&self.program)
- .args(self.args)
+ let mut process = self.spawn_internal()?;
+ track_output(process.stderr.take().unwrap(), sender.clone());
+ track_output(process.stdout.take().unwrap(), sender);
+ Ok(process)
+ }
+
+ #[cfg(windows)]
+ fn spawn_internal(&self) -> Result<Child, BuildError> {
+ std::process::Command::new(&self.program)
+ .args(self.args.clone())
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.current_dir(&self.working_dir)
- .spawn()?;
+ .spawn()
+ .map_err(Into::into)
+ }
- track_output(process.stderr.take().unwrap(), sender.clone());
- track_output(process.stdout.take().unwrap(), sender);
+ #[cfg(unix)]
+ fn spawn_internal(&self) -> Result<Child, BuildError> {
+ use std::os::unix::process::CommandExt;
+ std::process::Command::new(&self.program)
+ .args(self.args.clone())
+ .stdin(Stdio::null())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::piped())
+ .current_dir(&self.working_dir)
+ .process_group(0)
+ .spawn()
+ .map_err(Into::into)
+ }
+
+ #[cfg(windows)]
+ pub fn cancel(pid: u32) -> std::io::Result<bool> {
+ Ok(std::process::Command::new("taskkill")
+ .arg("/PID")
+ .arg(pid.to_string())
+ .arg("/F")
+ .arg("/T")
+ .status()?
+ .success())
+ }
+
+ #[cfg(not(windows))]
+ pub fn cancel(pid: u32) -> Result<bool> {
+ unsafe {
+ libc::killpg(pid as libc::pid_t, libc::SIGTERM);
+ }
- let status = process.wait();
- Ok(status?)
+ Ok(true)
}
}
diff --git a/support/texlab/crates/commands/src/fwd_search.rs b/support/texlab/crates/commands/src/fwd_search.rs
index c458f33cf1..fc0a130f86 100644
--- a/support/texlab/crates/commands/src/fwd_search.rs
+++ b/support/texlab/crates/commands/src/fwd_search.rs
@@ -32,6 +32,7 @@ pub enum ForwardSearchError {
LaunchViewer(#[from] std::io::Error),
}
+#[derive(Debug)]
pub struct ForwardSearch {
program: String,
args: Vec<String>,
@@ -79,7 +80,7 @@ impl ForwardSearch {
let tex_path = tex_path.to_string_lossy().into_owned();
let pdf_path = pdf_path.to_string_lossy().into_owned();
- let line = line.unwrap_or_else(|| child.line_index.line_col(child.cursor).line);
+ let line = line.unwrap_or_else(|| child.cursor.line);
let line = (line + 1).to_string();
let program = config.program.clone();
diff --git a/support/texlab/crates/symbols/src/workspace/sort.rs b/support/texlab/crates/symbols/src/workspace/sort.rs
index bc30728da9..0e24c25ac9 100644
--- a/support/texlab/crates/symbols/src/workspace/sort.rs
+++ b/support/texlab/crates/symbols/src/workspace/sort.rs
@@ -38,9 +38,8 @@ impl<'a> From<&'a Workspace> for ProjectOrdering<'a> {
#[cfg(test)]
mod tests {
- use base_db::Owner;
+ use base_db::{util::LineCol, Owner};
use distro::Language;
- use rowan::TextSize;
use super::{ProjectOrdering, Url, Workspace};
@@ -57,7 +56,7 @@ mod tests {
String::new(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -65,7 +64,7 @@ mod tests {
String::new(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -73,7 +72,7 @@ mod tests {
r#"\documentclass{article}\include{b}\include{a}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
let ordering = ProjectOrdering::from(&workspace);
@@ -95,7 +94,7 @@ mod tests {
String::new(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -103,7 +102,7 @@ mod tests {
r#"\include{a}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -111,7 +110,7 @@ mod tests {
r#"\begin{documnent}\include{b}\end{document}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
let ordering = ProjectOrdering::from(&workspace);
@@ -132,7 +131,7 @@ mod tests {
r#"\begin{document}\include{b}\end{document}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -140,7 +139,7 @@ mod tests {
r#"\include{a}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -148,7 +147,7 @@ mod tests {
r#"\include{a}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
let ordering = ProjectOrdering::from(&workspace);
@@ -169,7 +168,7 @@ mod tests {
r#"\begin{document}\include{b}\end{document}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -177,7 +176,7 @@ mod tests {
String::new(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -185,7 +184,7 @@ mod tests {
String::new(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
workspace.open(
@@ -193,7 +192,7 @@ mod tests {
r#"\begin{document}\include{c}\end{document}"#.to_string(),
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
let ordering = ProjectOrdering::from(&workspace);
diff --git a/support/texlab/crates/test-utils/src/fixture.rs b/support/texlab/crates/test-utils/src/fixture.rs
index 2935b4f519..1a5071b2db 100644
--- a/support/texlab/crates/test-utils/src/fixture.rs
+++ b/support/texlab/crates/test-utils/src/fixture.rs
@@ -1,6 +1,6 @@
use std::path::PathBuf;
-use base_db::{Owner, Workspace};
+use base_db::{util::LineCol, Owner, Workspace};
use rowan::{TextRange, TextSize};
use url::Url;
@@ -35,7 +35,7 @@ impl Fixture {
document.text.clone(),
language,
Owner::Client,
- TextSize::from(0),
+ LineCol { line: 0, col: 0 },
);
}
diff --git a/support/texlab/crates/texlab/Cargo.toml b/support/texlab/crates/texlab/Cargo.toml
index dc1eb5b913..821ecb9813 100644
--- a/support/texlab/crates/texlab/Cargo.toml
+++ b/support/texlab/crates/texlab/Cargo.toml
@@ -1,7 +1,7 @@
[package]
name = "texlab"
description = "LaTeX Language Server"
-version = "5.5.1"
+version = "5.6.0"
license.workspace = true
readme = "README.md"
authors.workspace = true
diff --git a/support/texlab/crates/texlab/benches/bench_main.rs b/support/texlab/crates/texlab/benches/bench_main.rs
index 8e69e1e5a4..47b302e313 100644
--- a/support/texlab/crates/texlab/benches/bench_main.rs
+++ b/support/texlab/crates/texlab/benches/bench_main.rs
@@ -1,9 +1,8 @@
-use base_db::{Owner, Workspace};
+use base_db::{util::LineCol, Owner, Workspace};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use distro::Language;
use lsp_types::{ClientCapabilities, Position, Url};
use parser::{parse_latex, SyntaxConfig};
-use rowan::TextSize;
const CODE: &str = include_str!("../../../texlab.tex");
@@ -22,7 +21,7 @@ fn criterion_benchmark(c: &mut Criterion) {
text,
Language::Tex,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
let client_capabilities = ClientCapabilities::default();
diff --git a/support/texlab/crates/texlab/src/main.rs b/support/texlab/crates/texlab/src/main.rs
index ed807f8799..d588a568bc 100644
--- a/support/texlab/crates/texlab/src/main.rs
+++ b/support/texlab/crates/texlab/src/main.rs
@@ -50,9 +50,6 @@ fn setup_logger(opts: Opts) {
let logger = fern::Dispatch::new()
.format(|out, message, record| out.finish(format_args!("{} - {}", record.level(), message)))
.level(verbosity_level)
- .filter(|metadata| {
- metadata.target().contains("texlab") || metadata.target().contains("lsp_server")
- })
.chain(io::stderr());
let logger = match opts.log_file {
diff --git a/support/texlab/crates/texlab/src/server.rs b/support/texlab/crates/texlab/src/server.rs
index 6b118655bc..0370f00192 100644
--- a/support/texlab/crates/texlab/src/server.rs
+++ b/support/texlab/crates/texlab/src/server.rs
@@ -10,15 +10,14 @@ use std::{
};
use anyhow::Result;
-use base_db::{Config, Owner, Workspace};
+use base_db::{util::LineCol, Config, Owner, Workspace};
use commands::{BuildCommand, CleanCommand, CleanTarget, ForwardSearch};
use crossbeam_channel::{Receiver, Sender};
use distro::{Distro, Language};
-use itertools::{FoldWhile, Itertools};
use lsp_server::{Connection, ErrorCode, Message, RequestId};
use lsp_types::{notification::*, request::*, *};
use parking_lot::{Mutex, RwLock};
-use rowan::{ast::AstNode, TextSize};
+use rowan::ast::AstNode;
use rustc_hash::{FxHashMap, FxHashSet};
use serde::{de::DeserializeOwned, Serialize};
use syntax::bibtex;
@@ -67,6 +66,7 @@ pub struct Server {
chktex_diagnostics: FxHashMap<Url, Vec<Diagnostic>>,
watcher: FileWatcher,
pool: ThreadPool,
+ pending_builds: Arc<Mutex<FxHashSet<u32>>>,
}
impl Server {
@@ -86,6 +86,7 @@ impl Server {
chktex_diagnostics: Default::default(),
watcher,
pool: threadpool::Builder::new().build(),
+ pending_builds: Default::default(),
}
}
@@ -360,7 +361,7 @@ impl Server {
params.text_document.text,
language,
Owner::Client,
- TextSize::default(),
+ LineCol { line: 0, col: 0 },
);
self.update_workspace();
@@ -387,28 +388,18 @@ impl Server {
workspace.edit(&uri, range, &change.text);
}
None => {
+ let new_line = document.cursor.line.min(change.text.lines().count() as u32);
let language = document.language;
- let line_col = document.line_index.line_col(document.cursor);
-
- let (_, new_cursor) = change
- .text
- .lines()
- .fold_while((0, 0), |(number, index), line| {
- if number == line_col.line {
- FoldWhile::Done((number, index))
- } else {
- itertools::FoldWhile::Continue((number + 1, index + line.len()))
- }
- })
- .into_inner();
-
drop(document);
workspace.open(
uri.clone(),
change.text,
language,
Owner::Client,
- TextSize::from(new_cursor as u32),
+ LineCol {
+ line: new_line as u32,
+ col: 0,
+ },
);
}
};
@@ -509,6 +500,9 @@ impl Server {
let position = params.text_document_position.position;
let client_capabilities = Arc::clone(&self.client_capabilities);
let client_info = self.client_info.clone();
+
+ self.update_cursor(&uri, position);
+
self.run_query(id, move |db| {
completion::complete(
db,
@@ -521,6 +515,16 @@ impl Server {
Ok(())
}
+ fn update_cursor(&self, uri: &Url, position: Position) {
+ self.workspace.write().set_cursor(
+ uri,
+ LineCol {
+ line: position.line,
+ col: 0,
+ },
+ );
+ }
+
fn completion_resolve(&self, id: RequestId, mut item: CompletionItem) -> Result<()> {
self.run_query(id, move |workspace| {
match item
@@ -582,17 +586,9 @@ impl Server {
let mut uri = params.text_document_position_params.text_document.uri;
normalize_uri(&mut uri);
- let workspace = self.workspace.read();
- if let Some(document) = workspace.lookup(&uri) {
- let position = document
- .line_index
- .offset_lsp(params.text_document_position_params.position);
-
- drop(workspace);
- self.workspace.write().set_cursor(&uri, position);
- }
-
let position = params.text_document_position_params.position;
+ self.update_cursor(&uri, position);
+
self.run_query(id, move |db| hover::find(db, &uri, position));
Ok(())
}
@@ -672,6 +668,16 @@ impl Server {
self.client
.send_response(lsp_server::Response::new_ok(id, dot))?;
}
+ "texlab.cancelBuild" => {
+ let pending_builds = Arc::clone(&self.pending_builds);
+ self.run_fallible(id, move || {
+ for pid in pending_builds.lock().drain() {
+ let _ = BuildCommand::cancel(pid);
+ }
+
+ Ok(())
+ });
+ }
_ => {
self.client
.send_error(
@@ -728,6 +734,8 @@ impl Server {
let command = BuildCommand::new(&workspace, &uri);
let internal = self.internal_tx.clone();
let progress = self.client_capabilities.has_work_done_progress_support();
+ let pending_builds = Arc::clone(&self.pending_builds);
+
self.pool.execute(move || {
let guard = LOCK.lock();
@@ -738,14 +746,29 @@ impl Server {
None
};
- let status = match command.and_then(|command| command.run(sender)) {
- Ok(status) if status.success() => BuildStatus::SUCCESS,
- Ok(_) => BuildStatus::ERROR,
- Err(why) => {
+ let status = command
+ .and_then(|command| {
+ let mut process = command.spawn(sender)?;
+ let pid = process.id();
+ pending_builds.lock().insert(pid);
+ let result = process.wait();
+
+ let status = if pending_builds.lock().remove(&pid) {
+ if result?.success() {
+ BuildStatus::SUCCESS
+ } else {
+ BuildStatus::ERROR
+ }
+ } else {
+ BuildStatus::CANCELLED
+ };
+
+ Ok(status)
+ })
+ .unwrap_or_else(|why| {
log::error!("Failed to compile document \"{uri}\": {why}");
BuildStatus::FAILURE
- }
- };
+ });
drop(progress_reporter);
drop(guard);
@@ -755,7 +778,7 @@ impl Server {
let _ = client.send_response(lsp_server::Response::new_ok(id, result));
}
- if fwd_search_after {
+ if fwd_search_after && status != BuildStatus::CANCELLED {
let _ = internal.send(InternalMessage::ForwardSearch(uri, params.position));
}
});
diff --git a/support/texlab/crates/texlab/tests/lsp/text_document/completion.rs b/support/texlab/crates/texlab/tests/lsp/text_document/completion.rs
index 78df56c583..e76f4360bd 100644
--- a/support/texlab/crates/texlab/tests/lsp/text_document/completion.rs
+++ b/support/texlab/crates/texlab/tests/lsp/text_document/completion.rs
@@ -786,7 +786,7 @@ fn test_project_resolution_import() {
r#"
%! main.tex
\documentclass{article}
-\import{sub}{sub/sub.tex}
+\import{sub}{sub.tex}
\lipsu
|
^^^^^
@@ -864,3 +864,51 @@ fn issue_883() {
% Comment"#
))
}
+
+#[test]
+fn issue_885() {
+ assert_json_snapshot!(complete(
+ r#"
+%! main.tex
+\documentclass{book}
+\usepackage{import}
+\begin{document}
+\subincludefrom{part 1}{main}
+\include{part 2/main}
+
+\ref{sec}
+ |
+ ^^^
+\end{document}
+
+%! part 1/main.tex
+\part{1}
+\label{part 1}
+\subimport{chapter 1}{main}
+
+%! part 1/chapter 1/main.tex
+\chapter{1}
+\label{chapter 1}
+\subimport{./}{section 1}
+%\subimport{}{section 1}
+
+%! part 1/chapter 1/section 1.tex
+\section{1}
+\label{section 1}
+
+%! part 2/main.tex
+\part{2}
+\label{part 2}
+\input{part 2/chapter 2/main}
+
+%! part 2/chapter 2/main.tex
+\chapter{2}
+\label{chapter 2}
+\input{part 2/chapter 2/section 2}
+
+%! part 2/chapter 2/section 2.tex
+\section{2}
+\label{section 2}
+"#
+ ));
+}
diff --git a/support/texlab/crates/texlab/tests/lsp/text_document/snapshots/lsp__text_document__completion__issue_885.snap b/support/texlab/crates/texlab/tests/lsp/text_document/snapshots/lsp__text_document__completion__issue_885.snap
new file mode 100644
index 0000000000..2f286288b9
--- /dev/null
+++ b/support/texlab/crates/texlab/tests/lsp/text_document/snapshots/lsp__text_document__completion__issue_885.snap
@@ -0,0 +1,18 @@
+---
+source: crates/texlab/tests/lsp/text_document/completion.rs
+expression: "complete(r#\"\n%! main.tex\n\\documentclass{book}\n\\usepackage{import}\n\\begin{document}\n\\subincludefrom{part 1}{main}\n\\include{part 2/main}\n\n\\ref{sec}\n |\n ^^^\n\\end{document}\n\n%! part 1/main.tex\n\\part{1}\n\\label{part 1}\n\\subimport{chapter 1}{main}\n\n%! part 1/chapter 1/main.tex\n\\chapter{1}\n\\label{chapter 1}\n\\subimport{./}{section 1}\n%\\subimport{}{section 1}\n\n%! part 1/chapter 1/section 1.tex\n\\section{1}\n\\label{section 1}\n\n%! part 2/main.tex\n\\part{2}\n\\label{part 2}\n\\input{part 2/chapter 2/main}\n\n%! part 2/chapter 2/main.tex\n\\chapter{2}\n\\label{chapter 2}\n\\input{part 2/chapter 2/section 2}\n\n%! part 2/chapter 2/section 2.tex\n\\section{2}\n\\label{section 2}\n\"#)"
+---
+[
+ {
+ "label": "section 1",
+ "detail": "Section (1)",
+ "preselect": false,
+ "filterText": "section 1 Section (1)"
+ },
+ {
+ "label": "section 2",
+ "detail": "Section (2)",
+ "preselect": false,
+ "filterText": "section 2 Section (2)"
+ }
+]