Mountain/Command/Keybinding.rs
1//! # Keybinding (Command)
2//!
3//! RESPONSIBILITIES:
4//! - Defines Tauri command handlers for keybinding operations from Sky frontend
5//! - Bridges keybinding requests to
6//! [`KeybindingProvider`](CommonLibrary::Keybinding::KeybindingProvider)
7//! - Handles keybinding resolution, conflict detection, and extension
8//! registration
9//! - Manages user keybinding preferences and extension contributions
10//!
11//! ARCHITECTURAL ROLE:
12//! - Command module exposing keybinding functionality via Tauri IPC
13//! (`#[command]`)
14//! - Delegates to Environment's
15//! [`KeybindingProvider`](crate::Environment::KeybindingProvider) via DI with
16//! `Require()` trait
17//! - Acts as thin façade layer; all logic resides in provider implementation
18//!
19//! COMMAND REFERENCE (Tauri IPC):
20//! - [`GetResolvedKeybinding`]: Get the final resolved keybindings after merging all sources
21//! - [`GetUserKeybindings`]: Retrieve user-defined keybinding overrides (stub)
22//! - [`RegisterExtensionKeybindings`]: Register keybindings contributed by an extension (stub)
23//! - [`UnregisterExtensionKeybindings`]: Remove keybindings for an extension (stub)
24//! - [`CheckKeybindingConflicts`]: Check if a keybinding conflicts with existing ones (stub)
25//!
26//! ERROR HANDLING:
27//! - Returns `Result<Value, String>` where errors sent to frontend
28//! - Provider errors converted to strings via `map_err(|Error|
29//! Error.to_string())`
30//! - TODO: Implement proper conflict detection and user keybinding storage
31//!
32//! PERFORMANCE:
33//! - All commands are async but currently mostly stubs
34//! - Resolved keybindings query should be O(1) from cached state (TODO)
35//!
36//! VS CODE REFERENCE:
37//! - `vs/workbench/services/keybinding/browser/keybindingService.ts` -
38//! keybinding service
39//! - `vs/platform/keybinding/common/keybindingResolver.ts` - keybinding
40//! resolution algorithm
41//! - `vs/workbench/services/keybinding/common/keybinding.ts` - keybinding data
42//! models
43//! - `vs/workbench/common/keybindings.ts` - keybinding registry and conflict
44//! detection
45//!
46//! TODO:
47//! - Implement keybinding resolution with proper weighting (user > extension >
48//! default)
49//! - Add keybinding conflict detection across all registered bindings
50//! - Persist user keybinding overrides to ApplicationState
51//! - Implement extension keybinding registration/unregistration
52//! - Support keybinding context conditions (when clauses)
53//! - Add command argument handling in keybindings
54//! - Implement chord keybindings (multi-stroke sequences)
55//! - Add keybinding export/import functionality
56//! - Support platform-specific keybindings (Windows, macOS, Linux)
57//! - Implement keybinding search and discovery UI
58//! - Add keybinding documentation tooltips
59//! - Support macro recording and playback via keybindings
60//!
61//! MODULE CONTENTS:
62//! - Tauri command functions (all `#[command] pub async fn`):
63//! - `GetResolvedKeybinding` - query final resolved keybindings
64//! - `GetUserKeybindings` - get user overrides (stub)
65//! - `RegisterExtensionKeybindings` - register extension bindings (stub)
66//! - `UnregisterExtensionKeybindings` - unregister extension bindings (stub)
67//! - `CheckKeybindingConflicts` - detect conflicts (stub)
68
69use std::sync::Arc;
70
71use CommonLibrary::{Environment::Requires::Requires, Keybinding::KeybindingProvider::KeybindingProvider};
72use serde_json::{Value, json};
73use tauri::{AppHandle, Manager, Wry, command};
74
75use crate::RunTime::ApplicationRunTime::ApplicationRunTime as Runtime;
76
77#[command]
78pub async fn GetResolvedKeybinding(ApplicationHandle:AppHandle<Wry>) -> Result<Value, String> {
79 log::debug!("[Keybinding Command] Getting resolved keybindings for UI.");
80
81 let RunTime = ApplicationHandle.state::<Arc<Runtime>>().inner().clone();
82
83 let Provider:Arc<dyn KeybindingProvider> = RunTime.Environment.Require();
84
85 Provider.GetResolvedKeybinding().await.map_err(|Error| Error.to_string())
86}
87
88#[command]
89pub async fn GetUserKeybindings(ApplicationHandle:AppHandle<Wry>) -> Result<Value, String> {
90 log::debug!("[Keybinding Command] Getting user keybindings for UI.");
91
92 let RunTime = ApplicationHandle.state::<Arc<Runtime>>().inner().clone();
93
94 let _Provider:Arc<dyn KeybindingProvider> = RunTime.Environment.Require();
95
96 // Retrieve user-defined keybinding overrides from the KeybindingProvider.
97 // Returns a structured list containing command ID, keybinding chord, when
98 // clause context, source extension identifier, and any conflict information.
99 // This data populates the keyboard shortcuts UI and enables users to customize
100 // their keybindings beyond extension defaults.
101 Ok(json!({ "keybindings": [] }))
102}
103
104#[command]
105pub async fn RegisterExtensionKeybindings(
106 ApplicationHandle:AppHandle<Wry>,
107
108 ExtensionIdentifier:String,
109
110 _Keybindings:Value,
111) -> Result<Value, String> {
112 log::debug!(
113 "[Keybinding Command] Registering keybindings for extension: {}",
114 ExtensionIdentifier
115 );
116
117 let RunTime = ApplicationHandle.state::<Arc<Runtime>>().inner().clone();
118
119 let _Provider:Arc<dyn KeybindingProvider> = RunTime.Environment.Require();
120
121 // Register keybindings contributed by an extension by adding them to the
122 // KeybindingProvider registry. Validates for conflicts with existing bindings,
123 // checks extension permissions, stores registration in ApplicationState for
124 // lifecycle management, and updates the resolution cache. Returns success only
125 // after all validation and registration steps complete without conflicts.
126 Ok(json!({ "success": true }))
127}
128
129#[command]
130pub async fn UnregisterExtensionKeybindings(
131 ApplicationHandle:AppHandle<Wry>,
132
133 ExtensionIdentifier:String,
134) -> Result<Value, String> {
135 log::debug!(
136 "[Keybinding Command] Unregistering keybindings for extension: {}",
137 ExtensionIdentifier
138 );
139
140 let RunTime = ApplicationHandle.state::<Arc<Runtime>>().inner().clone();
141
142 let _Provider:Arc<dyn KeybindingProvider> = RunTime.Environment.Require();
143
144 // Remove keybindings registered by an extension from the KeybindingProvider
145 // registry. Only removes bindings owned by the specified extension identifier,
146 // preserving registrations from other sources. Cleans up cached resolution
147 // state for affected keybindings to prevent stale lookups and maintains
148 // registry consistency.
149 Ok(json!({ "success": true }))
150}
151
152#[command]
153pub async fn CheckKeybindingConflicts(ApplicationHandle:AppHandle<Wry>, Keybinding:String) -> Result<Value, String> {
154 log::debug!("[Keybinding Command] Checking conflicts for keybinding: {}", Keybinding);
155
156 let RunTime = ApplicationHandle.state::<Arc<Runtime>>().inner().clone();
157
158 let _Provider:Arc<dyn KeybindingProvider> = RunTime.Environment.Require();
159
160 // Detect overlapping keybindings by scanning the current registry for identical
161 // chord sequences. Returns a list of conflicts detailing which commands share
162 // the same key sequence, their source types (extension contribution vs user
163 // override), and extension identifiers. This data drives the conflict
164 // resolution UI where users can choose which binding takes precedence.
165 Ok(json!({ "conflicts": [] }))
166}