hecto - 手把手教你写个 文本编辑器

https://www.philippflenker.com/hecto/ 的阅读笔记。 我是学完[[Rust权威指南]] 之后才看的这个。
手把手教你写个 文本编辑器(1300+行代码)。
作者是真有耐心,真手把手教。看文章+手敲一遍,我大概花了十几个小时。
收获很大,很值得。

day1 环境搭建

https://www.philippflenker.com/hecto-chapter-1/
就是初始化项目。

day2 读用户输入

https://www.philippflenker.com/hecto-chapter-2/

介绍了 io的模式。
默认模式是缓冲i/o , 缓冲i/o 是遇到回车才发送给用户程序。

但是文本编辑器需要即时i/o, 即没输入1个字符,程序都需要立即拿到。
第三方库termion可以让我们使用 raw mode(即时I/O)。

之所以stdout().into_raw_mode().unwrap()
是因为stdout 才是控制 终端模式的。
变量名_stdout之所以加个_ 是rust 的所有权机制导致的。
如果不加,会马上释放掉,从而丢失了状态。

提到了控制字符和打印字符。
0-31,127 都是控制字符。
32-126 都是打印字符。

ctrl+x 就是把x的前3位置0了。

二进制表示用{:#b}占位符。

提到了错误处理。。rust 是用Result来传递错误。Result是个枚举,要么有值,有么错误。 unwrap就是配合Result使用的。如果值正常,就返回值,否则panic

提到了match 模式匹配。

day3 原始输入和输出

https://www.philippflenker.com/hecto-chapter-3/
讲的就是不要重复造轮子,直接用termion 实现按键的检测。
Key::Char,Key::Ctrl,Key::Alt
去掉了底层的处理,,
从处理字节 变成了处理字符。

提到了Matches必须穷举。
提到了分离代码。。main只提供入口,尽量精简。
然后没有;的语句是表达式,也是函数的返回值。

struct 里的函数,第一个参数不是&self的是关联函数,也叫静态方法。否则就是关联方法。
cargo clippy 可以提供一些建议,让我们的代码更地道。

提到了转义序列 可以指示中断干些事,譬如为文本着色啥的。
x1b[2J
x1b = 按下esc 具体说明看vt100
J 是清除屏幕命令
2J的参数。0表示清除cursor-end 位置的屏幕。1表示清除start-cursor 位置的屏幕。2表示清除start-end 位置的屏幕。默认值是0

然后关于转义序列的知识 termion也封装好了。
控制鼠标的位置,也是用的转义序列。用的H命令。譬如\x1b[12;40H 鼠标显示在12行,40列。

使用了pub use terminal::Terminal; 重导出声明,这样后面用的时候 直接用Terminal就可以了

saturating_add 用户防止移除的。。譬如u8 最大致是255
直接 255+1 = 0
但是使用 255.saturating_add(1) 返回的是255, 可能产生溢出时,直接返回最大值。

隐藏/显示 鼠标 这里也是转义序列:
x1b[25h 隐藏。x1b[?25l
x1b[25l显示。 x1b[?25h

第一次提到了解构。 let Position{mut x, mut y} = position;

day4 查看文件

https://www.philippflenker.com/hecto-chapter-4/

新增Row, 和 Document结构体。
引入了宏#[derive(Default)] 这玩意是实现代码的代码,会自动给你实现Default方法。

引入了From trait, 这个用于类型转换的。用的挺多的。
例子中就是把&str 转成了Row对象。
Since we have implemented default on Document, we can use unwrap_or_default here.
现在才懂unwrap_or_default干嘛用的。。就是有值返回值,没值是也不抛出错误,而是调用default方法。

目前的结构体:

editor: 主体
document: 文件内容
row: 一行内容
terminal: 表达展示的,譬如移动鼠标,清屏等。
cursor_position: 跟踪鼠标位置
offset: 跟踪document内容偏移量。

![[hecto 2022-11-20 18.21.27.excalidraw]]

https://play.rust-lang.org/ 可用来实验简单的代码。

我们计算鼠标位置 只适应于ascii.
像utf8, 有的字符有2/3个字节,就有问题了。
得把按字节计算的方式改成按字符的方式计算了。

这个借助于第三方库unicode-segmentation

day5 编辑文件

https://www.philippflenker.com/hecto-chapter-5/
这篇感觉没啥新东西。
只能说设计的结构良好。
就是在编辑rows和row 2个数据。

后面说的都是 clippy 提示的。
然后性能优化了下。

极致的性能一般会导致可维护问题,这需要权衡。

day6 搜索

https://www.philippflenker.com/hecto-chapter-6/

1
开始实现的简单搜索,就是在每行里搜字符串,这里要注意的是,返回的索引位置是字符位置,而不是字节位置。
并且遇到第一个匹配行就返回了。

之前封装的prompt 派到用场了。。就是接收用户输入的字符串。。
Option 用的很多。让你不得不考虑可能为空的情况。
2.
然后实现的是实时搜索。就是没输入1个字符就搜素。
这里引入了闭包,作为prompt每次按键的一个回调。同时也引入了泛型。
|_,_,__|{} 这就是个闭包函数。

如果用户取消搜索。还原光标位置。没啥好说的,增加个变量存下原位置。
引入了clone, 有深拷贝和浅拷贝。clone,copy trait。

针对1的。这里可以通过按键,滚动到上一个/下一个匹配的位置上。
向前搜索容易,搜索起始位置就是当前的鼠标位置即可。
向后搜索,得加个方向参数了。遍历的时候也要反向遍历。
这里方向参数用的枚举。
rust的枚举相当强大。还可以带数据的。

#[derive(PartialEq, Copy, Clone)]  
pub enum SearchDirection {  
    Forward,  
    Backward,  
}

不得不说rfind真好。省事。

day7 语法高亮

https://www.philippflenker.com/hecto-chapter-7/

  1. 加颜色
    还是用的 转义序列。 前景色+字符+重置前景色
    这个作者牛逼,只需要改row.rs里的render函数就可以了。

  2. 改进。
    上面的有明显的缺陷。
    不够抽象,太具体。不能复用。 增加新的特征加高亮时不方便。
    改进方式是抽象了Type 类型,提供了to_color 返回对应的前景色。
    row增加了highlighting

  3. 改进。之前每个字符都加了颜色。但是连续的字符用同样的颜色时,加一个就够了。
    _ => color::Rgb(0,0,0), 这里我改成了黑色。要不然有点不正常。

  4. 把高亮规则 应用到搜索结果上。增加Match成员。
    又复用了之前写的find方法。很快搜出匹配的下标,增加高亮类型。

  5. 改进数字高亮,变量名带数字的不能高亮。。必须是被空格/符号 分隔开的数字才高量。 这个感觉容易,修改 highlight方法就可以了。

  6. 优化,让数字可以支持小数点。这个实现其实有bug, 3.4.5 也会当成数字高亮。

  7. 增加文件类型检测。就是根据文件名检测。
    在这里插入图片描述

前面的行号是我尝试加的。

  1. 应用文件类型,,根据文件类型做高亮。
    修改 highlight方法, 增加个HighlightingOptions 参数,然后改调用就可以。比较简单。

  2. 另存为是有问题,没有恰当高亮。修复下
    这里隐藏了numbers属性,改成了提供方法。

  3. 增加特性,高亮字符串。就是"包起来的字符"。引入了新概念 *c 解引用。
    在这里插入图片描述

  4. 修复bug, \" 有转义时不能当做结束字符。 处理有点巧妙。遇到\ 直接高亮2个字符。

  5. 增加特性,高亮字符。‘a’ 这种。和高亮字符串不一样。因为还有生命周期'a 语法是不用闭合的。合法的其实只有2中。'x' 和 '\x'.
    ![[Pasted image 20221124162504.png]]

  6. 增加特性,高亮 单行注释。 这个较简单。

在这里插入图片描述

  1. 重构,提高代码质量
    hightlight 分功能出来。不同的高亮规则用自己的函数。

  2. 高亮关键词。
    有之前的铺垫,这个应该好容易。。关键词 就是 高亮搜索词 一样的逻辑。
    ![[Pasted image 20221125213941.png]]

感觉实现的有问题。譬如in

  1. fix in 的问题
    需要有分隔符的 才是关键词。类似数字一样 得加个判断。
    is_separator 调用得改成Self::is_separator

  2. 高亮次要关键词。和高亮主要关键词 一样的。

  3. 高亮 多行注释。
    这个特殊点,之前都是单行处理。这个要跨行了。
    方法是修改highlight 方法,增加个是否是多行注释的标记。
    同时增删改 都需要修改。

  4. 性能优化
    控制高亮从 document 移动 editor中。因为只有需要显示的文档才需要高亮。
    改动分2步。
    第一步 是 高亮文档开始 到 显示的行。
    第二步是 只高亮 显示的行。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值