Skip to content

Commit 611792a

Browse files
committed
added builtin commands to the stlxterm emulator
1 parent 799e4bc commit 611792a

File tree

4 files changed

+262
-0
lines changed

4 files changed

+262
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef STLXTERM_BUILTIN_COMMANDS_H
2+
#define STLXTERM_BUILTIN_COMMANDS_H
3+
4+
#include <stdint.h>
5+
#include <stdbool.h>
6+
#include "terminal.h"
7+
8+
// Built-in command function type
9+
typedef int (*builtin_command_func_t)(terminal_t* term, int argc, char* argv[]);
10+
11+
// Built-in command structure
12+
typedef struct {
13+
const char* name;
14+
const char* description;
15+
builtin_command_func_t func;
16+
} builtin_command_t;
17+
18+
// Built-in command functions
19+
int cmd_echo(terminal_t* term, int argc, char* argv[]);
20+
int cmd_clear(terminal_t* term, int argc, char* argv[]);
21+
int cmd_getpid(terminal_t* term, int argc, char* argv[]);
22+
int cmd_help(terminal_t* term, int argc, char* argv[]);
23+
24+
// Command processing functions
25+
void process_command(terminal_t* term, const char* command_line);
26+
int execute_builtin_command(terminal_t* term, const char* command, int argc, char* argv[]);
27+
void split_command_line(const char* line, char* argv[], int max_args, int* argc);
28+
29+
// Available built-in commands
30+
extern const builtin_command_t builtin_commands[];
31+
extern const int builtin_command_count;
32+
33+
#endif // STLXTERM_BUILTIN_COMMANDS_H

userland/apps/stlxterm/include/terminal.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ typedef struct {
8888
// Output buffer (for child process communication)
8989
char output_buffer[4096];
9090
int output_buffer_pos;
91+
92+
// Command line handling
93+
char command_line[1024];
94+
int command_line_pos;
95+
bool command_ready;
9196
} terminal_t;
9297

9398
// Function prototypes
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
#define _POSIX_C_SOURCE 199309L
2+
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
#include <unistd.h>
7+
#include <sys/types.h>
8+
9+
#include "builtin_commands.h"
10+
11+
// Built-in command implementations
12+
13+
// Echo command - prints its arguments
14+
int cmd_echo(terminal_t* term, int argc, char* argv[]) {
15+
if (!term) {
16+
return -1;
17+
}
18+
19+
// Print all arguments separated by spaces
20+
for (int i = 1; i < argc; i++) {
21+
if (i > 1) {
22+
terminal_write_string(term, " ");
23+
}
24+
terminal_write_string(term, argv[i]);
25+
}
26+
27+
// Add newline at the end
28+
terminal_write_string(term, "\r\n");
29+
30+
return 0;
31+
}
32+
33+
// Clear command - clears the terminal screen
34+
int cmd_clear(terminal_t* term, int argc, char* argv[]) {
35+
(void)argc; // Unused parameter
36+
(void)argv; // Unused parameter
37+
38+
if (!term) {
39+
return -1;
40+
}
41+
42+
terminal_clear_screen(term);
43+
return 0;
44+
}
45+
46+
// Getpid command - prints the current process ID
47+
int cmd_getpid(terminal_t* term, int argc, char* argv[]) {
48+
(void)argc; // Unused parameter
49+
(void)argv; // Unused parameter
50+
51+
if (!term) {
52+
return -1;
53+
}
54+
55+
pid_t pid = getpid();
56+
char pid_str[32];
57+
snprintf(pid_str, sizeof(pid_str), "%d\r\n", (int)pid);
58+
terminal_write_string(term, pid_str);
59+
60+
return 0;
61+
}
62+
63+
// Help command - shows available built-in commands
64+
int cmd_help(terminal_t* term, int argc, char* argv[]) {
65+
(void)argc; // Unused parameter
66+
(void)argv; // Unused parameter
67+
68+
if (!term) {
69+
return -1;
70+
}
71+
72+
terminal_write_string(term, "Available built-in commands:\r\n");
73+
terminal_write_string(term, "============================\r\n");
74+
75+
for (int i = 0; i < builtin_command_count; i++) {
76+
char help_line[256];
77+
snprintf(help_line, sizeof(help_line), " %-10s - %s\r\n",
78+
builtin_commands[i].name, builtin_commands[i].description);
79+
terminal_write_string(term, help_line);
80+
}
81+
82+
terminal_write_string(term, "\r\n");
83+
return 0;
84+
}
85+
86+
// Command processing functions
87+
88+
// Split a command line into arguments
89+
void split_command_line(const char* line, char* argv[], int max_args, int* argc) {
90+
if (!line || !argv || !argc || max_args <= 0) {
91+
if (argc) *argc = 0;
92+
return;
93+
}
94+
95+
*argc = 0;
96+
97+
// Make a copy of the line since we need to modify it
98+
char* line_copy = malloc(strlen(line) + 1);
99+
if (!line_copy) {
100+
if (argc) *argc = 0;
101+
return;
102+
}
103+
strcpy(line_copy, line);
104+
105+
char* p = line_copy;
106+
107+
// Skip leading whitespace
108+
while (*p && (*p == ' ' || *p == '\t')) {
109+
p++;
110+
}
111+
112+
while (*p && *argc < max_args - 1) {
113+
argv[*argc] = p;
114+
(*argc)++;
115+
116+
// Find end of argument
117+
while (*p && *p != ' ' && *p != '\t') {
118+
p++;
119+
}
120+
121+
// Null-terminate the argument
122+
if (*p) {
123+
*p = '\0';
124+
p++;
125+
}
126+
127+
// Skip whitespace
128+
while (*p && (*p == ' ' || *p == '\t')) {
129+
p++;
130+
}
131+
}
132+
133+
argv[*argc] = NULL; // Null-terminate the argument list
134+
}
135+
136+
// Execute a built-in command
137+
int execute_builtin_command(terminal_t* term, const char* command, int argc, char* argv[]) {
138+
if (!term || !command) {
139+
return -1;
140+
}
141+
142+
// Find the command
143+
for (int i = 0; i < builtin_command_count; i++) {
144+
if (strcmp(command, builtin_commands[i].name) == 0) {
145+
return builtin_commands[i].func(term, argc, argv);
146+
}
147+
}
148+
149+
// Command not found
150+
char error_msg[256];
151+
snprintf(error_msg, sizeof(error_msg), "Command not found: %s\r\n", command);
152+
terminal_write_string(term, error_msg);
153+
return -1;
154+
}
155+
156+
// Process a complete command line
157+
void process_command(terminal_t* term, const char* command_line) {
158+
if (!term || !command_line) {
159+
return;
160+
}
161+
162+
// Skip empty lines
163+
if (strlen(command_line) == 0) {
164+
return;
165+
}
166+
167+
char* argv[32];
168+
int argc = 0;
169+
170+
// Split the command line into arguments
171+
split_command_line(command_line, argv, 32, &argc);
172+
173+
if (argc > 0) {
174+
// Execute the command
175+
execute_builtin_command(term, argv[0], argc, argv);
176+
177+
// Free the allocated memory
178+
if (argv[0]) {
179+
free(argv[0]);
180+
}
181+
}
182+
}
183+
184+
// Built-in commands table
185+
const builtin_command_t builtin_commands[] = {
186+
{"echo", "Print arguments to the terminal", cmd_echo},
187+
{"clear", "Clear the terminal screen", cmd_clear},
188+
{"getpid", "Print the current process ID", cmd_getpid},
189+
{"help", "Show available built-in commands", cmd_help}
190+
};
191+
192+
const int builtin_command_count = sizeof(builtin_commands) / sizeof(builtin_commands[0]);

userland/apps/stlxterm/src/terminal.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <stlxgfx/stlxgfx.h>
1212

1313
#include "terminal.h"
14+
#include "builtin_commands.h"
1415

1516
// Default colors
1617
#define DEFAULT_FG_COLOR 0xFFE0E0E0 // Light gray
@@ -159,6 +160,11 @@ void terminal_reset(terminal_t* term) {
159160
// Reset buffers
160161
term->input_buffer_pos = 0;
161162
term->output_buffer_pos = 0;
163+
164+
// Reset command line
165+
term->command_line_pos = 0;
166+
term->command_ready = false;
167+
memset(term->command_line, 0, sizeof(term->command_line));
162168
}
163169

164170
// Main terminal loop
@@ -265,15 +271,41 @@ void terminal_handle_event(terminal_t* term, const stlxgfx_event_t* event) {
265271
term->state.cursor_x--;
266272
terminal_write_char(term, ' '); // Clear the character
267273
term->state.cursor_x--; // Move back again
274+
275+
// Also remove from command line buffer
276+
if (term->command_line_pos > 0) {
277+
term->command_line_pos--;
278+
term->command_line[term->command_line_pos] = '\0';
279+
}
268280
}
269281
needs_redraw = true;
270282
} else if (event->udata1 == 0x28) { // Enter
271283
terminal_write_char(term, '\r');
272284
terminal_write_char(term, '\n');
285+
286+
// Process the command
287+
if (term->command_line_pos > 0) {
288+
process_command(term, term->command_line);
289+
290+
// Reset command line
291+
term->command_line_pos = 0;
292+
memset(term->command_line, 0, sizeof(term->command_line));
293+
}
294+
295+
// Show new prompt
296+
terminal_write_string(term, "$ ");
297+
273298
needs_redraw = true;
274299
} else if (ascii_char >= 32 && ascii_char <= 126) {
275300
// Handle printable characters
276301
terminal_write_char(term, (char)ascii_char);
302+
303+
// Add to command line buffer
304+
if (term->command_line_pos < (int)sizeof(term->command_line) - 1) {
305+
term->command_line[term->command_line_pos] = (char)ascii_char;
306+
term->command_line_pos++;
307+
}
308+
277309
needs_redraw = true;
278310
}
279311
break;

0 commit comments

Comments
 (0)