103 lines
3.0 KiB
C
103 lines
3.0 KiB
C
|
|
#include "repl_history.h"
|
||
|
|
#include <stdlib.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <readline/history.h>
|
||
|
|
|
||
|
|
RavaREPLHistory_t* rava_repl_history_create(size_t max_size) {
|
||
|
|
RavaREPLHistory_t *history = malloc(sizeof(RavaREPLHistory_t));
|
||
|
|
if (!history) return NULL;
|
||
|
|
history->capacity = max_size;
|
||
|
|
history->entries = calloc(max_size, sizeof(char*));
|
||
|
|
if (!history->entries) {
|
||
|
|
free(history);
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
history->count = 0;
|
||
|
|
history->position = 0;
|
||
|
|
return history;
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_repl_history_destroy(RavaREPLHistory_t *history) {
|
||
|
|
if (!history) return;
|
||
|
|
for (size_t i = 0; i < history->count; i++) {
|
||
|
|
free(history->entries[i]);
|
||
|
|
}
|
||
|
|
free(history->entries);
|
||
|
|
free(history);
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_repl_history_add(RavaREPLHistory_t *history, const char *entry) {
|
||
|
|
if (!history || !entry || strlen(entry) == 0) return;
|
||
|
|
if (history->count > 0) {
|
||
|
|
if (strcmp(history->entries[history->count - 1], entry) == 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (history->count >= history->capacity) {
|
||
|
|
free(history->entries[0]);
|
||
|
|
memmove(history->entries, history->entries + 1, (history->capacity - 1) * sizeof(char*));
|
||
|
|
history->count--;
|
||
|
|
}
|
||
|
|
history->entries[history->count++] = strdup(entry);
|
||
|
|
history->position = history->count;
|
||
|
|
add_history(entry);
|
||
|
|
}
|
||
|
|
|
||
|
|
const char* rava_repl_history_get(RavaREPLHistory_t *history, size_t index) {
|
||
|
|
if (!history || index >= history->count) return NULL;
|
||
|
|
return history->entries[index];
|
||
|
|
}
|
||
|
|
|
||
|
|
const char* rava_repl_history_prev(RavaREPLHistory_t *history) {
|
||
|
|
if (!history || history->count == 0) return NULL;
|
||
|
|
if (history->position > 0) {
|
||
|
|
history->position--;
|
||
|
|
}
|
||
|
|
return history->entries[history->position];
|
||
|
|
}
|
||
|
|
|
||
|
|
const char* rava_repl_history_next(RavaREPLHistory_t *history) {
|
||
|
|
if (!history || history->count == 0) return NULL;
|
||
|
|
if (history->position < history->count - 1) {
|
||
|
|
history->position++;
|
||
|
|
return history->entries[history->position];
|
||
|
|
}
|
||
|
|
history->position = history->count;
|
||
|
|
return NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
void rava_repl_history_reset_position(RavaREPLHistory_t *history) {
|
||
|
|
if (!history) return;
|
||
|
|
history->position = history->count;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool rava_repl_history_save(RavaREPLHistory_t *history, const char *filename) {
|
||
|
|
if (!history || !filename) return false;
|
||
|
|
FILE *f = fopen(filename, "w");
|
||
|
|
if (!f) return false;
|
||
|
|
for (size_t i = 0; i < history->count; i++) {
|
||
|
|
fprintf(f, "%s\n", history->entries[i]);
|
||
|
|
}
|
||
|
|
fclose(f);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool rava_repl_history_load(RavaREPLHistory_t *history, const char *filename) {
|
||
|
|
if (!history || !filename) return false;
|
||
|
|
FILE *f = fopen(filename, "r");
|
||
|
|
if (!f) return false;
|
||
|
|
char line[RAVA_REPL_MAX_INPUT];
|
||
|
|
while (fgets(line, sizeof(line), f)) {
|
||
|
|
size_t len = strlen(line);
|
||
|
|
if (len > 0 && line[len - 1] == '\n') {
|
||
|
|
line[len - 1] = '\0';
|
||
|
|
}
|
||
|
|
if (strlen(line) > 0) {
|
||
|
|
rava_repl_history_add(history, line);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
fclose(f);
|
||
|
|
return true;
|
||
|
|
}
|