MoonBit-native keyboard shortcut conflict, context, platform, accessibility, and CI analysis toolkit.
git clone https://github.com/zhangbowen2006/MoonKeyguard.git
cd MoonKeyguard
moon check --deny-warn
moon test --deny-warn
moon run cmd/mainmoon run cmd/main -- --format json
moon run cmd/main -- --format markdown --suggest
moon run cmd/main -- --format sarif --fail-on-warning
moon run cmd/main -- --metrics
moon run cmd/main -- --source "bind save command=save keys=Ctrl+S" --name quick-demokeymap name=editor version=1
context global parent= rank=0 description=all-windows
context editor parent=global rank=10 description=text-editor
reserve Cmd+Q platform=mac
bind save command=editor.save keys=Ctrl+S context=editor platform=all priority=10 description=save-buffer
bind jump_line command=editor.jump_line keys=Ctrl+K,Ctrl+L context=editor platform=all priority=5 description=jump-linelet parsed = @moonkeyguard.parse_keymap(source, name="editor")
if !parsed.ok {
println(@moonkeyguard.parse_diagnostics_to_json(parsed.diagnostics))
}
let analysis = @moonkeyguard.analyze(parsed.keymap)
println(@moonkeyguard.analysis_to_markdown(analysis))
let suggestions = @moonkeyguard.suggest_all(parsed.keymap, analysis)
println(@moonkeyguard.suggestions_to_markdown(suggestions))| API | 用途 |
|---|---|
| parse_keys / canonical_keys | 解析并规范化快捷键序列 |
| parse_keymap | 解析 DSL,返回结构化 parser diagnostics |
| analyze / audit | 运行冲突、上下文、平台、保留键和可访问性规则 |
| suggest_for / suggest_all | 生成不占用保留键的替换建议 |
| analysis_to_text/json/markdown/sarif | 生成终端、文档、机器和 GitHub 代码扫描报告 |
| build_conflict_graph | 计算冲突边、连通分量和 hotspot |
| diff_keymaps / migration_plan | 对两个版本做按 id 的语义 diff |
| reachability_matrix / reachability_to_* | 按 context/platform 证明绑定可达、遮蔽和不可用状态 |
| compare_baseline / baseline_report_to_* | 只阻止新增风险,保留历史问题作为可追踪债务 |
let report = @moonkeyguard.reachability_matrix(
parsed.keymap,
contexts=["global", "editor"],
platforms=["all", "mac"],
)
println(@moonkeyguard.reachability_to_markdown(report))let baseline = @moonkeyguard.analyze(@moonkeyguard.parse_keymap(old_source).keymap)
let current = @moonkeyguard.analyze(@moonkeyguard.parse_keymap(new_source).keymap)
let report = @moonkeyguard.compare_baseline(baseline, current)
println(@moonkeyguard.baseline_report_to_markdown(report))moon run examples/basicmoon check --deny-warn
moon build
moon test --deny-warn
moon fmt --check
moon infomoon test --deny-warnpub(all) struct AuditTimeline {
project : String
events : Array[TimelineEvent]
baseline : String
} derive(Eq, Debug)pub(all) struct BaselineReport {
baseline_fingerprint : String
current_fingerprint : String
baseline_count : Int
current_count : Int
new_findings : Array[Finding]
resolved_findings : Array[Finding]
retained_count : Int
new_error_count : Int
new_warning_count : Int
new_info_count : Int
fail_on_warning : Bool
passed : Bool
} derive(Eq, Debug)pub(all) struct BenchmarkCase {
name : String
inputs : Array[String]
context : String
platform : String
expected_status : DispatchStatus
repetitions : Int
} derive(Eq, Debug)pub(all) struct Binding {
id : String
command : String
keys : KeySequence
context : String
platform : String
source : String
line : Int
priority : Int
enabled : Bool
description : String
} derive(Eq, Debug)fn Binding::new(id : String, command : String, keys : KeySequence, context? : String, platform? : String, source? : String, line? : Int, priority? : Int, enabled? : Bool, description? : String) -> Bindingpub(all) struct CatalogReport {
keymap : Keymap
matched : Array[ReservedRule]
unmatched : Array[ReservedRule]
findings : Array[Finding]
} derive(Eq, Debug)pub(all) struct ConflictGraph {
nodes : Array[ConflictNode]
edges : Array[ConflictEdge]
components : Array[Array[String]]
} derive(Eq, Debug)pub(all) struct DispatchResult {
status : DispatchStatus
input : String
canonical : String
command : String
binding_ids : Array[String]
context : String
platform : String
message : String
} derive(Eq, Debug)pub(all) struct DispatchStep {
input : String
result : DispatchResult
elapsed_ms : Int
} derive(Eq, Debug)pub(all) struct DispatchTrace {
context : String
platform : String
steps : Array[DispatchStep]
matched_count : Int
prefix_count : Int
no_match_count : Int
} derive(Eq, Debug)pub(all) struct ImportReport {
keymap : Keymap
rows_seen : Int
rows_imported : Int
diagnostics : Array[ParseDiagnostic]
} derive(Eq, Debug)fn KeySequence::new(raw : String, steps : Array[String], canonical : String, has_modifier : Bool, modifier_count : Int) -> KeySequencepub(all) struct KeymapDiff {
from_name : String
to_name : String
changes : Array[BindingChange]
added : Int
removed : Int
modified : Int
unchanged : Int
context_added : Int
context_removed : Int
reserved_added : Int
reserved_removed : Int
} derive(Eq, Debug)pub(all) struct ParseResult {
keymap : Keymap
diagnostics : Array[ParseDiagnostic]
ok : Bool
} derive(Eq, Debug)pub(all) struct ProfileReport {
profile : PolicyProfile
parse : ParseResult
analysis : Analysis
metrics : KeymapMetrics
passed : Bool
gate_messages : Array[String]
} derive(Eq, Debug)pub(all) struct ReachabilityCell {
binding_id : String
context : String
platform : String
status : ReachabilityStatus
selected_id : String
message : String
} derive(Eq, Debug)pub(all) struct ReleaseInput {
keymap : Keymap
analysis : Analysis
validation : ValidationReport
profile : ProfileReport?
benchmark : Array[BenchmarkResult]
diff : KeymapDiff?
} derive(Eq, Debug)pub(all) struct RuleReport {
rules : ProjectRules
findings : Array[Finding]
passed : Bool
} derive(Eq, Debug)pub(all) struct StructuralIssue {
kind : StructuralKind
code : String
message : String
id : String
line : Int
severity : Severity
} derive(Eq, Debug)pub(all) struct TimelineDelta {
previous : TimelineEvent?
current : TimelineEvent
score_delta : Int
errors_delta : Int
warnings_delta : Int
regressed : Bool
} derive(Eq, Debug)pub(all) struct TimelineEvent {
sequence : Int
label : String
actor : String
kind : TimelineEventKind
fingerprint : String
errors : Int
warnings : Int
score : Int
note : String
} derive(Eq, Debug)pub(all) struct ValidationReport {
keymap_name : String
issues : Array[StructuralIssue]
error_count : Int
warning_count : Int
valid : Bool
} derive(Eq, Debug)fn benchmark_case(name : String, inputs : Array[String], context? : String, platform? : String, expected_status? : DispatchStatus, repetitions? : Int) -> BenchmarkCasefn canonical_keys(raw : String) -> Stringfn clean_demo_source() -> Stringfn compare_baseline(baseline : Analysis, current : Analysis, fail_on_warning? : Bool) -> BaselineReportfn demo_source() -> Stringfn platforms_overlap(left : String, right : String) -> Boolfn reachability_matrix(keymap : Keymap, contexts? : Array[String], platforms? : Array[String]) -> ReachabilityReportfn replay(keymap : Keymap, inputs : Array[String], context? : String, platform? : String) -> DispatchTracefn row(id : String, command : String, keys : String, context? : String, platform? : String, priority? : String, enabled? : String, description? : String) -> BindingRowfn select_bindings(keymap : Keymap, command? : String, context? : String, platform? : String, enabled_only? : Bool) -> KeymapSelectionfn timeline_append(timeline : AuditTimeline, label : String, actor : String, kind : TimelineEventKind, analysis : Analysis, note? : String) -> AuditTimelinefn timeline_record_gate(timeline : AuditTimeline, label : String, actor : String, analysis : Analysis, note? : String) -> AuditTimelineInstall
Download zipMoonBit-native keyboard shortcut conflict, context, platform, accessibility, and CI analysis toolkit.