1
0
mirror of https://github.com/janet-lang/janet synced 2026-02-06 10:10:20 +00:00

Add persistent repl history.

This commit is contained in:
Calvin Rose
2026-01-20 13:41:51 -06:00
parent 606a1fc11a
commit 0c402cf3d6
4 changed files with 105 additions and 9 deletions

View File

@@ -272,6 +272,11 @@ This variable does nothing in the default configuration of Janet, as PRF is disa
cannot be defined for this variable to have an effect.
.RE
.B JANET_HISTFILE
.RS
A file location to use for the default shell's REPL history. This relative path is where commands are persisted between sessions.
.RE
.B NO_COLOR
.RS
Turn off color by default in the repl and in the error handler of scripts. This can be changed at runtime

View File

@@ -718,6 +718,18 @@ JANET_CORE_FN(cfun_io_eflush,
return janet_wrap_nil();
}
void janet_xprintf(FILE *file, const char *format, ...) {
va_list args;
va_start(args, format);
JanetBuffer buffer;
int32_t len = 0;
while (format[len]) len++;
janet_buffer_init(&buffer, len);
janet_formatbv(&buffer, format, args);
fwrite(buffer.data, buffer.count, 1, file);
janet_buffer_deinit(&buffer);
}
void janet_dynprintf(const char *name, FILE *dflt_file, const char *format, ...) {
va_list args;
va_start(args, format);

View File

@@ -1439,6 +1439,7 @@ JANET_API void janet_loop(void);
* } else {
* janet_schedule(interrupted_fiber, janet_wrap_nil());
* }
* janet_interpreter_interrupt_handled(NULL);
* }
* }
*
@@ -1889,7 +1890,7 @@ JANET_API void janet_vm_free(JanetVM *vm);
JANET_API void janet_vm_save(JanetVM *into);
JANET_API void janet_vm_load(JanetVM *from);
JANET_API void janet_interpreter_interrupt(JanetVM *vm);
JANET_API void janet_interpreter_interrupt_handled(JanetVM *vm);
JANET_API void janet_interpreter_interrupt_handled(JanetVM *vm); /* Call this after running interrupt handler */
JANET_API JanetSignal janet_continue(JanetFiber *fiber, Janet in, Janet *out);
JANET_API JanetSignal janet_continue_signal(JanetFiber *fiber, Janet in, Janet *out, JanetSignal sig);
JANET_API JanetSignal janet_pcall(JanetFunction *fun, int32_t argn, const Janet *argv, Janet *out, JanetFiber **f);
@@ -2051,6 +2052,7 @@ JANET_NO_RETURN JANET_API void janet_panicv(Janet message);
JANET_NO_RETURN JANET_API void janet_panic(const char *message);
JANET_NO_RETURN JANET_API void janet_panics(JanetString message);
JANET_NO_RETURN JANET_API void janet_panicf(const char *format, ...);
JANET_API void janet_xprintf(FILE *file, const char *format, ...);
JANET_API void janet_dynprintf(const char *name, FILE *dflt_file, const char *format, ...);
#define janet_printf(...) janet_dynprintf("out", stdout, __VA_ARGS__)
#define janet_eprintf(...) janet_dynprintf("err", stderr, __VA_ARGS__)

View File

@@ -96,9 +96,9 @@ static void simpleline(JanetBuffer *buffer) {
#ifndef JANET_SIMPLE_GETLINE
/* static state */
#define JANET_LINE_MAX 1024
#define JANET_LINE_MAX 4096
#define JANET_MATCH_MAX 256
#define JANET_HISTORY_MAX 100
#define JANET_HISTORY_MAX 1000
static JANET_THREAD_LOCAL int gbl_israwmode = 0;
static JANET_THREAD_LOCAL const char *gbl_prompt = "> ";
static JANET_THREAD_LOCAL int gbl_plen = 2;
@@ -112,6 +112,8 @@ static JANET_THREAD_LOCAL int gbl_historyi = 0;
static JANET_THREAD_LOCAL JanetByteView gbl_matches[JANET_MATCH_MAX];
static JANET_THREAD_LOCAL int gbl_match_count = 0;
static JANET_THREAD_LOCAL int gbl_lines_below = 0;
static JANET_THREAD_LOCAL int gbl_history_loaded = 0;
static JANET_THREAD_LOCAL char *gbl_history_file = NULL;
#endif
/* Fallback */
@@ -430,6 +432,74 @@ static int insert(char c, int draw) {
return 0;
}
static void calc_history_file(void) {
char *hist = getenv("JANET_HISTFILE");
if (hist) {
gbl_history_file = sdup(hist);
} else {
const char *home = (const char *) getenv("HOME");
if (NULL == home) home = "";
const char *filename = ".janet_history.jdn";
size_t homelen = strlen(home);
size_t filelen = strlen(filename);
size_t buflen = homelen + filelen + 1;
char *buffer = janet_malloc(buflen + 1);
if (homelen) memcpy(buffer, home, homelen);
buffer[homelen] = '/';
memcpy(buffer + homelen + 1, filename, filelen);
buffer[buflen] = '\0';
gbl_history_file = buffer;
}
/* fprintf(stderr, "history_file: %s\n", gbl_history_file); */
}
static void loadhistory(void) {
if (gbl_history_loaded) return;
calc_history_file();
gbl_history_loaded = 1;
FILE *history_file = fopen(gbl_history_file, "rb");
if (NULL == history_file) return;
JanetParser p;
janet_parser_init(&p);
int c = 0;
while ((c = fgetc(history_file))) {
if (c == EOF) {
janet_parser_eof(&p);
} else {
janet_parser_consume(&p, c);
}
while (janet_parser_has_more(&p) && gbl_history_count < JANET_HISTORY_MAX) {
if (janet_parser_status(&p) == JANET_PARSE_ERROR) {
janet_eprintf("bad history file: %s\n", janet_parser_error(&p));
goto parsing_done;
}
Janet x = janet_parser_produce(&p);
const char *cstr = (const char *) janet_to_string(x);
if (cstr[0]) { /* Drop empty strings */
gbl_history[gbl_history_count++] = sdup(cstr);
}
}
if (c == EOF) break;
}
parsing_done:
janet_parser_deinit(&p);
gbl_historyi = 0;
fclose(history_file);
}
static void savehistory(void) {
if (gbl_history_count <= 1 || !gbl_history_file) return;
FILE *history_file = fopen(gbl_history_file, "wb");
for (int i = 0; i < gbl_history_count; i++) {
if (gbl_history[i][0]) { /* Drop empty strings */
janet_xprintf(history_file, "%j\n", janet_cstringv(gbl_history[i]));
}
}
fclose(history_file);
}
static void historymove(int delta) {
if (gbl_history_count > 1) {
janet_free(gbl_history[gbl_historyi]);
@@ -896,6 +966,7 @@ static int line() {
case 3: /* ctrl-c */
clearlines();
norawmode();
savehistory();
#ifdef _WIN32
ExitProcess(1);
#else
@@ -1089,17 +1160,18 @@ void janet_line_init() {
}
void janet_line_deinit() {
int i;
norawmode();
for (i = 0; i < gbl_history_count; i++)
for (int i = 0; i < gbl_history_count; i++)
janet_free(gbl_history[i]);
gbl_historyi = 0;
if (gbl_history_file) janet_free(gbl_history_file);
}
void janet_line_get(const char *p, JanetBuffer *buffer) {
gbl_prompt = p;
buffer->count = 0;
gbl_historyi = 0;
loadhistory();
if (check_simpleline(buffer)) return;
FILE *out = janet_dynfile("err", stderr);
if (line()) {
@@ -1130,6 +1202,13 @@ static void clear_at_exit(void) {
* Entry
*/
static void cleanup_at_exit(void) {
/* Deinitialize vm */
savehistory();
janet_deinit();
janet_line_deinit();
}
int main(int argc, char **argv) {
int i, status;
JanetArray *args;
@@ -1146,6 +1225,7 @@ int main(int argc, char **argv) {
#if !defined(JANET_SIMPLE_GETLINE)
atexit(clear_at_exit);
#endif
atexit(cleanup_at_exit);
#if defined(JANET_PRF)
uint8_t hash_key[JANET_HASH_KEY_SIZE + 1];
@@ -1193,9 +1273,6 @@ int main(int argc, char **argv) {
/* Run the fiber in an event loop */
status = janet_loop_fiber(fiber);
/* Deinitialize vm */
janet_deinit();
janet_line_deinit();
/* Deinit moved to atexit */
return status;
}