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
//! # Texter
//!
//! Texter is a crate aiming to simplify writing an LSP using `tree-sitter` whilst benefiting from
//! incremental updates. The main type that you will interacte with is [`Text`][`core::text::Text`].
//!
//! ## Usage with lsp-types
//!
//! [`change::Change`] implements [`From<lsp_types::TextDocumentContentChangeEvent>`] so in
//! most cases calling [`Into::into`] and providing it to [`Text::update`][`core::text::Text::update`] is enough to keep content
//! in sync.
//!
//! ### Selecting an encoding
//!
//! Positions provided from a client may be for different encodings. UTF-8, UTF-16, or
//! UTF-32. When starting up an LSP, the client provides encoding it will use. With that
//! information we can store a function pointer and create new [`Text`][`core::text::Text::update`]'s as needed.
//!
//! The example below works the same way to how it is done in `rust-analyzer`.
//! ```
//! # #[cfg( feature = "lsp-types")] {
//! # fn get_client_encoding() -> Option<Vec<PositionEncodingKind>> {None}
//! use texter::core::text::Text;
//! use texter::lsp_types::PositionEncodingKind;
//!
//! fn decide_encoding() -> fn(String) -> Text {
//! // The type provided in client capabilities.
//! let encodings: Option<Vec<PositionEncodingKind>> = get_client_encoding();
//! let Some(encodings) = encodings else {
//! return Text::new_utf16;
//! };
//!
//! // Hope that we can use anything other than UTF-16
//! for encoding in encodings {
//! if encoding == PositionEncodingKind::UTF8 {
//! return Text::new;
//! } else if encoding == PositionEncodingKind::UTF32 {
//! return Text::new_utf32;
//! }
//! }
//!
//! // Too bad, UTF-16 it is.
//! Text::new_utf16
//! }
//! # }
//! ```
//!
//! ### How to write an LSP using the crate?
//!
//! There is multiple ways to structure your server, `texter` aims to influence the structure as little as possible.
//! For an example you can check out [trunkls](https://github.com/airblast-dev/trunkls).
//!
//! ## Usage with tree-sitter
//!
//! When using a [`Text`][`core::text::Text`] with incremental updates we want to keep using a single
//! [`tree_sitter::Tree`] across edits. To simplify the process [`Updateable`][`updateables::Updateable`]
//! is implemented on [`tree_sitter::Tree`]. So simply providing a mutable reference of the tree to
//! a [`Text`][`core::text::Text`]'s update method is enough to keep the data in sync.
//!
//! In case you want to update a [`tree_sitter::Node`], [`Updateable`][`updateables::Updateable`] is implemented
//! for it as well.
pub use lsp_types;
pub use tree_sitter;