19 个稳定版本
1.2.5 | 2023年10月31日 |
---|---|
1.2.4 | 2023年10月12日 |
1.2.3 | 2023年9月20日 |
1.1.2 | 2023年8月4日 |
1.0.6 | 2023年3月27日 |
#340 在 数据结构 中
每月下载量 155
在 3 个crate中使用(通过parsec-core)
315KB
6.5K SLoC
AnyRope
AnyRope 是一个为 Rust 设计的任意数据类型绳数据结构,旨在执行类似绳的操作,但针对的是非文本数据类型。
示例用法
这种用法的一个例子是在文本编辑器中对文本进行标记,例如,可以将一个文本绳与一个标记绳相关联。
// The tags that will be assossiated with a piece of text, that could be a rope.
#[derive(Clone, Copy, PartialEq, Eq)]
enum Tag {
PrintRed,
Underline,
Normal,
Skip(usize)
}
use Tag::*;
impl any_rope::Measurable for Tag {
type Measure = usize;
fn measure(&self) -> Self::Measure {
match self {
// The zero here represents the fact that multiple tags may be placed
// in the same character.
PrintRed | Underline | Normal => 0,
// Skip here is an amount of characters with no tags in them.
Skip(amount) => *amount
}
}
}
// An `&str` that will be colored.
let my_str = "This word will be red!";
// Here's what this means:
// - Skip 5 characters;
// - Change the color to red;
// - Skip 4 characters;
// - Change the rendering back to normal.
let mut tags = any_rope::Rope::from_slice(&[Skip(5), PrintRed, Skip(4), Normal]);
// Do note that Tag::Skip only represents characters because we are also iterating
// over a `Chars` iterator, and have chosen to do so.
// An empty range, when used in an inclusive removal
// will remove all 0 width elements in that specific
// width. `Rope::remove_exclusive()` would keep them.
// In this case, that would be `Tag::PrintRed`
//
// The reason why we need to pass in a comparison
// function is because of the flexibility of the
// `Measurable::Measure` type. By passing various
// types of comparison functions, we can selectively
// choose what we are looking for. This is similar to
// what regular ropes do when searching within text,
// the end user can search by byte, char, line, etc.
tags.remove_inclusive(5..5, usize::cmp);
// In place of that `Tag::PrintRed`, we will insert `Tag::Underline`.
tags.insert(5, Underline, usize::cmp);
// The AnyRope iterator not only returns the element in question, but also the width
// where it starts.
let mut tags_iter = tags.iter().peekable();
for (cur_index, ch) in my_str.chars().enumerate() {
// The while let loop here is a useful way to activate all tags within the same
// character. For example, we could have a sequence of [Tag::UnderLine, Tag::PrintRed]
// in the `Rope`, both of which have a width of 0, allowing one to execute multiple
// `Tag`s in a single character.
while let Some((index, tag)) = tags_iter.peek() {
if *index == cur_index {
activate_tag(tag);
tags_iter.next();
} else {
break;
}
}
print!("{}", ch);
}
何时使用 AnyRope?
到目前为止,我还没有在其他地方找到 AnyRope 的用途,除了文本编辑器,但我不会排除它可能在其他地方有用的可能性。
功能
宽度概念
实现 Measurable 的元素的宽度可以是最终用户想要的任何宽度,这使 AnyRope 能够以非常灵活的方式在多个方面发挥作用。
绳切片
AnyRope 有绳切片,允许您仅使用绳的一部分,使用全部绳的只读操作,包括迭代器和子切片。
灵活的 API 和低级访问
尽管 AnyRope 故意限制了范围,但它也提供了 API 以高效地访问和处理其内部切片块表示,允许客户端代码以最小的开销高效地实现附加功能。
线程安全
AnyRope 确保即使克隆共享内存,一切也都是线程安全的。克隆可以被发送到其他线程进行读写。
不安全代码
AnyRope 使用不安全代码来实现一些空间和性能特性。尽管已尽力将不安全代码隔离并使其正确,但在可能面临对抗性条件的软件中使用 AnyRope 时请谨慎。
许可证
AnyRope 根据 MIT 许可证授权(LICENSE.md 或 http://opensource.org/licenses/MIT)
贡献
贡献绝对欢迎!然而,请开启一个issue或给我发邮件讨论较大的变更,以避免做很多可能被拒绝的工作。
除非你明确表示不同,否则你提交给AnyRope的任何贡献将按照上述方式授权,不附加任何额外条款或条件。