Forge
csharpdeeb25a2
1using Avalonia.Input;
2using CascadeIDE.Contracts;
3
4namespace CascadeIDE.Features.Shell.Application;
5
6/// <summary>Соответствие клавиш главного окна символам мелодии CascadeChord.</summary>
7[PresentationProjection("cascade-chord-melody-keys")]
8public static class CascadeChordMelodyKeyMap
9{
10 /// <summary>
11 /// Строчные латиница/цифры и символы для параметрических хвостов (<c>:</c>, <c>/</c>, <c>.</c>, <c>-</c>).
12 /// Буквы — по <see cref="Key"/> (как в ADR 0060 зеркало HUD); «:» и пробел дополняются
13 /// <see cref="PhysicalKey"/>, чтобы раскладка не ломала <c>:</c> (например RU: Shift+физ. 6).
14 /// </summary>
15 public static bool TryMapChordMelodyGlyph(Key key, KeyModifiers modifiers, PhysicalKey physicalKey, out char ch)
16 {
17 ch = default;
18 var shift = modifiers.HasFlag(KeyModifiers.Shift);
19 // В chord-последовательностях Ctrl часто продолжают держать (в стиле VSCode: Ctrl+K затем /).
20 // Поэтому Ctrl здесь игнорируем; а вот Alt/Meta ломают ввод и считаются "не мелодией".
21 if (modifiers.HasFlag(KeyModifiers.Alt) || modifiers.HasFlag(KeyModifiers.Meta))
22 return false;
23
24 if (key == Key.Space)
25 {
26 ch = ' ';
27 return true;
28 }
29
30 // Физ. клавиша «;» (US справа от L): без Shift — «;» в хвост (разделитель в int_chain, см. TOML); со Shift — «:».
31 // Так аккорд обходит глючный Shift у Avalonia для «:».
32 if (physicalKey == PhysicalKey.Semicolon)
33 {
34 ch = shift ? ':' : ';';
35 return true;
36 }
37
38 // «:» — RU и др.: часто Shift+физ. цифра 6 (на US той же клавише — ^; в хвосте мелодии нужен ':').
39 if (physicalKey == PhysicalKey.Digit6 && shift)
40 {
41 ch = ':';
42 return true;
43 }
44
45 if (TryMapToChar(key, out ch))
46 return true;
47
48 return key switch
49 {
50 // Windows US часто даёт VK_OEM_1 как Key.Oem1; «;» / «:» — те же позиции, что и PhysicalKey.Semicolon.
51
52 Key.OemSemicolon when shift =>
53 WithChar(':', out ch),
54 Key.OemSemicolon when !shift =>
55 WithChar(';', out ch),
56 Key.Oem1 when shift =>
57 WithChar(':', out ch),
58 Key.Oem1 when !shift =>
59 WithChar(';', out ch),
60 Key.OemPeriod when !shift =>
61 WithChar('.', out ch),
62
63 Key.Oem2 or Key.Divide =>
64 WithChar('/', out ch),
65 Key.OemMinus or Key.Subtract =>
66 shift ? WithChar('_', out ch) : WithChar('-', out ch),
67 Key.OemPlus or Key.Add =>
68 shift ? WithChar('+', out ch) : WithChar('=', out ch),
69 _ => false,
70 };
71
72 static bool WithChar(char c, out char o)
73 {
74 o = c;
75 return true;
76 }
77 }
78
79 public static bool TryMapToChar(Key key, out char ch)
80 {
81 ch = default;
82 if (key >= Key.A && key <= Key.Z)
83 {
84 ch = (char)('a' + (key - Key.A));
85 return true;
86 }
87
88 if (key >= Key.D0 && key <= Key.D9)
89 {
90 ch = (char)('0' + (key - Key.D0));
91 return true;
92 }
93
94 if (key >= Key.NumPad0 && key <= Key.NumPad9)
95 {
96 ch = (char)('0' + (key - Key.NumPad0));
97 return true;
98 }
99
100 return false;
101 }
102}
103
View only · write via MCP/CIDE