Reference

History

首先阅读一下文档https://codemirror.net/docs/ref/#h_undo_history,可以了解到history相关通过如下:

  • 可以通过history()来创建history扩展,支持一下配置
    • minDepth,允许的最小history事件,默认值为100
    • newGroupDelay,间隔多长多历史事件进行分组,默认值为500
  • historyKeymap提供默认的history操作的键绑定
  • historyField脱敏化的状态字段
  • undo,撤销命令
  • redo,重做命令
  • undoSelection,涉及取选的撤销命令
  • redoSelection,设计取选的重做命令
  • undoDepth,可撤销的命令计数
  • redoDepth,可重做的命令计数
  • isolateHistory,在历史记录中,将有此标记的transaction与其他transaction区分开来,区分办法包括before, after以及full
  • invertedEffects,此凡侧(facet)可以注册一个函数,用于增加特定的效果到历史记录中,这些效果可以被撤销和重做。

Annotation

https://codemirror.net/docs/ref/#state.Annotation

  • 一种给transaction添加元数据的方式,具有扩展性。用来给影响这个transaction的动作建模(比如时间戳,源头等等)。对于transaction执行过程产生的影响,则用state effect建模比较合适。

  • 结构

    • type
    • value
    • 镜头的define<T>()用于定义类型

StateEffect

https://codemirror.net/docs/ref/#state.StateEffect

用于表示transaction过程中产生的影响。多用于给自定state field的变动建模。

  • 结构

    • value
    • map,通过位置映射重调effect
    • is<T>,判断effect类型
    • 静态的define<Value=null>,定义一个新的effect
    • 静态的mapEffects,把一个effect数组过映射一个变动集
    • 静态的reconfigure,用于重配置root扩展
    • 静态的appendConfig,将扩展附加到顶级配置

ChangeDesc

https://codemirror.net/docs/ref/#state.ChangeDesc

是changeSet的变体,但是不储存插入的文本,因此无法被应用,但是更轻量

  • 结构
    • length,变动前文档的长度
    • newLength,变动后文档的长度
    • empty,是否有具体变动
    • iterGaps(),遍历未变动的部分
    • iterChangedRanges(),遍历已变动的部分
    • invertedDesc,给出逆变形式
    • composeDesc,
    • mapDesc,
    • mapPos,
    • touchesRange()

ChangeSet

https://codemirror.net/docs/ref/#state.ChangeSet

System Guide

Configuration

然后再阅读一下系统介绍文档:https://codemirror.net/docs/guide/#configuration:

  • 每个编辑器状态都藏有自己的配置,通常是从激活的扩展中得出的。通常的transaction处理中,这些配置保持不变。 但是可以使用compartment或者efect来重新配置。

    • 每个状态配置的直接effect是它存储的fields以及facets关联到的值。
  • 一个Facet是一个扩展点。不同的扩展可以为同一facet提供值。可以从state得出face的值。

    • Facet是值的聚合,它可以是多个值构成的数组,或者从若干值计算得出的值
      • 可以是tab size
      • 可以是event handlers
      • 可是对allowMultipleSelections的计算
    • Facet需要明白定义,并产生一个facet值。此值可导出,在其他地方为其充值或者取值。
    • Facet大多数是静态的,但也可以从state的其他分部动态得出

Extending CodeMirror

  • State Fields可以让扩展存储额外的信息到state中,比如undo需要存储撤销记录,folding需要存储被折叠的区域。

    • 扩展可以自定义State Field,但是只能存储不可改值。
    • State field采用reducer与state的剩余部分保持同步,每次state更新,都会调用一个函数,参数为当前值和需处理的transaction
    • annotations和effect可以帮助沟通state field的变化
  • 扩展的结构

    • 通常,在编辑器上实现一个有用的扩展需要涉及几方面:一个state field用于保持状态、一个基底主题来提供样式,一个视图插件来管理输入输出,再加上一些命令,然后带一个facet用于配置。

    • 常见的办法是为扩展导出一个返回扩展值的函数。

    • 扩展会拉入其他扩展,所以要考虑扩展被拉入多次的情况。

    • 扩展的多个例现如果是同一个值,那么编辑器会自动去重

    • 但是如果扩展的配置会发生变化呢?有时候这是个错误,但其他情况下可以定义一定的策略来协调不同的配置。可以用facet来担此任。此facet可以藏于模块内,其整合函数要么协调不同的配置,要么抛出错误。

history.ts

history相关部分的源码在https://github.com/codemirror/commands.git中,只有一个文件,即src/history.ts

  • 定义了一个annotation:fromHistory,值为{side: BranchName, rest: Branch}

    • BranchName是redo、undo二选一,Branch是历史事件合集
  • 定义了一个annotation:isolateHistory

  • 定义了一个facet:invertedEffects

  • 定义了一个facet:historyConfig,内部用

  • 定义了一个state field:historyField,其值类型是HistoryState。

    • HistoryState
      • 有两个分支,done,undo
      • addChanges,记录一个某时发生的HistEvent事件
        • 设定层层条件之后,将一个HistEvent添加到done分支
      • addSelection,记录一个某时发生的取选
      • addMapping,对于给定的mapping做出反应
      • pop,从某分支中弹出一个记录
  • 定义了一个HistEvent类型,用来保存一组改动或者效应

    • 结构
      • changes,类型为ChangeSet
      • effects,类型为StateEffect<any>[]
      • mapped,累计的mapping
      • startSelection,此事件之前的取选
      • selectionAfter,此事件之后的取选

Example: Undoable Effects

如果将某操作以state effect建模,则可以让history模块来重做和撤销之。 文中举的例子是为文本增加高亮。

感想

  • facet或许可以翻译成剖面吗?

(下面没有了)