Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | n/a |
0 / 0 |
|
76.92% |
10 / 13 |
CRAP | |
70.77% |
46 / 65 |
|
Aviat\Kilo\ctrl_key | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
Aviat\Kilo\is_ascii | |
100.00% |
1 / 1 |
2 | |
100.00% |
3 / 3 |
|||
Aviat\Kilo\is_ctrl | |
100.00% |
1 / 1 |
3 | |
100.00% |
2 / 2 |
|||
Aviat\Kilo\is_digit | |
100.00% |
1 / 1 |
3 | |
100.00% |
2 / 2 |
|||
Aviat\Kilo\is_space | |
100.00% |
1 / 1 |
1 | |
100.00% |
7 / 7 |
|||
Aviat\Kilo\is_separator | |
100.00% |
1 / 1 |
4 | |
100.00% |
4 / 4 |
|||
Aviat\Kilo\array_replace_range | |
100.00% |
1 / 1 |
2 | |
100.00% |
5 / 5 |
|||
Aviat\Kilo\str_has | |
100.00% |
1 / 1 |
3 | |
100.00% |
5 / 5 |
|||
Aviat\Kilo\syntax_to_color | |
100.00% |
1 / 1 |
1 | |
100.00% |
14 / 14 |
|||
Aviat\Kilo\tabs_to_spaces | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
Aviat\Kilo\error_code_name | |
0.00% |
0 / 1 |
2 | |
0.00% |
0 / 15 |
|||
Aviat\Kilo\saturating_add | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 1 |
|||
Aviat\Kilo\saturating_sub | |
0.00% |
0 / 1 |
6 | |
0.00% |
0 / 3 |
1 | <?php declare(strict_types=1); |
2 | |
3 | namespace Aviat\Kilo; |
4 | |
5 | use Aviat\Kilo\Enum\{Color, Highlight, RawKeyCode}; |
6 | |
7 | // ---------------------------------------------------------------------------- |
8 | // ! C function/macro equivalents |
9 | // ---------------------------------------------------------------------------- |
10 | |
11 | /** |
12 | * Do bit twiddling to convert a letter into |
13 | * its Ctrl-letter equivalent ordinal ascii value |
14 | * |
15 | * @param string $char |
16 | * @return int |
17 | */ |
18 | function ctrl_key(string $char): int |
19 | { |
20 | if ( ! is_ascii($char)) |
21 | { |
22 | return -1; |
23 | } |
24 | |
25 | // b1,100,001 (a) & b0,011,111 (0x1f) = b0,000,001 (SOH) |
26 | // b1,100,010 (b) & b0,011,111 (0x1f) = b0,000,010 (STX) |
27 | // ...and so on |
28 | return ord($char) & 0x1f; |
29 | } |
30 | |
31 | /** |
32 | * Does the one-character string contain an ascii ordinal value? |
33 | * |
34 | * @param string $single_char |
35 | * @return bool |
36 | */ |
37 | function is_ascii(string $single_char): bool |
38 | { |
39 | if (strlen($single_char) > 1) |
40 | { |
41 | return FALSE; |
42 | } |
43 | |
44 | return ord($single_char) < 0x80; |
45 | } |
46 | |
47 | /** |
48 | * Does the one-character string contain an ascii control character? |
49 | * |
50 | * @param string $char |
51 | * @return bool |
52 | */ |
53 | function is_ctrl(string $char): bool |
54 | { |
55 | $c = ord($char); |
56 | return is_ascii($char) && ( $c === 0x7f || $c < 0x20 ); |
57 | } |
58 | |
59 | /** |
60 | * Does the one-character string contain an ascii number? |
61 | * |
62 | * @param string $char |
63 | * @return bool |
64 | */ |
65 | function is_digit(string $char): bool |
66 | { |
67 | $c = ord($char); |
68 | return is_ascii($char) && ( $c > 0x2f && $c < 0x3a ); |
69 | } |
70 | |
71 | /** |
72 | * Does the one-character string contain ascii whitespace? |
73 | * |
74 | * @param string $char |
75 | * @return bool |
76 | */ |
77 | function is_space(string $char): bool |
78 | { |
79 | return match($char) { |
80 | RawKeyCode::CARRIAGE_RETURN, |
81 | RawKeyCode::FORM_FEED, |
82 | RawKeyCode::NEWLINE, |
83 | RawKeyCode::SPACE, |
84 | RawKeyCode::TAB, |
85 | RawKeyCode::VERTICAL_TAB => true, |
86 | |
87 | default => false, |
88 | }; |
89 | } |
90 | |
91 | // ---------------------------------------------------------------------------- |
92 | // ! Helper functions |
93 | // ---------------------------------------------------------------------------- |
94 | |
95 | /** |
96 | * Does the one-character string contain a character that separates tokens? |
97 | * |
98 | * @param string $char |
99 | * @return bool |
100 | */ |
101 | function is_separator(string $char): bool |
102 | { |
103 | if ( ! is_ascii($char)) |
104 | { |
105 | return FALSE; |
106 | } |
107 | |
108 | $isSep = str_contains(',.()+-/*=~%<>[];', $char); |
109 | |
110 | return is_space($char) || $char === RawKeyCode::NULL || $isSep; |
111 | } |
112 | |
113 | /** |
114 | * Replaces a slice of an array with the same value |
115 | * |
116 | * @param array $array The array to update |
117 | * @param int $offset The index of the first location to update |
118 | * @param int $length The number of indices to update |
119 | * @param mixed $value The value to replace in the range |
120 | */ |
121 | function array_replace_range(array &$array, int $offset, int $length, mixed $value):void |
122 | { |
123 | if ($length === 1) |
124 | { |
125 | $array[$offset] = $value; |
126 | return; |
127 | } |
128 | |
129 | $replacement = array_fill(0, $length, $value); |
130 | array_splice($array, $offset, $length, $replacement); |
131 | } |
132 | |
133 | /** |
134 | * Does the string $haystack contain $str, optionally searching from $offset? |
135 | * |
136 | * @param string $haystack |
137 | * @param string $str |
138 | * @param int|null $offset |
139 | * @return bool |
140 | */ |
141 | function str_has(string $haystack, string $str, ?int $offset = NULL): bool |
142 | { |
143 | if (empty($str)) |
144 | { |
145 | return FALSE; |
146 | } |
147 | |
148 | return ($offset !== NULL) |
149 | ? strpos($haystack, $str, $offset) !== FALSE |
150 | : \str_contains($haystack, $str); |
151 | } |
152 | |
153 | /** |
154 | * Get the ASCII color escape number for the specified syntax type |
155 | * |
156 | * @param int $hl |
157 | * @return int |
158 | */ |
159 | function syntax_to_color(int $hl): int |
160 | { |
161 | return match ($hl) |
162 | { |
163 | Highlight::COMMENT => Color::FG_CYAN, |
164 | Highlight::ML_COMMENT => Color::FG_BRIGHT_BLACK, |
165 | Highlight::KEYWORD1 => Color::FG_YELLOW, |
166 | Highlight::KEYWORD2 => Color::FG_GREEN, |
167 | Highlight::STRING => Color::FG_MAGENTA, |
168 | Highlight::CHARACTER => Color::FG_BRIGHT_MAGENTA, |
169 | Highlight::NUMBER => Color::FG_BRIGHT_RED, |
170 | Highlight::OPERATOR => Color::FG_BRIGHT_GREEN, |
171 | Highlight::VARIABLE => Color::FG_BRIGHT_CYAN, |
172 | Highlight::DELIMITER => Color::FG_BLUE, |
173 | Highlight::INVALID => Color::BG_BRIGHT_RED, |
174 | Highlight::MATCH => Color::INVERT, |
175 | Highlight::IDENTIFIER => Color::FG_BRIGHT_WHITE, |
176 | default => Color::FG_WHITE, |
177 | }; |
178 | } |
179 | |
180 | /** |
181 | * Replace tabs with the specified number of spaces. |
182 | * |
183 | * @param string $str |
184 | * @param int $number |
185 | * @return string |
186 | */ |
187 | function tabs_to_spaces(string $str, int $number = KILO_TAB_STOP): string |
188 | { |
189 | return str_replace(RawKeyCode::TAB, str_repeat(RawKeyCode::SPACE, $number), $str); |
190 | } |
191 | |
192 | function error_code_name(int $code): string |
193 | { |
194 | return match ($code) { |
195 | E_ERROR => 'Error', |
196 | E_WARNING => 'Warning', |
197 | E_PARSE => 'Parse Error', |
198 | E_NOTICE => 'Notice', |
199 | E_CORE_ERROR => 'Core Error', |
200 | E_CORE_WARNING => 'Core Warning', |
201 | E_COMPILE_ERROR => 'Compile Error', |
202 | E_COMPILE_WARNING => 'Compile Warning', |
203 | E_USER_ERROR => 'User Error', |
204 | E_USER_WARNING => 'User Warning', |
205 | E_USER_NOTICE => 'User Notice', |
206 | E_RECOVERABLE_ERROR => 'Recoverable Error', |
207 | E_DEPRECATED => 'Deprecated', |
208 | E_USER_DEPRECATED => 'User Deprecated', |
209 | default => 'Unknown', |
210 | }; |
211 | } |
212 | |
213 | function saturating_add(int $a, int $b, int $max): int |
214 | { |
215 | return ($a + $b > $max) ? $max : $a + $b; |
216 | } |
217 | |
218 | function saturating_sub(int $a, int $b): int |
219 | { |
220 | if ($b > $a) |
221 | { |
222 | return 0; |
223 | } |
224 | |
225 | return $a - $b; |
226 | } |