aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDavid Walter Seikel2014-01-30 21:37:56 +1000
committerDavid Walter Seikel2014-01-30 21:37:56 +1000
commit7161efbd008f139884df16b82c07f3c2b7f5b50d (patch)
treed168b4d5f1dc2a3b935891ce26347df5fde1386c
parentAdded dumbsh, a really really dumb shell, for demonstration. (diff)
downloadboxes-7161efbd008f139884df16b82c07f3c2b7f5b50d.zip
boxes-7161efbd008f139884df16b82c07f3c2b7f5b50d.tar.gz
boxes-7161efbd008f139884df16b82c07f3c2b7f5b50d.tar.bz2
boxes-7161efbd008f139884df16b82c07f3c2b7f5b50d.tar.xz
Fix up dumbsh so it all works.
-rw-r--r--dumbsh.c104
1 files changed, 65 insertions, 39 deletions
diff --git a/dumbsh.c b/dumbsh.c
index 1d4ca4f..fe184dd 100644
--- a/dumbsh.c
+++ b/dumbsh.c
@@ -30,47 +30,51 @@ struct keyCommand
30GLOBALS( 30GLOBALS(
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
37static void moveCursor() 38static 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.
48static void handleCSI(long extra, char *command, int *params, int count) 50static 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.
67static void deleteChar() 71static 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
76static void backSpaceChar() 80static 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.
85static void doCommand() 91static 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
95static void downLine()
96{
97 // Do command history stuff here.
98} 97}
99 98
100static void endOfLine() 99static void endOfLine()
101{ 100{
102 TT.x = strlen(toybuf) - 1; 101 TT.x = strlen(toybuf) - 1;
103 moveCursor(); 102 updateLine();
104} 103}
105 104
106static void leftChar() 105static void leftChar()
107{ 106{
108 TT.x--; 107 TT.x--;
109 moveCursor(); 108 updateLine();
109}
110
111static void nextHistory()
112{
113 TT.current = TT.current->next;
114 strcpy(toybuf, TT.current->data);
115 TT.x = strlen(toybuf);
116 updateLine();
117}
118
119static 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
112static void quit() 127static void quit()
@@ -117,28 +132,26 @@ static void quit()
117static void rightChar() 132static void rightChar()
118{ 133{
119 TT.x++; 134 TT.x++;
120 moveCursor(); 135 updateLine();
121} 136}
122 137
123static void startOfLine() 138static void startOfLine()
124{ 139{
125 TT.x = 0; 140 TT.x = 0;
126 moveCursor(); 141 updateLine();
127}
128
129static 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.
135static struct keyCommand simpleEmacsKeys[] = 145static 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)
189void dumbsh_main(void) 204void 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}