summaryrefslogtreecommitdiff
path: root/support/texlab/src/workspace/api.rs
blob: 1ccd19d4e4e2b70cf026b87cb529ee7b7be218f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::{fs, path::PathBuf, sync::Arc};

use anyhow::Result;

use crate::{DocumentLanguage, Uri};

use super::Document;

#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, PartialOrd, Ord)]
pub enum WorkspaceSource {
    Client,
    Server,
}

#[derive(Debug, Clone)]
pub struct WorkspaceSubset {
    pub documents: Vec<Arc<Document>>,
}

pub type OpenHandler = Arc<dyn Fn(Arc<dyn Workspace>, Arc<Document>) + Send + Sync + 'static>;

pub trait Workspace: Send + Sync {
    fn open(
        &self,
        uri: Arc<Uri>,
        text: String,
        language: DocumentLanguage,
        source: WorkspaceSource,
    ) -> Arc<Document>;

    fn register_open_handler(&self, handler: OpenHandler);

    fn reload(&self, path: PathBuf) -> Result<Option<Arc<Document>>> {
        let uri = Arc::new(Uri::from_file_path(path.clone()).unwrap());

        if self.is_open(&uri) && !uri.as_str().ends_with(".log") {
            return Ok(self.get(&uri));
        }

        let data = fs::read(&path)?;
        let text = String::from_utf8_lossy(&data).into_owned();
        if let Some(language) = DocumentLanguage::by_path(&path) {
            Ok(Some(self.open(
                uri,
                text,
                language,
                WorkspaceSource::Server,
            )))
        } else {
            Ok(None)
        }
    }

    fn load(&self, path: PathBuf) -> Result<Option<Arc<Document>>> {
        let uri = Arc::new(Uri::from_file_path(path.clone()).unwrap());

        if let Some(document) = self.get(&uri) {
            return Ok(Some(document));
        }

        let data = fs::read(&path)?;
        let text = String::from_utf8_lossy(&data).into_owned();
        if let Some(language) = DocumentLanguage::by_path(&path) {
            Ok(Some(self.open(
                uri,
                text,
                language,
                WorkspaceSource::Server,
            )))
        } else {
            Ok(None)
        }
    }

    fn documents(&self) -> Vec<Arc<Document>>;

    fn has(&self, uri: &Uri) -> bool;

    fn get(&self, uri: &Uri) -> Option<Arc<Document>>;

    fn close(&self, uri: &Uri);

    fn is_open(&self, uri: &Uri) -> bool;

    fn subset(&self, uri: Arc<Uri>) -> Option<WorkspaceSubset>;
}