mirror of
https://github.com/latex-lsp/texlab.git
synced 2025-08-04 10:49:55 +00:00
Fix tracking cursor position (#889)
This commit is contained in:
parent
68bf2b3d96
commit
10890d8869
8 changed files with 62 additions and 60 deletions
|
@ -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();
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 },
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
@ -362,7 +361,7 @@ impl Server {
|
|||
params.text_document.text,
|
||||
language,
|
||||
Owner::Client,
|
||||
TextSize::default(),
|
||||
LineCol { line: 0, col: 0 },
|
||||
);
|
||||
|
||||
self.update_workspace();
|
||||
|
@ -389,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,
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -511,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,
|
||||
|
@ -523,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
|
||||
|
@ -584,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(())
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue