深入剖析vscode工具函数(七)range模块

703 阅读3分钟

深入剖析vscode工具函数(七)range模块

VSCode的range模块

range 模块是VSCode中的一个基础的模块,用来处理编辑器中的范围。这个范围可以是一个抽象的区间,可以是区域的宽高,可以是字符的长度等等,应用场景不一。位于 commonrange 是一个非常通用的模块,在 editor 里面还有专门为编辑器设计的专用API。

IRange的定义

export interface IRange {
 startnumber;
 endnumber;
}

IRange 接口只有两个属性:startend。这两个属性都是数字类型,可以理解为区间的起点和终点。在实际应用中,IRange 接口可以用于表示各种文本范围,例如单个字符、单词、行、段落等。IRange 接口可以被用于实现各种文本操作,例如搜索、高亮、选择、拖拽等。IRange 接口的简单定义使其易于使用,并且可以根据具体需求进行扩展和定制。

区间的交集

 export function intersect(one: IRange, other: IRange): IRange {
   if (one.start >= other.end || other.start >= one.end) {
    return { start0end0 };
   }
 
   const start = Math.max(one.start, other.start);
   const end = Math.min(one.end, other.end);
 
   if (end - start <= 0) {
    return { start0end0 };
   }
 
   return { startend };
  }

这段算法实现了区间的交集,我们给个图示:

区间 one:   |-----| (start: 2, end: 7)
区间 other:       |-----| (start: 6, end: 11)
交集结果:      | (start6end7)

这个交集的实现就是找到 start 的最大值和 end 的最小值,它们这个区间就是交集。

在VSCode这个实现版本中,我认为两个判断条件其实有一个是冗余的:

  • one.start >= other.end || other.start >= one.end 这个排除了不相交的情况
  • end - start <= 0 其实也是排除了不相交的情况

这两个判断条件理论上只需要一个,如果写了第一个判断条件,应该下面的判断条件是不可能会走到的。(如果真的有这个情况恳请斧正)。

区间的相对差集

export function relativeComplement(one: IRange, other: IRange): IRange[] {
  const result: IRange[] = [];
  const first = { start: one.start, end: Math.min(other.start, one.end) };
  const second = { start: Math.max(other.end, one.start), end: one.end };

  if (!isEmpty(first)) {
   result.push(first);
  }

  if (!isEmpty(second)) {
   result.push(second);
  }

  return result;
 }

这个算法表示的是计算相对差集(relative complement),即计算区间 one(IRange)中不在区间 other(IRange)内的部分。以下是一个简单的图示,显示了两个区间的相对补集算法:

区间 one:   |-----| (start: 2, end: 7)
区间 other:       |-----| (start: 4, end: 6)
相对补集:   |--|   |-| (start: 2, end: 4) 和 (start: 6, end: 7)

这个函数的实现也比较简单,它首先将一个范围按照另一个范围进行分割,得到两个子范围。然后,函数检查两个子范围是否为空,如果不为空,则将它们添加到一个数组中,最后返回这个数组。

在VSCode中的应用

其实 range 里定义的算法都是通用的,我们可以将区间看成是代码的行列数,那么它们的交集和补集就是代码区块的重叠,如果将它看成元素的宽高区域,那么交集和补集就是元素的分割与重叠。

image

image

可以看到在VSCode的 listview 布局中就大量使用 range 中的算法去计算列表的可视范围和动态区域。

小结

在本文中,我们讨论了 VS Code 中 range 模块非常常用的两个函数:intersectrelativeComplement。这些函数是编辑器操作中非常基础而实用的函数,它们的实现也非常简单易懂。

intersect 函数用于计算两个范围的交集,并返回一个新的范围对象。这个函数可以帮助我们在实现文本编辑功能时,计算出选中范围和操作范围的交集,从而只操作交集部分的文本。

relativeComplement 函数用于计算一个范围相对于另一个范围的差集,并返回一个范围对象数组。这个函数可以帮助我们在实现文本编辑功能时,计算出要操作的范围和要排除的范围之间的差集,从而只操作差集部分的文本。

这两个函数的实现非常简单,但在实际的编辑器操作中非常实用。掌握这两个函数的使用,可以使得我们在理解VSCode关于列表布局、编辑器相关核心代码的时候更加清晰。