146 lines
4.2 KiB
C
146 lines
4.2 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
|
|
#define MAX_SIZE 1024
|
|
#define HISTORY_SIZE 10
|
|
|
|
// Global variable for termios
|
|
struct termios orig_termios;
|
|
|
|
// Terminal input helpers
|
|
void EnableRawMode(struct termios* orig_termios) {
|
|
struct termios raw = *orig_termios;
|
|
raw.c_lflag &= ~(ECHO | ICANON); // Disable echo and canonical mode
|
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
|
|
}
|
|
|
|
void DisableRawMode(struct termios* orig_termios) {
|
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, orig_termios);
|
|
}
|
|
|
|
// Wrapper function to pass DisableRawMode with argument
|
|
void DisableRawModeWrapper() {
|
|
DisableRawMode(&orig_termios);
|
|
}
|
|
|
|
int LogCommandHistory(char* buf, char** command_log, int* n) {
|
|
int index = *n % HISTORY_SIZE;
|
|
int prev_index = (*n == 0) ? HISTORY_SIZE - 1 : (*n - 1) % HISTORY_SIZE;
|
|
|
|
if (command_log[prev_index] != NULL && strcmp(buf, command_log[prev_index]) == 0) {
|
|
return 0;
|
|
}
|
|
if (command_log[index] != NULL) {
|
|
free(command_log[index]);
|
|
}
|
|
|
|
command_log[index] = strdup(buf);
|
|
(*n)++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void FreeCommandHistory(char** command_log, int n) {
|
|
for (int i = 0; i < n; i++) {
|
|
free(command_log[i]);
|
|
}
|
|
}
|
|
|
|
// Get input with arrow key navigation
|
|
void GetInputWithHistory(char* buf, char** command_log, int n) {
|
|
int index = n % HISTORY_SIZE;
|
|
int history_counter = 0;
|
|
int pos = 0;
|
|
char c;
|
|
|
|
while (1) {
|
|
c = getchar();
|
|
|
|
|
|
if (c == '\n') { // Enter key
|
|
buf[pos] = '\0';
|
|
printf("\n");
|
|
return;
|
|
} else if (c == 127 || c == '\b') { // Backspace
|
|
if (pos > 0) {
|
|
pos--;
|
|
buf[pos] = '\0';
|
|
printf("\b \b");
|
|
}
|
|
} else if (c == '\033') { // Inputting arrow keys
|
|
getchar(); // Skipping the first '[' character
|
|
char arrow = getchar();
|
|
if (arrow == 'A' && history_counter < HISTORY_SIZE) { // Up arrow
|
|
int prev_index = (index == 0) ? HISTORY_SIZE - 1 : (index - 1) % HISTORY_SIZE;
|
|
if (command_log[prev_index] != NULL) {
|
|
index = (index == 0) ? HISTORY_SIZE - 1 : index - 1; // Decrease the index
|
|
history_counter++;
|
|
|
|
strcpy(buf, command_log[index]);
|
|
printf("\33[2K\r"); // Clear line
|
|
printf("[%s] $ %s", getcwd(NULL, 0), buf);
|
|
pos = strlen(buf);
|
|
}
|
|
} else if (arrow == 'B') { // Down arrow
|
|
if (history_counter > 1) {
|
|
index = (index + 1) % HISTORY_SIZE;
|
|
history_counter--;
|
|
|
|
strcpy(buf, command_log[index]);
|
|
printf("\33[2K\r"); // Clear line
|
|
printf("[%s] $ %s", getcwd(NULL, 0), buf);
|
|
pos = strlen(buf);
|
|
} else if (history_counter == 1) {
|
|
history_counter--;
|
|
index++;
|
|
|
|
buf[0] = '\0'; // Clear buffer
|
|
printf("\33[2K\r"); // Clear line
|
|
printf("[%s] $ ", getcwd(NULL, 0));
|
|
pos = 0;
|
|
}
|
|
}
|
|
} else { // Regular character
|
|
if (pos < MAX_SIZE - 1) {
|
|
buf[pos++] = c;
|
|
buf[pos] = '\0';
|
|
printf("%c", c);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
char buf[MAX_SIZE];
|
|
char* command_log[HISTORY_SIZE] = {NULL};
|
|
int n = 0;
|
|
|
|
tcgetattr(STDIN_FILENO, &orig_termios);
|
|
|
|
// Register atexit to call DisableRawModeWrapper when the program exits
|
|
atexit(DisableRawModeWrapper);
|
|
|
|
while (1) {
|
|
printf("[%s] $ ", getcwd(NULL, 0));
|
|
|
|
// Enable raw mode for manual input handling
|
|
EnableRawMode(&orig_termios);
|
|
GetInputWithHistory(buf, command_log, n);
|
|
DisableRawMode(&orig_termios);
|
|
|
|
if (strcmp(buf, "exit") == 0) {
|
|
break;
|
|
}
|
|
|
|
LogCommandHistory(buf, command_log, &n);
|
|
printf("Executed: %s\n", buf); // For testing, replace with actual command handling
|
|
}
|
|
|
|
FreeCommandHistory(command_log, n);
|
|
return 0;
|
|
}
|