1 module scone.input.os.posix.locale.input_map;
2 
3 version (Posix)
4 {
5     import scone.input.keyboard_event : KeyboardEvent;
6     import scone.input.scone_control_key : SCK;
7     import scone.input.scone_key : SK;
8     import scone.input.os.posix.keyboard_event_tree : KeyboardEventTree;
9     import std.experimental.logger : sharedLog;
10 
11     /**
12      * Wrapper for an input sequence sent by the POSIX terminal.
13      *
14      * An input from the terminal is given by numbers in a sequence.
15      *
16      * For example, the right arrow key might send the sequence "27 91 67",
17      * and will be stored as [27, 91, 67]
18      */
19     alias InputSequence = uint[];
20 
21     class InputMap
22     {
23         this(string tsv)
24         {
25             this.keypressTree = new KeyboardEventTree();
26             loadKeyboardEventTree(this.keypressTree, tsv);
27         }
28 
29         KeyboardEvent[] keyboardEventsFromSequence(uint[] sequence)
30         {
31             return this.keypressTree.find(sequence);
32         }
33 
34         private void loadKeyboardEventTree(KeyboardEventTree tree, string tsv)
35         {
36             import std.file : exists, readText;
37             import std..string : chomp;
38             import std.array : split;
39             import std.conv : parse;
40 
41             string[] ies = tsv.split('\n');
42 
43             // Loop all input sequences, and store them
44             foreach (s; ies)
45             {
46                 s = s.chomp;
47                 // if line is empty or begins with #
48                 if (s == "" || s[0] == '#')
49                 {
50                     continue;
51                 }
52 
53                 string[] arguments = split(s, '\t');
54                 if (arguments.length != 3)
55                 {
56                     sharedLog.warning("Reading input sequences CSV found %i arguments, exprected 3", arguments
57                             .length);
58 
59                     continue;
60                 }
61 
62                 auto key = parse!(SK)(arguments[0]);
63                 auto controlKey = parse!(SCK)(arguments[1]);
64                 auto seq = arguments[2];
65 
66                 if (seq == "-")
67                 {
68                     continue;
69                 }
70 
71                 bool inserted = tree.insert(sequenceFromString(seq), KeyboardEvent(key, controlKey));
72                 if (!inserted)
73                 {
74                     sharedLog.error("Could not map sequence ", seq, " to keypress ", key, "+", controlKey);
75                 }
76             }
77         }
78 
79         /// get uint[], from string in the format of "num1,num2,...,numX"
80         private uint[] sequenceFromString(string input) pure
81         {
82             import std.array : split;
83             import std.conv : parse;
84 
85             string[] numbers = split(input, ",");
86             uint[] sequence;
87             foreach (number_as_string; numbers)
88             {
89                 sequence ~= parse!uint(number_as_string);
90             }
91 
92             return sequence;
93         }
94 
95         private KeyboardEventTree keypressTree;
96     }
97 }