#string #lsp #text-document #representation #convert #offset #helper

lsp-document

在LSP文档和Rust字符串之间转换的辅助工具

7 个版本 (破坏性更新)

0.6.0 2022年5月2日
0.5.0 2022年3月26日
0.4.0 2021年11月6日
0.3.0 2021年11月6日
0.1.1 2021年4月4日

#1273 in 文本处理


3 个Crates中使用 (2个直接使用)

MIT 许可证

24KB
388

lsp-document

Docs

帮助在文本文档的LSP表示和Rust字符串之间转换。

TL;DR

LSP使用UTF16编码的字符串,而Rust的字符串是UTF8编码的。这意味着LSP和Rust中的文本偏移量是不同的

  • LSP偏移量位于16位代码单元中,每个字符是1或2个这样的单元,
  • Rust字符串按字节索引,每个字符占用1到4个字节。

为了确保LSP客户端和服务器“讨论”文本文档的同一部分,我们需要一个转换层。

此crate提供了这样的层。

示例用法

有关详细信息,请参阅文档

use lsp_document::{TextMap, TextAdapter, Pos, IndexedText};
use lsp_types::Position;

// Character width
// U16:     1111111111111 1111111111 1 11 1 1 111111111 21
// U8:      1111111111111 1222122221 1 13 3 3 111111111 41
// U8 offset
//          0         1       2      3       4          5
//          0123456789012 3468013579 0 12 5 8 123456789 04
let text = "Hello, world!\nКак дела?\r\n做得好\nThis is 💣!";
let text = IndexedText::new(text);
//
// Examples of using TextMap methods
//
// Pos of 💣 from its offset
assert_eq!(text.offset_to_pos(50).unwrap(), Pos::new(3, 8));
// Raw line range info
assert_eq!(text.line_range(2).unwrap(), Pos::new(2, 0)..Pos::new(2, 10));
// Extracting part of text between two positions
assert_eq!(text.substr(Pos::new(1, 7)..Pos::new(1, 15)).unwrap(), "дела");

//
// Example of using TextAdapter methods
//
// Pos of `!` after 💣
assert_eq!(text.lsp_pos_to_pos(&Position::new(3, 10)).unwrap(), Pos::new(3, 12));
assert_eq!(text.pos_to_lsp_pos(&Pos::new(3, 12)).unwrap(), Position::new(3, 10));

使用String进行文本操作

目前,此crate适用于类似str的文本表示。UTF8编码的字符串在内存中高效打包,这意味着

  1. 👍 存储这些字符串的内存开销低。
  2. 👍 内容在内存中连续,因此随机访问和字符迭代速度快(这对于在lsp和本地位置之间进行转换非常重要)。
  3. 👎 修改字符串很慢,因为它需要与字符串长度成比例的时间。

由于我们通常更多地查询数据而不是更改数据(在LSP服务器的情况下),因此第3点的性能影响可能不会成为问题。因此,对于许多应用程序来说,使用String应该是没有问题的。

然而,有一个由Rope支持的实现不会伤害(尽管目前这不是优先事项)。

依赖关系

~2–3MB
~89K SLoC