TextFormation 是一个简单的规则系统,可用于实现输入补全和空格控制。可以理解为匹配 "}" 和 "{" 并进行缩进。
dependencies: [
.package(url: "https://github.com/ChimeHQ/TextFormation", from: "0.8.0")
]
TextFormation 的核心模型是一个 Filter
(过滤器)。通常,针对一种给定的语言,过滤器只需设置一次。之后,将以 TextMutation
(文本突变)的形式的变化输入到过滤器中。过滤器在 TextMutation
**应用之前**对其进行检查。一个过滤器可以有三种可能的结果动作。
none
表示该突变应该传递到列表中的下一个过滤器stop
表示不应该应用进一步的过滤discard
就像 stop,但也意味着 TextMutation
不应该被应用过滤器不一定会更改文本。您必须尊重过滤器的动作,确保在 none
和 stop
的情况下实际应用突变。过滤器的设计努力允许突变发生,以帮助维持标准文本视图的预期选择和撤销行为。
谨慎地使用过滤器嵌套(可能使用 CompositeFilter
)和这些动作可以产生一些非常强大的行为。这是一个链的例子,它产生的输入补全大致匹配 Xcode 对开/闭花括号的处理方式
// skip over closings
let skip = SkipFilter(matching: "}")
// apply whitespace to our close
let closeWhitespace = LineLeadingWhitespaceFilter(string: "}")
// handle newlines inserted in between opening and closing
let newlinePair = NewlineWithinPairFilter(open: "{", close: "}")
// auto-insert closings after an opening, with special-handling for newlines
let closePair = ClosePairFilter(open: "{", close: "}")
// surround selection-replacements with the pair
let openPairReplacement = OpenPairReplacementFilter(open: "{", close: "}")
// delete a matching close when adjacent and the opening is deleted
let deleteClose = DeleteCloseFilter(open: "{", close: "}")
let filters: [Filter] = [skip, closeWhitespace, openPairReplacement, newlinePair, closePair, deleteClose]
// treat a "stop" as only applying to our local chain
let filter = CompositeFilter(filters: filters, handler: { (_, action) in
switch action {
case .stop, .none:
return .none
case .discard:
return .discard
}
})
这种用法可能会很常见,所以所有这些行为都被封装在一个预制过滤器中:StandardOpenPairFilter
。
let filter = StandardOpenPairFilter(open: "{", close: "}")
使用过滤器
// simple indentation algorithm that uses minimal text context
let indenter = TextualIndenter()
// delete any trailing whitespace, and use our indenter to compute
// any needed leading whitespace using a four-space unit
let providers = WhitespaceProviders(leadingWhitespace: indenter.substitionProvider(indentationUnit: " ", width: 4),
trailingWhitespace: { _, _ in return "" })
let action = filter.shouldProcessMutation(mutation, in: textView, with: providers)
还有一个名为 TextViewFilterApplier
的类型,可以更轻松地将过滤器连接到 NSTextView
或 UITextView
。您只需要使用其中一个代理方法即可
public func textView(_ textView: NSTextView, shouldChangeTextInRanges affectedRanges: [NSValue], replacementStrings: [String]?) -> Bool
public func textView(_ textView: NSTextView, shouldChangeTextInRange affectedRange: NSRange, replacementString: String?) -> Bool
public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool
在一般情况下正确地缩进可能需要解析。它通常还需要一些对用户偏好的理解。包含的 TextualIndenter
类型具有一个基于模式的系统,可以在许多情况下充分地执行缩进。
它还包括一些语言的预定义模式
TextualIndenter.rubyPatterns
TextualIndenter.pythonPatterns
我们很乐意收到您的来信!通过 issue 或 pull request 与我们联系。
请注意,此项目以 贡献者行为准则 发布。通过参与此项目,您同意遵守其条款。