mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-03 09:52:27 +00:00
feat: implicitly focus entry on no focus request sent (#262)
* feat: implicitly focus entry on no focus command sent * dev: garden
This commit is contained in:
parent
ca5d8f61cc
commit
d05c5012ff
3 changed files with 74 additions and 12 deletions
|
@ -330,7 +330,7 @@ impl CompileClientActor {
|
|||
self.config = config;
|
||||
}
|
||||
|
||||
pub fn change_entry(&mut self, path: Option<ImmutPath>) -> Result<(), Error> {
|
||||
pub fn change_entry(&mut self, path: Option<ImmutPath>) -> Result<bool, Error> {
|
||||
if path
|
||||
.as_deref()
|
||||
.is_some_and(|p| !p.is_absolute() && !p.starts_with("/untitled"))
|
||||
|
@ -340,7 +340,7 @@ impl CompileClientActor {
|
|||
|
||||
let next_entry = self.config.determine_entry(path);
|
||||
if next_entry == self.entry {
|
||||
return Ok(());
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let diag_group = &self.diag_group;
|
||||
|
@ -373,7 +373,7 @@ impl CompileClientActor {
|
|||
|
||||
self.entry = next_entry;
|
||||
|
||||
Ok(())
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
pub fn add_memory_changes(&self, event: MemoryEvent) {
|
||||
|
|
|
@ -205,6 +205,10 @@ pub struct TypstLanguageServer {
|
|||
pub pinning: bool,
|
||||
/// The client focusing file.
|
||||
pub focusing: Option<ImmutPath>,
|
||||
/// The client ever focused implicitly by activities.
|
||||
pub ever_focusing_by_activities: bool,
|
||||
/// The client ever sent manual focusing request.
|
||||
pub ever_manual_focusing: bool,
|
||||
|
||||
// Configurations
|
||||
/// User configuration from the editor.
|
||||
|
@ -261,6 +265,8 @@ impl TypstLanguageServer {
|
|||
}),
|
||||
dedicates: Vec::new(),
|
||||
shutdown_requested: false,
|
||||
ever_focusing_by_activities: false,
|
||||
ever_manual_focusing: false,
|
||||
sema_tokens_registered: None,
|
||||
formatter_registered: None,
|
||||
config: Default::default(),
|
||||
|
@ -822,10 +828,17 @@ impl TypstLanguageServer {
|
|||
pub fn focus_document(&mut self, arguments: Vec<JsonValue>) -> LspResult<JsonValue> {
|
||||
let new_entry = parse_path_or_null(arguments.first())?;
|
||||
|
||||
let update_result = self.focus_entry(new_entry.clone());
|
||||
update_result.map_err(|err| internal_error(format!("could not focus file: {err}")))?;
|
||||
if !self.ever_manual_focusing {
|
||||
self.ever_manual_focusing = true;
|
||||
log::info!("first manual focusing is coming");
|
||||
}
|
||||
|
||||
info!("file focused: {entry:?}", entry = new_entry);
|
||||
let ok = self.focus_entry(new_entry.clone());
|
||||
let ok = ok.map_err(|err| internal_error(format!("could not focus file: {err}")))?;
|
||||
|
||||
if ok {
|
||||
info!("file focused: {new_entry:?}");
|
||||
}
|
||||
Ok(JsonValue::Null)
|
||||
}
|
||||
|
||||
|
@ -977,6 +990,9 @@ impl TypstLanguageServer {
|
|||
let text = params.text_document.text;
|
||||
|
||||
self.create_source(path.clone(), text).unwrap();
|
||||
|
||||
// Focus after opening
|
||||
self.implicit_focus_entry(|| Some(path.as_path().into()), 'o');
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1104,6 +1120,7 @@ impl TypstLanguageServer {
|
|||
|
||||
fn hover(&mut self, params: HoverParams) -> LspResult<Option<Hover>> {
|
||||
let (path, position) = as_path_pos(params.text_document_position_params);
|
||||
self.implicit_focus_entry(|| Some(path.as_path().into()), 'h');
|
||||
run_query!(self.Hover(path, position))
|
||||
}
|
||||
|
||||
|
@ -1113,6 +1130,7 @@ impl TypstLanguageServer {
|
|||
) -> LspResult<Option<Vec<FoldingRange>>> {
|
||||
let path = as_path(params.text_document);
|
||||
let line_folding_only = self.const_config().doc_line_folding_only;
|
||||
self.implicit_focus_entry(|| Some(path.as_path().into()), 'f');
|
||||
run_query!(self.FoldingRange(path, line_folding_only))
|
||||
}
|
||||
|
||||
|
@ -1138,6 +1156,7 @@ impl TypstLanguageServer {
|
|||
params: SemanticTokensParams,
|
||||
) -> LspResult<Option<SemanticTokensResult>> {
|
||||
let path = as_path(params.text_document);
|
||||
self.implicit_focus_entry(|| Some(path.as_path().into()), 't');
|
||||
run_query!(self.SemanticTokensFull(path))
|
||||
}
|
||||
|
||||
|
@ -1147,6 +1166,7 @@ impl TypstLanguageServer {
|
|||
) -> LspResult<Option<SemanticTokensFullDeltaResult>> {
|
||||
let path = as_path(params.text_document);
|
||||
let previous_result_id = params.previous_result_id;
|
||||
self.implicit_focus_entry(|| Some(path.as_path().into()), 't');
|
||||
run_query!(self.SemanticTokensDelta(path, previous_result_id))
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,11 @@ use crate::{actor::typ_client::CompileClientActor, compiler::CompileServer, Typs
|
|||
|
||||
impl CompileServer {
|
||||
/// Focus main file to some path.
|
||||
pub fn do_change_entry(&mut self, new_entry: Option<ImmutPath>) -> Result<(), Error> {
|
||||
pub fn do_change_entry(&mut self, new_entry: Option<ImmutPath>) -> Result<bool, Error> {
|
||||
self.compiler
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.change_entry(new_entry.clone())?;
|
||||
|
||||
Ok(())
|
||||
.change_entry(new_entry.clone())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -48,14 +46,58 @@ impl TypstLanguageServer {
|
|||
}
|
||||
|
||||
/// Updates the primary (focusing) entry
|
||||
pub fn focus_entry(&mut self, new_entry: Option<ImmutPath>) -> Result<(), Error> {
|
||||
pub fn focus_entry(&mut self, new_entry: Option<ImmutPath>) -> Result<bool, Error> {
|
||||
if self.pinning || self.config.compile.has_default_entry_path {
|
||||
self.focusing = new_entry;
|
||||
return Ok(());
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
self.primary.do_change_entry(new_entry.clone())
|
||||
}
|
||||
|
||||
/// This is used for tracking activating document status if a client is not
|
||||
/// performing any focus command request.
|
||||
///
|
||||
/// See https://github.com/microsoft/language-server-protocol/issues/718
|
||||
///
|
||||
/// we do want to focus the file implicitly by `textDocument/diagnostic`
|
||||
/// (pullDiagnostics mode), as suggested by language-server-protocol#718,
|
||||
/// however, this has poor support, e.g. since neovim 0.10.0.
|
||||
pub fn implicit_focus_entry(
|
||||
&mut self,
|
||||
new_entry: impl FnOnce() -> Option<ImmutPath>,
|
||||
site: char,
|
||||
) {
|
||||
if self.ever_manual_focusing {
|
||||
return;
|
||||
}
|
||||
// didOpen
|
||||
match site {
|
||||
// foldingRange, hover, semanticTokens
|
||||
'f' | 'h' | 't' => {
|
||||
self.ever_focusing_by_activities = true;
|
||||
}
|
||||
// didOpen
|
||||
_ => {
|
||||
if self.ever_focusing_by_activities {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let new_entry = new_entry();
|
||||
|
||||
let update_result = self.focus_entry(new_entry.clone());
|
||||
match update_result {
|
||||
Ok(true) => {
|
||||
log::info!("file focused[implicit,{site}]: {new_entry:?}");
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("could not focus file: {err}");
|
||||
}
|
||||
Ok(false) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue