diff options
Diffstat (limited to '')
| -rw-r--r-- | dumbsh.c | 104 |
1 files changed, 65 insertions, 39 deletions
| @@ -30,47 +30,51 @@ struct keyCommand | |||
| 30 | GLOBALS( | 30 | GLOBALS( |
| 31 | unsigned h, w; | 31 | unsigned h, w; |
| 32 | int x, y; | 32 | int x, y; |
| 33 | struct double_list *current; | ||
| 33 | ) | 34 | ) |
| 34 | 35 | ||
| 35 | #define TT this.dumbsh | 36 | #define TT this.dumbsh |
| 36 | 37 | ||
| 37 | static void moveCursor() | 38 | static void updateLine() |
| 38 | { | 39 | { |
| 39 | if (0 > TT.y) TT.y = 0; | 40 | if (0 > TT.y) TT.y = 0; |
| 40 | if (0 > TT.x) TT.x = 0; | 41 | if (0 > TT.x) TT.x = 0; |
| 41 | if (strlen(toybuf) <= TT.x) TT.x = strlen(toybuf); | 42 | if (strlen(toybuf) <= TT.x) TT.x = strlen(toybuf); |
| 42 | if (TT.w < TT.y) TT.y = TT.w; | 43 | if (TT.h < TT.y) TT.y = TT.h; |
| 43 | if (TT.h < TT.x) TT.x = TT.h; | 44 | if (TT.w < TT.x) TT.x = TT.w; |
| 44 | printf("\x1B[%d;0H%s\x1B[%d;%dH", TT.y + 1, toybuf, TT.y + 1, TT.x + 1); | 45 | printf("\x1B[%d;0H%-*s\x1B[%d;%dH", TT.y + 1, TT.w, toybuf, TT.y + 1, TT.x + 1); |
| 45 | fflush(stdout); | 46 | fflush(stdout); |
| 46 | } | 47 | } |
| 47 | 48 | ||
| 49 | // Callback for incoming CSI commands from the terminal. | ||
| 48 | static void handleCSI(long extra, char *command, int *params, int count) | 50 | static void handleCSI(long extra, char *command, int *params, int count) |
| 49 | { | 51 | { |
| 50 | // Parameters are cursor line and column. Note this may be sent at other times, not just during terminal resize. | 52 | // Is it a cursor location report? |
| 51 | if (strcmp("R", command) == 0) | 53 | if (strcmp("R", command) == 0) |
| 52 | { | 54 | { |
| 55 | // Parameters are cursor line and column. Note this may be sent at other times, not just during terminal resize. | ||
| 56 | // The defaults are 1, which get ignored by the heuristic below. | ||
| 53 | int r = params[0], c = params[1]; | 57 | int r = params[0], c = params[1]; |
| 54 | 58 | ||
| 55 | // The defaults are 1, which get ignored by the heuristic below. | ||
| 56 | // Check it's not an F3 key variation, coz some of them use the same CSI function code. | 59 | // Check it's not an F3 key variation, coz some of them use the same CSI function code. |
| 57 | // This is a heuristic, we are checking against an unusable terminal size. | 60 | // This is a heuristic, we are checking against an unusable terminal size. |
| 58 | if ((2 == count) && (8 < r) && (8 < c)) | 61 | if ((2 == count) && (8 < r) && (8 < c)) |
| 59 | { | 62 | { |
| 60 | TT.h = r; | 63 | TT.h = r; |
| 61 | TT.w = c; | 64 | TT.w = c; |
| 62 | moveCursor(); | 65 | updateLine(); |
| 63 | } | 66 | } |
| 64 | } | 67 | } |
| 65 | } | 68 | } |
| 66 | 69 | ||
| 70 | // The various commands. | ||
| 67 | static void deleteChar() | 71 | static void deleteChar() |
| 68 | { | 72 | { |
| 69 | int j; | 73 | int j; |
| 70 | 74 | ||
| 71 | for (j = TT.x; toybuf[j]; j++) | 75 | for (j = TT.x; toybuf[j]; j++) |
| 72 | toybuf[j] = toybuf[j + 1]; | 76 | toybuf[j] = toybuf[j + 1]; |
| 73 | moveCursor(); | 77 | updateLine(); |
| 74 | } | 78 | } |
| 75 | 79 | ||
| 76 | static void backSpaceChar() | 80 | static void backSpaceChar() |
| @@ -82,31 +86,42 @@ static void backSpaceChar() | |||
| 82 | } | 86 | } |
| 83 | } | 87 | } |
| 84 | 88 | ||
| 89 | // This is where we would actually deal with what ever command the user had typed in. | ||
| 90 | // For now we just move on. | ||
| 85 | static void doCommand() | 91 | static void doCommand() |
| 86 | { | 92 | { |
| 87 | // This is where we would actually deal with what ever command the user had typed in. | ||
| 88 | // For now we just move on. | ||
| 89 | toybuf[0] = 0; | 93 | toybuf[0] = 0; |
| 90 | TT.x = 0; | 94 | TT.x = 0; |
| 91 | TT.y++; | 95 | TT.y++; |
| 92 | moveCursor(); | 96 | updateLine(); |
| 93 | } | ||
| 94 | |||
| 95 | static void downLine() | ||
| 96 | { | ||
| 97 | // Do command history stuff here. | ||
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | static void endOfLine() | 99 | static void endOfLine() |
| 101 | { | 100 | { |
| 102 | TT.x = strlen(toybuf) - 1; | 101 | TT.x = strlen(toybuf) - 1; |
| 103 | moveCursor(); | 102 | updateLine(); |
| 104 | } | 103 | } |
| 105 | 104 | ||
| 106 | static void leftChar() | 105 | static void leftChar() |
| 107 | { | 106 | { |
| 108 | TT.x--; | 107 | TT.x--; |
| 109 | moveCursor(); | 108 | updateLine(); |
| 109 | } | ||
| 110 | |||
| 111 | static void nextHistory() | ||
| 112 | { | ||
| 113 | TT.current = TT.current->next; | ||
| 114 | strcpy(toybuf, TT.current->data); | ||
| 115 | TT.x = strlen(toybuf); | ||
| 116 | updateLine(); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void prevHistory() | ||
| 120 | { | ||
| 121 | TT.current = TT.current->prev; | ||
| 122 | strcpy(toybuf, TT.current->data); | ||
| 123 | TT.x = strlen(toybuf); | ||
| 124 | updateLine(); | ||
| 110 | } | 125 | } |
| 111 | 126 | ||
| 112 | static void quit() | 127 | static void quit() |
| @@ -117,28 +132,26 @@ static void quit() | |||
| 117 | static void rightChar() | 132 | static void rightChar() |
| 118 | { | 133 | { |
| 119 | TT.x++; | 134 | TT.x++; |
| 120 | moveCursor(); | 135 | updateLine(); |
| 121 | } | 136 | } |
| 122 | 137 | ||
| 123 | static void startOfLine() | 138 | static void startOfLine() |
| 124 | { | 139 | { |
| 125 | TT.x = 0; | 140 | TT.x = 0; |
| 126 | moveCursor(); | 141 | updateLine(); |
| 127 | } | ||
| 128 | |||
| 129 | static void upLine() | ||
| 130 | { | ||
| 131 | // Do command history stuff here. | ||
| 132 | } | 142 | } |
| 133 | 143 | ||
| 134 | // The key to command mappings. | 144 | // The key to command mappings. |
| 135 | static struct keyCommand simpleEmacsKeys[] = | 145 | static struct keyCommand simpleEmacsKeys[] = |
| 136 | { | 146 | { |
| 137 | {"Del", backSpaceChar}, | 147 | {"BS", backSpaceChar}, |
| 148 | {"Del", deleteChar}, | ||
| 138 | {"^D", deleteChar}, | 149 | {"^D", deleteChar}, |
| 139 | {"Return", doCommand}, | 150 | {"Return", doCommand}, |
| 140 | {"Down", downLine}, | 151 | {"^J", doCommand}, |
| 141 | {"^N", downLine}, | 152 | {"^M", doCommand}, |
| 153 | {"Down", nextHistory}, | ||
| 154 | {"^N", nextHistory}, | ||
| 142 | {"End", endOfLine}, | 155 | {"End", endOfLine}, |
| 143 | {"^E", endOfLine}, | 156 | {"^E", endOfLine}, |
| 144 | {"Left", leftChar}, | 157 | {"Left", leftChar}, |
| @@ -149,8 +162,8 @@ static struct keyCommand simpleEmacsKeys[] = | |||
| 149 | {"^F", rightChar}, | 162 | {"^F", rightChar}, |
| 150 | {"Home", startOfLine}, | 163 | {"Home", startOfLine}, |
| 151 | {"^A", startOfLine}, | 164 | {"^A", startOfLine}, |
| 152 | {"Up", upLine}, | 165 | {"Up", prevHistory}, |
| 153 | {"^P", upLine}, | 166 | {"^P", prevHistory}, |
| 154 | {NULL, NULL} | 167 | {NULL, NULL} |
| 155 | }; | 168 | }; |
| 156 | 169 | ||
| @@ -168,17 +181,19 @@ static int handleKeySequence(long extra, char *sequence) | |||
| 168 | } | 181 | } |
| 169 | } | 182 | } |
| 170 | 183 | ||
| 171 | if ((0 == sequence[1]) && isprint(sequence[0])) // See if it's an ordinary key. | 184 | // See if it's ordinary keys. |
| 185 | if (isprint(sequence[0])) | ||
| 172 | { | 186 | { |
| 173 | if (TT.x < sizeof(toybuf)) | 187 | if (TT.x < sizeof(toybuf)) |
| 174 | { | 188 | { |
| 175 | int j; | 189 | int j, l = strlen(sequence); |
| 176 | 190 | ||
| 177 | for (j = strlen(toybuf); j >= TT.x; j--) | 191 | for (j = strlen(toybuf); j >= TT.x; j--) |
| 178 | toybuf[j + 1] = toybuf[j]; | 192 | toybuf[j + l] = toybuf[j]; |
| 179 | toybuf[TT.x] = sequence[0]; | 193 | for (j = 0; j < l; j++) |
| 180 | TT.x++; | 194 | toybuf[TT.x + j] = sequence[j]; |
| 181 | moveCursor(); | 195 | TT.x += l; |
| 196 | updateLine(); | ||
| 182 | } | 197 | } |
| 183 | return 1; | 198 | return 1; |
| 184 | } | 199 | } |
| @@ -189,6 +204,18 @@ static int handleKeySequence(long extra, char *sequence) | |||
| 189 | void dumbsh_main(void) | 204 | void dumbsh_main(void) |
| 190 | { | 205 | { |
| 191 | struct termios termio, oldtermio; | 206 | struct termios termio, oldtermio; |
| 207 | char *temp = getenv("HOME"); | ||
| 208 | int fd; | ||
| 209 | |||
| 210 | // Load bash history. | ||
| 211 | temp = xmsprintf("%s/%s", temp ? temp : "", ".bash_history"); | ||
| 212 | if (-1 != (fd = open(temp, O_RDONLY))) | ||
| 213 | { | ||
| 214 | while ((temp = get_line(fd))) TT.current = dlist_add(&TT.current, temp); | ||
| 215 | close(fd); | ||
| 216 | } | ||
| 217 | if (!TT.current) | ||
| 218 | TT.current = dlist_add(&TT.current, ""); | ||
| 192 | 219 | ||
| 193 | // Grab the old terminal settings and save it. | 220 | // Grab the old terminal settings and save it. |
| 194 | tcgetattr(0, &oldtermio); | 221 | tcgetattr(0, &oldtermio); |
| @@ -205,16 +232,15 @@ void dumbsh_main(void) | |||
| 205 | termio.c_cc[VMIN]=1; | 232 | termio.c_cc[VMIN]=1; |
| 206 | tcsetattr(0, TCSANOW, &termio); | 233 | tcsetattr(0, TCSANOW, &termio); |
| 207 | 234 | ||
| 235 | // Let the mouldy old terminal mold us. | ||
| 208 | TT.w = 80; | 236 | TT.w = 80; |
| 209 | TT.h = 24; | 237 | TT.h = 24; |
| 210 | terminal_size(&TT.w, &TT.h); | 238 | terminal_size(&TT.w, &TT.h); |
| 211 | 239 | ||
| 212 | // Run the main loop. | 240 | updateLine(); |
| 213 | handle_keys(0, handleKeySequence, handleCSI); | 241 | handle_keys(0, handleKeySequence, handleCSI); |
| 214 | 242 | ||
| 215 | // Restore the old terminal settings. | ||
| 216 | tcsetattr(0, TCSANOW, &oldtermio); | 243 | tcsetattr(0, TCSANOW, &oldtermio); |
| 217 | |||
| 218 | puts(""); | 244 | puts(""); |
| 219 | fflush(stdout); | 245 | fflush(stdout); |
| 220 | } | 246 | } |
