diff options
| author | M1K <michael@m1k.me> | 2018-05-01 18:39:46 +0100 |
|---|---|---|
| committer | Jack Humbert <jack.humb@gmail.com> | 2018-05-01 13:39:46 -0400 |
| commit | 5112af887ae59c9c54eabaec5c1ae2f5a53de180 (patch) | |
| tree | b5ec0dfbc99af7eb3890e9e661aca7d57836fa89 | |
| parent | f756b72167a573640d2427920603fa369c7949ae (diff) | |
| download | qmk_firmware-5112af887ae59c9c54eabaec5c1ae2f5a53de180.tar.gz qmk_firmware-5112af887ae59c9c54eabaec5c1ae2f5a53de180.zip | |
Added command history to terminal with other bug fixes, added new song to song_list.h (#2855)
* Implemented Terminal + added song to song_list.h
* Added wait() in order to prevent misbehaviour of 'command not found'
| -rw-r--r-- | docs/feature_terminal.md | 31 | ||||
| -rw-r--r-- | quantum/audio/song_list.h | 6 | ||||
| -rw-r--r-- | quantum/process_keycode/process_terminal.c | 125 |
3 files changed, 146 insertions, 16 deletions
diff --git a/docs/feature_terminal.md b/docs/feature_terminal.md index 334a46c2d..1863599f8 100644 --- a/docs/feature_terminal.md +++ b/docs/feature_terminal.md | |||
| @@ -14,12 +14,14 @@ When enabled, a `> ` prompt will appear, where you'll be able to type, backspace | |||
| 14 | 14 | ||
| 15 | `#define TERMINAL_HELP` enables some other output helpers that aren't really needed with this page. | 15 | `#define TERMINAL_HELP` enables some other output helpers that aren't really needed with this page. |
| 16 | 16 | ||
| 17 | Pressing "up" and "down" will allow you to cycle through the past 5 commands entered. | ||
| 18 | |||
| 17 | ## Future Ideas | 19 | ## Future Ideas |
| 18 | 20 | ||
| 19 | * Keyboard/user-extensible commands | 21 | * Keyboard/user-extensible commands |
| 20 | * Smaller footprint | 22 | * Smaller footprint |
| 21 | * Arrow key support | 23 | * Arrow key support |
| 22 | * Command history | 24 | * Command history - Done |
| 23 | * SD card support | 25 | * SD card support |
| 24 | * LCD support for buffer display | 26 | * LCD support for buffer display |
| 25 | * Keycode -> name string LUT | 27 | * Keycode -> name string LUT |
| @@ -43,14 +45,39 @@ QMK Firmware | |||
| 43 | Built: 2017-08-29-20:24:44 | 45 | Built: 2017-08-29-20:24:44 |
| 44 | ``` | 46 | ``` |
| 45 | 47 | ||
| 48 | |||
| 49 | ### `print-buffer` | ||
| 50 | |||
| 51 | Outputs the last 5 commands entered | ||
| 52 | |||
| 53 | ``` | ||
| 54 | > print-buffer | ||
| 55 | 0. print-buffer | ||
| 56 | 1. help | ||
| 57 | 2. about | ||
| 58 | 3. keymap 0 | ||
| 59 | 4. help | ||
| 60 | 5. flush-buffer | ||
| 61 | ``` | ||
| 62 | |||
| 63 | ### `flush-buffer` | ||
| 64 | |||
| 65 | Clears command buffer | ||
| 66 | ``` | ||
| 67 | > flush-buffer | ||
| 68 | Buffer cleared! | ||
| 69 | ``` | ||
| 70 | |||
| 71 | |||
| 46 | ### `help` | 72 | ### `help` |
| 47 | 73 | ||
| 74 | |||
| 48 | Prints out the available commands: | 75 | Prints out the available commands: |
| 49 | 76 | ||
| 50 | ``` | 77 | ``` |
| 51 | > help | 78 | > help |
| 52 | commands available: | 79 | commands available: |
| 53 | about help keycode keymap exit | 80 | about help keycode keymap exit print-buffer flush-buffer |
| 54 | ``` | 81 | ``` |
| 55 | 82 | ||
| 56 | ### `keycode <layer> <row> <col>` | 83 | ### `keycode <layer> <row> <col>` |
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h index a66c4d864..1ddcfb345 100644 --- a/quantum/audio/song_list.h +++ b/quantum/audio/song_list.h | |||
| @@ -20,6 +20,12 @@ | |||
| 20 | 20 | ||
| 21 | #define NO_SOUND | 21 | #define NO_SOUND |
| 22 | 22 | ||
| 23 | #define LP_NUMB \ | ||
| 24 | H__NOTE(_CS5), H__NOTE(_E5), H__NOTE(_CS5), WD_NOTE(_FS5), \ | ||
| 25 | WD_NOTE(_A5), WD_NOTE(_GS5), WD_NOTE(_REST), H__NOTE(_CS5), H__NOTE(_E5), \ | ||
| 26 | H__NOTE(_CS5), WD_NOTE(_A5), WD_NOTE(_GS5), WD_NOTE(_E5), | ||
| 27 | |||
| 28 | |||
| 23 | #define ODE_TO_JOY \ | 29 | #define ODE_TO_JOY \ |
| 24 | Q__NOTE(_E4), Q__NOTE(_E4), Q__NOTE(_F4), Q__NOTE(_G4), \ | 30 | Q__NOTE(_E4), Q__NOTE(_E4), Q__NOTE(_F4), Q__NOTE(_G4), \ |
| 25 | Q__NOTE(_G4), Q__NOTE(_F4), Q__NOTE(_E4), Q__NOTE(_D4), \ | 31 | Q__NOTE(_G4), Q__NOTE(_F4), Q__NOTE(_E4), Q__NOTE(_D4), \ |
diff --git a/quantum/process_keycode/process_terminal.c b/quantum/process_keycode/process_terminal.c index deb1543e3..bc365dddf 100644 --- a/quantum/process_keycode/process_terminal.c +++ b/quantum/process_keycode/process_terminal.c | |||
| @@ -20,10 +20,20 @@ | |||
| 20 | #include <stdio.h> | 20 | #include <stdio.h> |
| 21 | #include <math.h> | 21 | #include <math.h> |
| 22 | 22 | ||
| 23 | #ifndef CMD_BUFF_SIZE | ||
| 24 | #define CMD_BUFF_SIZE 5 | ||
| 25 | #endif | ||
| 26 | |||
| 27 | |||
| 23 | bool terminal_enabled = false; | 28 | bool terminal_enabled = false; |
| 24 | char buffer[80] = ""; | 29 | char buffer[80] = ""; |
| 30 | char cmd_buffer[CMD_BUFF_SIZE][80]; | ||
| 31 | bool cmd_buffer_enabled = true; //replace with ifdef? | ||
| 25 | char newline[2] = "\n"; | 32 | char newline[2] = "\n"; |
| 26 | char arguments[6][20]; | 33 | char arguments[6][20]; |
| 34 | bool firstTime = true; | ||
| 35 | |||
| 36 | short int current_cmd_buffer_pos = 0; //used for up/down arrows - keeps track of where you are in the command buffer | ||
| 27 | 37 | ||
| 28 | __attribute__ ((weak)) | 38 | __attribute__ ((weak)) |
| 29 | const char terminal_prompt[8] = "> "; | 39 | const char terminal_prompt[8] = "> "; |
| @@ -34,36 +44,37 @@ const char terminal_prompt[8] = "> "; | |||
| 34 | #endif | 44 | #endif |
| 35 | float terminal_song[][2] = TERMINAL_SONG; | 45 | float terminal_song[][2] = TERMINAL_SONG; |
| 36 | #define TERMINAL_BELL() PLAY_SONG(terminal_song) | 46 | #define TERMINAL_BELL() PLAY_SONG(terminal_song) |
| 37 | #else | 47 | #else |
| 38 | #define TERMINAL_BELL() | 48 | #define TERMINAL_BELL() |
| 39 | #endif | 49 | #endif |
| 40 | 50 | ||
| 41 | __attribute__ ((weak)) | 51 | __attribute__ ((weak)) |
| 42 | const char keycode_to_ascii_lut[58] = { | 52 | const char keycode_to_ascii_lut[58] = { |
| 43 | 0, 0, 0, 0, | 53 | 0, 0, 0, 0, |
| 44 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', | 54 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', |
| 45 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', | 55 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', |
| 46 | '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, '\t', | 56 | '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0, 0, 0, '\t', |
| 47 | ' ', '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',', '.', '/' | 57 | ' ', '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',', '.', '/' |
| 48 | }; | 58 | }; |
| 49 | 59 | ||
| 50 | __attribute__ ((weak)) | 60 | __attribute__ ((weak)) |
| 51 | const char shifted_keycode_to_ascii_lut[58] = { | 61 | const char shifted_keycode_to_ascii_lut[58] = { |
| 52 | 0, 0, 0, 0, | 62 | 0, 0, 0, 0, |
| 53 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', | 63 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', |
| 54 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', | 64 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
| 55 | '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 0, 0, 0, '\t', | 65 | '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', 0, 0, 0, '\t', |
| 56 | ' ', '_', '+', '{', '}', '|', 0, ':', '\'', '~', '<', '>', '?' | 66 | ' ', '_', '+', '{', '}', '|', 0, ':', '\'', '~', '<', '>', '?' |
| 57 | }; | 67 | }; |
| 58 | 68 | ||
| 59 | struct stringcase { | 69 | struct stringcase { |
| 60 | char* string; | 70 | char* string; |
| 61 | void (*func)(void); | 71 | void (*func)(void); |
| 62 | } typedef stringcase; | 72 | } typedef stringcase; |
| 63 | 73 | ||
| 64 | void enable_terminal(void) { | 74 | void enable_terminal(void) { |
| 65 | terminal_enabled = true; | 75 | terminal_enabled = true; |
| 66 | strcpy(buffer, ""); | 76 | strcpy(buffer, ""); |
| 77 | memset(cmd_buffer,0,CMD_BUFF_SIZE * 80); | ||
| 67 | for (int i = 0; i < 6; i++) | 78 | for (int i = 0; i < 6; i++) |
| 68 | strcpy(arguments[i], ""); | 79 | strcpy(arguments[i], ""); |
| 69 | // select all text to start over | 80 | // select all text to start over |
| @@ -73,6 +84,29 @@ void enable_terminal(void) { | |||
| 73 | 84 | ||
| 74 | void disable_terminal(void) { | 85 | void disable_terminal(void) { |
| 75 | terminal_enabled = false; | 86 | terminal_enabled = false; |
| 87 | SEND_STRING("\n"); | ||
| 88 | } | ||
| 89 | |||
| 90 | void push_to_cmd_buffer(void) { | ||
| 91 | if (cmd_buffer_enabled) { | ||
| 92 | if (cmd_buffer == NULL) { | ||
| 93 | return; | ||
| 94 | } else { | ||
| 95 | if (firstTime) { | ||
| 96 | firstTime = false; | ||
| 97 | strcpy(cmd_buffer[0],buffer); | ||
| 98 | return; | ||
| 99 | } | ||
| 100 | |||
| 101 | for (int i= CMD_BUFF_SIZE - 1;i > 0 ;--i) { | ||
| 102 | strncpy(cmd_buffer[i],cmd_buffer[i-1],80); | ||
| 103 | } | ||
| 104 | |||
| 105 | strcpy(cmd_buffer[0],buffer); | ||
| 106 | |||
| 107 | return; | ||
| 108 | } | ||
| 109 | } | ||
| 76 | } | 110 | } |
| 77 | 111 | ||
| 78 | void terminal_about(void) { | 112 | void terminal_about(void) { |
| @@ -136,11 +170,34 @@ void terminal_keymap(void) { | |||
| 136 | } | 170 | } |
| 137 | } | 171 | } |
| 138 | 172 | ||
| 139 | stringcase terminal_cases[] = { | 173 | void print_cmd_buff(void) { |
| 174 | /* without the below wait, a race condition can occur wherein the | ||
| 175 | buffer can be printed before it has been fully moved */ | ||
| 176 | wait_ms(250); | ||
| 177 | for(int i=0;i<CMD_BUFF_SIZE;i++){ | ||
| 178 | char tmpChar = ' '; | ||
| 179 | itoa(i ,&tmpChar,10); | ||
| 180 | const char * tmpCnstCharStr = &tmpChar; //because sned_string wont take a normal char * | ||
| 181 | send_string(tmpCnstCharStr); | ||
| 182 | SEND_STRING(". "); | ||
| 183 | send_string(cmd_buffer[i]); | ||
| 184 | SEND_STRING("\n"); | ||
| 185 | } | ||
| 186 | } | ||
| 187 | |||
| 188 | |||
| 189 | void flush_cmd_buffer(void) { | ||
| 190 | memset(cmd_buffer,0,CMD_BUFF_SIZE * 80); | ||
| 191 | SEND_STRING("Buffer Cleared!\n"); | ||
| 192 | } | ||
| 193 | |||
| 194 | stringcase terminal_cases[] = { | ||
| 140 | { "about", terminal_about }, | 195 | { "about", terminal_about }, |
| 141 | { "help", terminal_help }, | 196 | { "help", terminal_help }, |
| 142 | { "keycode", terminal_keycode }, | 197 | { "keycode", terminal_keycode }, |
| 143 | { "keymap", terminal_keymap }, | 198 | { "keymap", terminal_keymap }, |
| 199 | { "flush-buffer" , flush_cmd_buffer}, | ||
| 200 | { "print-buffer" , print_cmd_buff}, | ||
| 144 | { "exit", disable_terminal } | 201 | { "exit", disable_terminal } |
| 145 | }; | 202 | }; |
| 146 | 203 | ||
| @@ -154,6 +211,7 @@ void terminal_help(void) { | |||
| 154 | } | 211 | } |
| 155 | 212 | ||
| 156 | void command_not_found(void) { | 213 | void command_not_found(void) { |
| 214 | wait_ms(50); //sometimes buffer isnt grabbed quick enough | ||
| 157 | SEND_STRING("command \""); | 215 | SEND_STRING("command \""); |
| 158 | send_string(buffer); | 216 | send_string(buffer); |
| 159 | SEND_STRING("\" not found\n"); | 217 | SEND_STRING("\" not found\n"); |
| @@ -171,7 +229,7 @@ void process_terminal_command(void) { | |||
| 171 | pch = strtok(NULL, " "); | 229 | pch = strtok(NULL, " "); |
| 172 | i++; | 230 | i++; |
| 173 | } | 231 | } |
| 174 | 232 | ||
| 175 | bool command_found = false; | 233 | bool command_found = false; |
| 176 | for( stringcase* case_p = terminal_cases; case_p != terminal_cases + sizeof( terminal_cases ) / sizeof( terminal_cases[0] ); case_p++ ) { | 234 | for( stringcase* case_p = terminal_cases; case_p != terminal_cases + sizeof( terminal_cases ) / sizeof( terminal_cases[0] ); case_p++ ) { |
| 177 | if( 0 == strcmp( case_p->string, buffer ) ) { | 235 | if( 0 == strcmp( case_p->string, buffer ) ) { |
| @@ -192,6 +250,16 @@ void process_terminal_command(void) { | |||
| 192 | send_string(terminal_prompt); | 250 | send_string(terminal_prompt); |
| 193 | } | 251 | } |
| 194 | } | 252 | } |
| 253 | void check_pos(void) { | ||
| 254 | if (current_cmd_buffer_pos >= CMD_BUFF_SIZE) { //if over the top, move it back down to the top of the buffer so you can climb back down... | ||
| 255 | current_cmd_buffer_pos = CMD_BUFF_SIZE - 1; | ||
| 256 | } else if (current_cmd_buffer_pos < 0) { //...and if you fall under the bottom of the buffer, reset back to 0 so you can climb back up | ||
| 257 | current_cmd_buffer_pos = 0; | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | |||
| 262 | |||
| 195 | 263 | ||
| 196 | bool process_terminal(uint16_t keycode, keyrecord_t *record) { | 264 | bool process_terminal(uint16_t keycode, keyrecord_t *record) { |
| 197 | 265 | ||
| @@ -210,6 +278,8 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { | |||
| 210 | char char_to_add; | 278 | char char_to_add; |
| 211 | switch (keycode) { | 279 | switch (keycode) { |
| 212 | case KC_ENTER: | 280 | case KC_ENTER: |
| 281 | push_to_cmd_buffer(); | ||
| 282 | current_cmd_buffer_pos = 0; | ||
| 213 | process_terminal_command(); | 283 | process_terminal_command(); |
| 214 | return false; break; | 284 | return false; break; |
| 215 | case KC_ESC: | 285 | case KC_ESC: |
| @@ -226,9 +296,36 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { | |||
| 226 | return false; | 296 | return false; |
| 227 | } break; | 297 | } break; |
| 228 | case KC_LEFT: | 298 | case KC_LEFT: |
| 299 | return false; break; | ||
| 229 | case KC_RIGHT: | 300 | case KC_RIGHT: |
| 230 | case KC_UP: | 301 | return false; break; |
| 302 | case KC_UP: // 0 = recent | ||
| 303 | check_pos(); //check our current buffer position is valid | ||
| 304 | if (current_cmd_buffer_pos <= CMD_BUFF_SIZE - 1) { //once we get to the top, dont do anything | ||
| 305 | str_len = strlen(buffer); | ||
| 306 | for(int i= 0;i < str_len ;++i) { | ||
| 307 | send_string(SS_TAP(X_BSPACE)); //clear w/e is on the line already | ||
| 308 | //process_terminal(KC_BSPC,record); | ||
| 309 | } | ||
| 310 | strncpy(buffer,cmd_buffer[current_cmd_buffer_pos],80); | ||
| 311 | |||
| 312 | send_string(buffer); | ||
| 313 | ++current_cmd_buffer_pos; //get ready to access the above cmd if up/down is pressed again | ||
| 314 | } | ||
| 315 | return false; break; | ||
| 231 | case KC_DOWN: | 316 | case KC_DOWN: |
| 317 | check_pos(); | ||
| 318 | if (current_cmd_buffer_pos >= 0) { //once we get to the bottom, dont do anything | ||
| 319 | str_len = strlen(buffer); | ||
| 320 | for(int i= 0;i < str_len ;++i) { | ||
| 321 | send_string(SS_TAP(X_BSPACE)); //clear w/e is on the line already | ||
| 322 | //process_terminal(KC_BSPC,record); | ||
| 323 | } | ||
| 324 | strncpy(buffer,cmd_buffer[current_cmd_buffer_pos],79); | ||
| 325 | |||
| 326 | send_string(buffer); | ||
| 327 | --current_cmd_buffer_pos; //get ready to access the above cmd if down/up is pressed again | ||
| 328 | } | ||
| 232 | return false; break; | 329 | return false; break; |
| 233 | default: | 330 | default: |
| 234 | if (keycode <= 58) { | 331 | if (keycode <= 58) { |
| @@ -240,7 +337,7 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { | |||
| 240 | } | 337 | } |
| 241 | if (char_to_add != 0) { | 338 | if (char_to_add != 0) { |
| 242 | strncat(buffer, &char_to_add, 1); | 339 | strncat(buffer, &char_to_add, 1); |
| 243 | } | 340 | } |
| 244 | } break; | 341 | } break; |
| 245 | } | 342 | } |
| 246 | 343 | ||
| @@ -249,4 +346,4 @@ bool process_terminal(uint16_t keycode, keyrecord_t *record) { | |||
| 249 | } | 346 | } |
| 250 | } | 347 | } |
| 251 | return true; | 348 | return true; |
| 252 | } \ No newline at end of file | 349 | } |
