@@ -83,6 +83,7 @@ func (e *xcodeExporter) Export(
8383) (* pluginapi.PluginExportReport , error ) {
8484 // Decode existing config for non-destructive merge
8585 var existingKeybindings []xcodeKeybinding
86+ var existingTextKeybindings xcodeTextKeybinding
8687 if opts .ExistingConfig != nil {
8788 // Read all content first
8889 rawData , err := io .ReadAll (opts .ExistingConfig )
@@ -95,6 +96,7 @@ func (e *xcodeExporter) Export(
9596 return nil , fmt .Errorf ("failed to decode existing config: %w" , err )
9697 }
9798 existingKeybindings = plistData .MenuKeyBindings .KeyBindings
99+ existingTextKeybindings = plistData .TextKeyBindings .KeyBindings
98100 }
99101
100102 var unmanagedKeybindings []xcodeKeybinding
@@ -109,14 +111,22 @@ func (e *xcodeExporter) Export(
109111 // Reorder according to base command order if provided
110112 finalKeybindings = orderByBaseCommand (finalKeybindings , existingKeybindings )
111113
114+ // Generate text key bindings
115+ finalTextKeybindings := e .generateTextKeyBindings (setting , existingTextKeybindings )
116+
112117 // Use plist library to generate the XML
113118 plistData := xcodeKeybindingsPlist {
114119 MenuKeyBindings : menuKeyBindings {
115120 KeyBindings : finalKeybindings ,
116121 },
122+ TextKeyBindings : textKeyBindings {
123+ KeyBindings : finalTextKeybindings ,
124+ },
117125 }
118126
119- if err := plist .NewEncoder (destination ).Encode (plistData ); err != nil {
127+ encoder := plist .NewEncoder (destination )
128+ encoder .Indent ("\t " )
129+ if err := encoder .Encode (plistData ); err != nil {
120130 return nil , fmt .Errorf ("failed to write plist XML: %w" , err )
121131 }
122132
@@ -146,6 +156,7 @@ func (e *xcodeExporter) identifyUnmanagedKeybindings(existingKeybindings []xcode
146156
147157// findMappingByXcodeKeybinding performs reverse lookup to find if an Xcode keybinding
148158// corresponds to any action in our mappings.
159+ // It checks both Action (for Menu Key Bindings) and CommandID.
149160func (e * xcodeExporter ) findMappingByXcodeKeybinding (kb xcodeKeybinding ) * mappings.ActionMappingConfig {
150161 for _ , mapping := range e .mappingConfig .Mappings {
151162 for _ , xcodeConfig := range mapping .Xcode {
@@ -230,3 +241,51 @@ func (e *xcodeExporter) mergeKeybindings(managed, unmanaged []xcodeKeybinding) [
230241
231242 return result
232243}
244+
245+ // generateTextKeyBindings generates Xcode Text Key Bindings from KeymapSetting.
246+ // It merges managed text bindings with existing ones, with managed taking priority.
247+ func (e * xcodeExporter ) generateTextKeyBindings (
248+ setting * keymapv1.Keymap ,
249+ existingTextBindings xcodeTextKeybinding ,
250+ ) xcodeTextKeybinding {
251+ // Start with existing text bindings or create new map
252+ result := make (xcodeTextKeybinding )
253+ for k , v := range existingTextBindings {
254+ result [k ] = v
255+ }
256+
257+ // Generate managed text bindings
258+ for _ , km := range setting .GetActions () {
259+ mapping := e .mappingConfig .Get (km .GetName ())
260+ if mapping == nil {
261+ continue
262+ }
263+
264+ xcodeConfigs := mapping .Xcode
265+ if len (xcodeConfigs ) == 0 {
266+ continue
267+ }
268+
269+ for _ , b := range km .GetBindings () {
270+ if b == nil {
271+ continue
272+ }
273+ binding := keymap .NewKeyBinding (b )
274+ keys , err := formatKeybinding (binding )
275+ if err != nil {
276+ e .logger .Warn ("Skipping text keybinding with un-formattable key" , "action" , km .GetName (), "error" , err )
277+ continue
278+ }
279+
280+ for _ , xcodeConfig := range xcodeConfigs {
281+ if xcodeConfig .TextAction == "" {
282+ continue
283+ }
284+ // Managed text bindings override existing ones with same key
285+ result [keys ] = xcodeConfig .TextAction
286+ }
287+ }
288+ }
289+
290+ return result
291+ }
0 commit comments