///|
/// 描述一次同步补全发生时的行缓冲区和当前词。
pub(all) struct CompletionContext {
/// 光标之前的完整文本。
before_cursor : String
/// 光标之后的完整文本。
after_cursor : String
/// 光标前最大的连续非空白后缀。
current_word : String
} derive(@debug.Debug)
///|
/// 保存一个 `LineEditor` 的共享 completer 注册状态。
priv struct CompletionState {
mut completer : ((CompletionContext) -> Array[String])?
}
///|
fn CompletionState::new() -> CompletionState {
{ completer: None }
}
///|
fn CompletionState::get(
self : CompletionState,
) -> ((CompletionContext) -> Array[String])? {
self.completer
}
///|
/// 注册或替换当前 editor 的同步 completer。
///
/// completer 在用户按 Tab 时同步执行。参数中的三个字符串均由 MoonBit 独立持有;返回
/// 的每个字符串表示对 `current_word` 的完整替换。空字符串会被忽略,重复候选保留第一
/// 项;空数组表示没有候选。单候选直接替换,多候选先扩展最长公共前缀,再次按 Tab 时
/// 按返回顺序列出候选。库不会用非前缀的公共部分缩短当前输入。
///
/// **Parameters:**
///
/// - `completer`:不抛异常的同步 callback;库不会按当前词筛选返回值或追加空格。
///
/// **Errors:**
///
/// 当前进程正在读取,或者从 completion callback 中重入时抛出 `Busy`。
///
/// **Lifecycle:**
///
/// `LineEditor` 的所有别名共享同一个 completer。callback 只由 MoonBit 状态持有;读取
/// 开始时取得的快照会强持有到本次 `read_line()` 结束。
///
/// **Thread safety:**
///
/// 此方法不提供跨线程同步;活跃读取期间不会等待,而是抛出 `Busy`。
pub fn LineEditor::set_completer(
self : LineEditor,
completer : (CompletionContext) -> Array[String],
) -> Unit raise ReadlineError {
self.ensure_usable()
guard self.owner.can_update_completion() else { raise Busy }
self.completion.completer = Some(completer)
}
///|
/// 清除当前 editor 注册的同步 completer。
///
/// 清除后,后续 Tab 不再调用先前的 callback。已经开始的读取不会在运行中切换
/// completer。
///
/// **Errors:**
///
/// 当前进程正在读取,或者从 completion callback 中重入时抛出 `Busy`。
///
/// **Lifecycle:**
///
/// `LineEditor` 的所有别名共享清除结果;不需要单独释放 callback 注册。
pub fn LineEditor::clear_completer(
self : LineEditor,
) -> Unit raise ReadlineError {
self.ensure_usable()
guard self.owner.can_update_completion() else { raise Busy }
self.completion.completer = None
}