1use {
2 crate::{
3 xkb::{
4 controls::ControlMask,
5 group::GroupChange,
6 group_component::GroupComponent,
7 keymap::{
8 self,
9 actions::{
10 ControlsLockAction, ControlsSetAction, GroupLatchAction, GroupLockAction,
11 GroupSetAction, ModsLatchAction, ModsLockAction, ModsSetAction,
12 RedirectKeyAction,
13 },
14 Action, Indicator, KeyBehavior, KeyGroup, KeyLevel, KeyOverlay, KeyType,
15 },
16 mod_component::ModComponentMask,
17 resolved::GroupsRedirect,
18 rmlvo::{self, MergeMode},
19 Keymap,
20 },
21 Keysym, ModifierMask,
22 },
23 debug_fn::debug_fn,
24 hashbrown::{HashMap, HashSet},
25 isnt::std_1::vec::IsntVecExt,
26 smallvec::SmallVec,
27 std::{
28 fmt::{self, Display, Formatter, Write},
29 sync::Arc,
30 },
31};
32
33pub(crate) struct FormatFormat<'a, T>(pub(crate) &'a T);
34
35impl<T> Display for FormatFormat<'_, T>
36where
37 T: Format,
38{
39 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40 let mut writer = Writer {
41 nesting: 0,
42 multi_line: f.alternate(),
43 lookup_only: false,
44 omit_multiple_actions: false,
45 long_keys: None,
46 newline: match f.alternate() {
47 true => "\n",
48 false => " ",
49 },
50 f,
51 };
52 self.0.format(&mut writer)
53 }
54}
55
56struct Writer<'a, 'b> {
57 nesting: usize,
58 multi_line: bool,
59 lookup_only: bool,
60 omit_multiple_actions: bool,
61 long_keys: Option<HashMap<Arc<String>, String>>,
62 newline: &'static str,
63 f: &'a mut Formatter<'b>,
64}
65
66trait Format {
67 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result;
68}
69
70impl Writer<'_, '_> {
71 fn write(&mut self, s: &str) -> fmt::Result {
72 self.f.write_str(s)
73 }
74
75 fn write_newline(&mut self) -> fmt::Result {
76 self.f.write_str(self.newline)
77 }
78
79 fn write_string(&mut self, s: &str) -> fmt::Result {
80 self.write("\"")?;
81 for c in s.chars() {
82 match c {
83 '\\' => self.write(r"\\")?,
84 '\n' => self.write(r"\n")?,
85 '\r' => self.write(r"\r")?,
86 '\t' => self.write(r"\t")?,
87 _ if (c as u32) < 0x20 || c == '\x7f' || c == '"' => {
88 write!(self.f, r"\{:03o}", c as u32)?
89 }
90 _ => self.f.write_char(c)?,
91 }
92 }
93 self.write("\"")?;
94 Ok(())
95 }
96
97 fn write_key_name(&mut self, name: &Arc<String>) -> fmt::Result {
98 if name.len() > 4 {
99 if let Some(names) = &mut self.long_keys {
100 if let Some(name) = names.get(name) {
101 return self.f.write_str(name);
102 }
103 }
104 }
105 self.write(name)
106 }
107
108 fn write_nesting(&mut self) -> fmt::Result {
109 if self.multi_line {
110 let spaces = self.nesting * 4;
111 write!(self.f, "{:spaces$}", "", spaces = spaces)?;
112 }
113 Ok(())
114 }
115
116 fn write_nested(&mut self, f: impl FnOnce(&mut Self) -> fmt::Result) -> fmt::Result {
117 self.write_newline()?;
118 self.nesting += 1;
119 f(self)?;
120 self.nesting -= 1;
121 Ok(())
122 }
123
124 fn write_inline_list<T>(
125 &mut self,
126 items: &[T],
127 mut f: impl FnMut(&mut Self, &T) -> fmt::Result,
128 ) -> fmt::Result {
129 for (idx, item) in items.iter().enumerate() {
130 if idx == 0 {
131 self.write(" ")?;
132 } else {
133 self.write(", ")?;
134 }
135 f(self, item)?;
136 }
137 Ok(())
138 }
139}
140
141impl Display for keymap::Formatter<'_> {
142 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
143 let mut long_keys = None;
144 if self.rename_long_keys {
145 let mut has_any = false;
146 let mut conflicts = HashSet::new();
147 for key in &self.keymap.keycodes {
148 if key.name.len() > 4 {
149 has_any = true;
150 }
151 if key.name.len() == 4
152 && key.name.as_bytes()[0] == b'K'
153 && key.name.as_bytes()[1..].iter().all(|b| b.is_ascii_digit())
154 {
155 conflicts.insert(key.name.clone());
156 }
157 }
158 let mut names = HashMap::new();
159 if has_any {
160 let mut next = 0u64;
161 for key in &self.keymap.keycodes {
162 if key.name.len() <= 4 {
163 continue;
164 }
165 let name = loop {
166 let name = format!("K{:03}", next);
167 next += 1;
168 if !conflicts.contains(&name) {
169 break name;
170 }
171 };
172 names.insert(key.name.clone(), name);
173 }
174 }
175 if !names.is_empty() {
176 long_keys = Some(names);
177 }
178 }
179 let mut writer = Writer {
180 nesting: 0,
181 multi_line: !self.single_line,
182 lookup_only: self.lookup_only,
183 omit_multiple_actions: !self.multiple_actions_per_level,
184 long_keys,
185 newline: match self.single_line {
186 false => "\n",
187 true => " ",
188 },
189 f,
190 };
191 Format::format(self.keymap, &mut writer)
192 }
193}
194
195impl Format for Keymap {
196 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
197 f.write_nesting()?;
198 f.write("xkb_keymap ")?;
199 if let Some(name) = &self.name {
200 f.write_string(name)?;
201 f.write(" ")?;
202 }
203 f.write("{")?;
204 f.write_nested(|f| {
205 Keycodes(self).format(f)?;
206 f.write_newline()?;
207 f.write_newline()?;
208 Types(self).format(f)?;
209 f.write_newline()?;
210 f.write_newline()?;
211 Compat(self).format(f)?;
212 f.write_newline()?;
213 f.write_newline()?;
214 Symbols(self).format(f)?;
215 f.write_newline()?;
216 Ok(())
217 })?;
218 f.write_nesting()?;
219 f.write("};")?;
220 Ok(())
221 }
222}
223
224struct Keycodes<'a>(&'a Keymap);
225
226impl Format for Keycodes<'_> {
227 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
228 let m = self.0;
229 f.write_nesting()?;
230 f.write("xkb_keycodes {")?;
231 f.write_nested(|f| {
232 f.write_nesting()?;
233 f.write("minimum = 8;")?;
234 f.write_newline()?;
235 f.write_nesting()?;
236 write!(f.f, "maximum = {};", m.max_keycode)?;
237 f.write_newline()?;
238 f.write_newline()?;
239 for i in &m.indicators {
240 KeycodeIndicator(i).format(f)?;
241 f.write_newline()?;
242 }
243 if m.keycodes.is_not_empty() {
244 f.write_newline()?;
245 KeycodeKeys(m).format(f)?;
246 }
247 Ok(())
248 })?;
249 f.write_nesting()?;
250 f.write("};")?;
251 Ok(())
252 }
253}
254
255struct Compat<'a>(&'a Keymap);
256
257impl Format for Compat<'_> {
258 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
259 let m = self.0;
260 f.write_nesting()?;
261 f.write("xkb_compat {")?;
262 f.write_nested(|f| {
263 let mut wrote_any_indicators = false;
264 for i in &m.indicators {
265 let write = i.modifier_mask.0 != 0
266 || i.group_mask.0 != 0
267 || i.group_component != GroupComponent::Effective
268 || i.controls != ControlMask::NONE;
269 if write {
270 wrote_any_indicators = true;
271 CompatIndicator(i).format(f)?;
272 f.write_newline()?;
273 }
274 }
275 if wrote_any_indicators {
276 f.write_newline()?;
277 }
278 f.write_nesting()?;
280 f.write("interpret VoidSymbol {")?;
281 f.write_nested(|f| {
282 f.write_nesting()?;
283 f.write("repeat = false;")?;
284 f.write_newline()
285 })?;
286 f.write_nesting()?;
287 f.write("};")?;
288 f.write_newline()?;
289 Ok(())
290 })?;
291 f.write_nesting()?;
292 f.write("};")?;
293 Ok(())
294 }
295}
296
297struct KeycodeIndicator<'a>(&'a Indicator);
298
299impl Format for KeycodeIndicator<'_> {
300 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
301 let i = self.0;
302 f.write_nesting()?;
303 if i.virt {
304 f.write("virtual ")?;
305 }
306 f.write("indicator ")?;
307 write!(f.f, "{}", i.index.raw())?;
308 f.write(" = ")?;
309 f.write_string(&i.name)?;
310 f.write(";")?;
311 Ok(())
312 }
313}
314
315struct CompatIndicator<'a>(&'a Indicator);
316
317impl Format for CompatIndicator<'_> {
318 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
319 let i = self.0;
320 f.write_nesting()?;
321 f.write("indicator ")?;
322 f.write_string(&i.name)?;
323 f.write(" {")?;
324 f.write_nested(|f| {
325 if i.modifier_mask.0 != 0 {
326 f.write_nesting()?;
327 write!(f.f, "modifiers = {};", modifier_mask(i.modifier_mask))?;
328 f.write_newline()?;
329 if i.mod_components != ModComponentMask::EFFECTIVE {
330 f.write_nesting()?;
331 write!(f.f, "whichModState = {};", i.mod_components)?;
332 f.write_newline()?;
333 }
334 }
335 if i.group_mask.0 != 0 {
336 f.write_nesting()?;
337 write!(f.f, "groups = 0x{:08x};", i.group_mask.0)?;
338 f.write_newline()?;
339 }
340 if i.group_component != GroupComponent::Effective {
341 f.write_nesting()?;
342 write!(f.f, "whichGroupState = {};", i.group_component)?;
343 f.write_newline()?;
344 }
345 if i.controls != ControlMask::NONE {
346 f.write_nesting()?;
347 write!(f.f, "controls = {};", i.controls)?;
348 f.write_newline()?;
349 }
350 Ok(())
351 })?;
352 f.write_nesting()?;
353 f.write("};")?;
354 Ok(())
355 }
356}
357
358struct KeycodeKeys<'a>(&'a Keymap);
359
360impl Format for KeycodeKeys<'_> {
361 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
362 for k in &self.0.keycodes {
363 f.write_nesting()?;
364 f.write("<")?;
365 f.write_key_name(&k.name)?;
366 write!(f.f, "> = {};", k.keycode.0)?;
367 f.write_newline()?;
368 }
369 Ok(())
370 }
371}
372
373struct Types<'a>(&'a Keymap);
374
375impl Format for Types<'_> {
376 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
377 let m = self.0;
378 f.write_nesting()?;
379 f.write("xkb_types {")?;
380 f.write_nested(|f| {
381 VirtualModifiers(m).format(f)?;
382 for i in &m.types {
383 f.write_newline()?;
384 TypesKeyType(i).format(f)?;
385 f.write_newline()?;
386 }
387 Ok(())
388 })?;
389 f.write_nesting()?;
390 f.write("};")?;
391 Ok(())
392 }
393}
394
395struct TypesKeyType<'a>(&'a KeyType);
396
397impl Format for TypesKeyType<'_> {
398 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
399 let m = self.0;
400 f.write_nesting()?;
401 f.write("type ")?;
402 f.write_string(&m.name)?;
403 f.write(" {")?;
404 f.write_nested(|f| {
405 f.write_nesting()?;
406 write!(f.f, "modifiers = {};", modifier_mask(m.modifiers))?;
407 f.write_newline()?;
408 for (l, n) in &m.level_names {
409 f.write_nesting()?;
410 write!(f.f, "level_name[Level{}] = ", l.raw())?;
411 f.write_string(n)?;
412 f.write(";")?;
413 f.write_newline()?;
414 }
415 for level in &m.mappings {
416 f.write_nesting()?;
417 let mask = modifier_mask(level.modifiers);
418 write!(f.f, "map[{}] = Level{};", mask, level.level.raw())?;
419 f.write_newline()?;
420 if level.preserved.0 != 0 {
421 f.write_nesting()?;
422 write!(
423 f.f,
424 "preserve[{}] = {};",
425 mask,
426 modifier_mask(level.preserved)
427 )?;
428 f.write_newline()?;
429 }
430 }
431 Ok(())
432 })?;
433 f.write_nesting()?;
434 f.write("};")?;
435 Ok(())
436 }
437}
438
439struct VirtualModifiers<'a>(&'a Keymap);
440
441impl Format for VirtualModifiers<'_> {
442 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
443 let m = self.0;
444 for v in &m.virtual_modifiers {
445 f.write_nesting()?;
446 f.write("virtual_modifiers ")?;
447 f.write(&v.name)?;
448 if v.values.0 != 0 {
449 f.write(" = ")?;
450 write!(f.f, "{}", modifier_mask(v.values))?;
451 }
452 f.write(";")?;
453 f.write_newline()?;
454 }
455 Ok(())
456 }
457}
458
459impl Format for Action {
460 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
461 match self {
462 Action::ModsSet(e) => e.format(f),
463 Action::ModsLatch(e) => e.format(f),
464 Action::ModsLock(e) => e.format(f),
465 Action::GroupSet(e) => e.format(f),
466 Action::GroupLatch(e) => e.format(f),
467 Action::GroupLock(e) => e.format(f),
468 Action::RedirectKey(e) => e.format(f),
469 Action::ControlsSet(e) => e.format(f),
470 Action::ControlsLock(e) => e.format(f),
471 }
472 }
473}
474
475impl Format for ModsSetAction {
476 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
477 f.write("SetMods(")?;
478 write!(f.f, "modifiers = {}", modifier_mask(self.modifiers))?;
479 if self.clear_locks {
480 f.write(", clearLocks")?;
481 }
482 f.write(")")?;
483 Ok(())
484 }
485}
486
487impl Format for ModsLatchAction {
488 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
489 f.write("LatchMods(")?;
490 write!(f.f, "modifiers = {}", modifier_mask(self.modifiers))?;
491 if self.clear_locks {
492 f.write(", clearLocks")?;
493 }
494 if self.latch_to_lock {
495 f.write(", latchToLock")?;
496 }
497 f.write(")")?;
498 Ok(())
499 }
500}
501
502impl Format for ModsLockAction {
503 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
504 write!(
505 f.f,
506 "LockMods(modifiers = {}{})",
507 modifier_mask(self.modifiers),
508 affect(self.lock, self.unlock),
509 )
510 }
511}
512
513impl Format for GroupSetAction {
514 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
515 f.write("SetGroup(")?;
516 write!(f.f, "group = {}", group_change(self.group))?;
517 if self.clear_locks {
518 f.write(", clearLocks")?;
519 }
520 f.write(")")?;
521 Ok(())
522 }
523}
524
525impl Format for GroupLatchAction {
526 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
527 f.write("LatchGroup(")?;
528 write!(f.f, "group = {}", group_change(self.group))?;
529 if self.clear_locks {
530 f.write(", clearLocks")?;
531 }
532 if self.latch_to_lock {
533 f.write(", latchToLock")?;
534 }
535 f.write(")")?;
536 Ok(())
537 }
538}
539
540impl Format for GroupLockAction {
541 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
542 f.write("LockGroup(")?;
543 write!(f.f, "group = {}", group_change(self.group))?;
544 f.write(")")?;
545 Ok(())
546 }
547}
548
549impl Format for RedirectKeyAction {
550 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
551 f.write("RedirectKey(")?;
552 f.write("key = <")?;
553 f.write_key_name(&self.key_name)?;
554 f.write(">")?;
555 if self.mods_to_clear.0 != 0 {
556 write!(f.f, ", clearMods = {}", modifier_mask(self.mods_to_clear))?;
557 }
558 if self.mods_to_set.0 != 0 {
559 write!(f.f, ", mods = {}", modifier_mask(self.mods_to_set))?;
560 }
561 f.write(")")?;
562 Ok(())
563 }
564}
565
566impl Format for ControlsSetAction {
567 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
568 write!(f.f, "SetControls(controls = {})", self.controls)?;
569 Ok(())
570 }
571}
572
573impl Format for ControlsLockAction {
574 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
575 write!(
576 f.f,
577 "LockControls(controls = {}{})",
578 self.controls,
579 affect(self.lock, self.unlock),
580 )
581 }
582}
583
584struct Symbols<'a>(&'a Keymap);
585
586impl Format for Symbols<'_> {
587 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
588 let m = self.0;
589 f.write_nesting()?;
590 f.write("xkb_symbols {")?;
591 f.write_nested(|f| {
592 let mut need_newline = false;
593 if m.mod_maps.is_not_empty() {
594 ModMaps(m).format(f)?;
595 need_newline = true;
596 }
597 if m.group_names.is_not_empty() {
598 if need_newline {
599 f.write_newline()?;
600 }
601 GroupNames(m).format(f)?;
602 need_newline = true;
603 }
604 if m.keys.len() > 0 {
605 if need_newline {
606 f.write_newline()?;
607 }
608 Keys(m).format(f)?;
609 }
610 Ok(())
611 })?;
612 f.write_nesting()?;
613 f.write("};")?;
614 Ok(())
615 }
616}
617
618struct Keys<'a>(&'a Keymap);
619
620impl Format for Keys<'_> {
621 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
622 let m = self.0;
623 f.write_nesting()?;
624 f.write("key.repeat = true;")?;
625 f.write_newline()?;
626 f.write_newline()?;
627 for key in m.keys.values() {
628 f.write_nesting()?;
629 f.write("key <")?;
630 f.write_key_name(&key.key_name)?;
631 f.write("> {")?;
632 f.write_nested(|f| {
633 let mut needs_newline = false;
634 fn handle_newline(needs_newline: &mut bool, f: &mut Writer<'_, '_>) -> fmt::Result {
635 if *needs_newline {
636 f.write(",")?;
637 f.write_newline()?;
638 }
639 *needs_newline = false;
640 Ok(())
641 }
642 if !key.repeat {
643 f.write_nesting()?;
644 f.write("repeat = false")?;
645 needs_newline = true;
646 }
647 if !f.lookup_only {
648 if let Some(behavior) = &key.behavior {
649 handle_newline(&mut needs_newline, f)?;
650 f.write_nesting()?;
651 match behavior {
652 KeyBehavior::Lock => {
653 f.write("locks = true")?;
654 }
655 KeyBehavior::Overlay(b) => {
656 let idx = match b.overlay() {
657 KeyOverlay::Overlay1 => 1,
658 KeyOverlay::Overlay2 => 2,
659 };
660 write!(f.f, "overlay{idx} = <")?;
661 f.write_key_name(&b.key_name)?;
662 f.write(">")?;
663 }
664 KeyBehavior::RadioGroup(g) => {
665 if g.allow_none {
666 write!(f.f, "allownone")?;
667 needs_newline = true;
668 handle_newline(&mut needs_newline, f)?;
669 f.write_nesting()?;
670 }
671 write!(f.f, "radiogroup = {}", g.radio_group.raw())?;
672 }
673 }
674 needs_newline = true;
675 }
676 }
677 if key.redirect != GroupsRedirect::Wrap {
678 handle_newline(&mut needs_newline, f)?;
679 f.write_nesting()?;
680 match key.redirect {
681 GroupsRedirect::Wrap => {}
682 GroupsRedirect::Clamp => {
683 f.write("groupsClamp = true")?;
684 }
685 GroupsRedirect::Redirect(n) => {
686 write!(f.f, "groupsRedirect = Group{}", n.raw())?;
687 }
688 }
689 needs_newline = true;
690 }
691 for (offset, group) in key.groups.iter().enumerate() {
692 if let Some(group) = group {
693 if group.levels.len() == 0 {
694 continue;
695 }
696 let idx = offset + 1;
697 handle_newline(&mut needs_newline, f)?;
698 f.write_nesting()?;
699 write!(f.f, "type[Group{idx}] = ")?;
700 f.write_string(&group.key_type.name)?;
701 needs_newline = true;
702 }
703 }
704 for (offset, group) in key.groups.iter().enumerate() {
705 if let Some(group) = group {
706 let idx = offset + 1;
707 #[expect(clippy::too_many_arguments)]
708 fn write_levels<T: Format>(
709 needs_newline: &mut bool,
710 idx: usize,
711 group: &KeyGroup,
712 f: &mut Writer<'_, '_>,
713 name: &str,
714 absent: &str,
715 field: impl Fn(&KeyLevel) -> &SmallVec<[T; 1]>,
716 is_actions: bool,
717 ) -> fmt::Result {
718 if group.levels.iter().all(|l| field(l).is_empty()) {
719 return Ok(());
720 }
721 handle_newline(needs_newline, f)?;
722 f.write_nesting()?;
723 write!(f.f, "{name}[Group{idx}] = [")?;
724 f.write_inline_list(&group.levels, |f, l| {
725 let mut list = &**field(l);
726 if is_actions && f.omit_multiple_actions && list.len() > 1 {
727 list = &[];
728 }
729 if list.is_empty() {
730 f.write(absent)?;
731 } else if list.len() == 1 {
732 list[0].format(f)?;
733 } else {
734 f.write("{")?;
735 f.write_inline_list(list, |f, a| a.format(f))?;
736 f.write(" }")?;
737 }
738 Ok(())
739 })?;
740 f.write(" ]")?;
741 *needs_newline = true;
742 Ok(())
743 }
744 write_levels(
745 &mut needs_newline,
746 idx,
747 group,
748 f,
749 "symbols",
750 "NoSymbol",
751 |l| &l.symbols,
752 false,
753 )?;
754 if !f.lookup_only {
755 write_levels(
756 &mut needs_newline,
757 idx,
758 group,
759 f,
760 "actions",
761 "NoAction()",
762 |l| &l.actions,
763 true,
764 )?;
765 }
766 }
767 }
768 if !needs_newline {
769 f.write_nesting()?;
770 f.write("repeat = true")?;
771 }
772 f.write_newline()?;
773 Ok(())
774 })?;
775 f.write_nesting()?;
776 f.write("};")?;
777 f.write_newline()?;
778 }
779 Ok(())
780 }
781}
782
783impl Format for Keysym {
784 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
785 Display::fmt(self, f.f)
786 }
787}
788
789struct ModMaps<'a>(&'a Keymap);
790
791impl Format for ModMaps<'_> {
792 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
793 for (idx, kc) in &self.0.mod_maps {
794 f.write_nesting()?;
795 write!(f.f, "modmap {} {{ ", modifier_mask(idx.to_mask()))?;
796 if let Some(s) = kc.key_sym {
797 s.format(f)?;
798 } else {
799 f.write("<")?;
800 f.write_key_name(&kc.key_name)?;
801 f.write(">")?;
802 }
803 f.write(" };")?;
804 if kc.key_sym.is_some() && f.multi_line {
805 write!(f.f, " // <{}>", kc.key_name)?;
806 }
807 f.write_newline()?;
808 }
809 Ok(())
810 }
811}
812
813struct GroupNames<'a>(&'a Keymap);
814
815impl Format for GroupNames<'_> {
816 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
817 for (idx, kc) in &self.0.group_names {
818 f.write_nesting()?;
819 write!(f.f, "name[Group{}] = ", idx.raw())?;
820 f.write_string(kc)?;
821 f.write(";")?;
822 f.write_newline()?;
823 }
824 Ok(())
825 }
826}
827
828fn group_change(gc: GroupChange) -> impl Display {
829 debug_fn(move |f| match gc {
830 GroupChange::Absolute(g) => {
831 write!(f, "Group{}", g.raw())
832 }
833 GroupChange::Rel(r) => {
834 if r > 0 {
835 f.write_str("+")?;
836 }
837 Display::fmt(&r, f)
838 }
839 })
840}
841
842fn affect(lock: bool, unlock: bool) -> impl Display {
843 debug_fn(move |f| {
844 let affect = match (lock, unlock) {
845 (false, false) => "neither",
846 (true, false) => "lock",
847 (false, true) => "unlock",
848 _ => return Ok(()),
849 };
850 write!(f, ", affect={}", affect)
851 })
852}
853
854fn modifier_mask(mm: ModifierMask) -> impl Display {
855 debug_fn(move |f| {
856 if mm.0 == 0 {
857 f.write_str("None")
858 } else if mm.0 & !0xff != 0 {
859 write!(f, "0x{:08x}", mm.0)
860 } else {
861 let mut first = true;
862 macro_rules! one {
863 ($n:expr, $name:expr) => {
864 if mm.0 & (1 << $n) != 0 {
865 if !first {
866 f.write_str("+")?;
867 }
868 first = false;
869 f.write_str($name)?;
870 }
871 };
872 }
873 one!(0, "Shift");
874 one!(1, "Lock");
875 one!(2, "Control");
876 one!(3, "Mod1");
877 one!(4, "Mod2");
878 one!(5, "Mod3");
879 one!(6, "Mod4");
880 one!(7, "Mod5");
881 let _ = first;
882 Ok(())
883 }
884 })
885}
886
887impl Format for rmlvo::Expanded {
888 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
889 f.write_nesting()?;
890 f.write("xkb_keymap {")?;
891 f.write_nested(|f| {
892 let elements = [
893 ("xkb_keycodes", &self.keycodes),
894 ("xkb_types", &self.types),
895 ("xkb_compat", &self.compat),
896 ("xkb_symbols", &self.symbols),
897 ("xkb_geometry", &self.geometry),
898 ];
899 for (name, elements) in elements {
900 f.write_nesting()?;
901 f.write(name)?;
902 f.write(" {")?;
903 f.write_nested(|f| RmlvoIncludes(elements).format(f))?;
904 f.write_nesting()?;
905 f.write("};")?;
906 f.write_newline()?;
907 }
908 Ok(())
909 })?;
910 f.write_nesting()?;
911 f.write("};")?;
912 Ok(())
913 }
914}
915
916struct RmlvoIncludes<'a>(&'a [rmlvo::Element]);
917
918impl Format for RmlvoIncludes<'_> {
919 fn format(&self, f: &mut Writer<'_, '_>) -> fmt::Result {
920 for e in self.0 {
921 f.write_nesting()?;
922 match e.merge_mode {
923 MergeMode::Augment => f.write("augment ")?,
924 MergeMode::Override => f.write("override ")?,
925 MergeMode::Replace => f.write("replace ")?,
926 }
927 f.write_string(&e.include)?;
928 f.write_newline()?;
929 }
930 Ok(())
931 }
932}
933
934#[cfg(feature = "compose")]
935mod compose {
936 use crate::xkb::{
937 compose::{ComposeTable, MatchRule, MatchStep},
938 format::{Format, Writer},
939 };
940
941 impl Format for MatchStep<'_> {
942 fn format(&self, f: &mut Writer<'_, '_>) -> std::fmt::Result {
943 f.write("<")?;
944 self.node.keysym.format(f)?;
945 f.write(">")?;
946 Ok(())
947 }
948 }
949
950 impl Format for MatchRule<'_, '_> {
951 fn format(&self, f: &mut Writer<'_, '_>) -> std::fmt::Result {
952 for (idx, step) in self.steps.iter().enumerate() {
953 if idx > 0 {
954 f.write(" ")?;
955 }
956 step.format(f)?;
957 }
958 f.write(":")?;
959 if let Some(s) = &self.payload.string {
960 f.write(" ")?;
961 f.write_string(s)?;
962 }
963 if let Some(s) = self.payload.keysym {
964 f.write(" ")?;
965 s.format(f)?;
966 }
967 Ok(())
968 }
969 }
970
971 impl Format for ComposeTable {
972 fn format(&self, f: &mut Writer<'_, '_>) -> std::fmt::Result {
973 let mut iter = self.iter();
974 let mut first = true;
975 while let Some(rule) = iter.next() {
976 if !first {
977 f.write("\n")?;
978 }
979 first = false;
980 rule.format(f)?;
981 }
982 Ok(())
983 }
984 }
985}