sorm/cli.h

168 lines
4.3 KiB
C
Raw Permalink Normal View History

2024-11-22 13:45:03 +00:00
#ifndef SORM_CLI_H
#define SORM_CLI_H
2024-11-22 14:51:47 +00:00
#include "sorm.h"
#include <fcntl.h>
#include <readline/history.h>
#include <readline/readline.h>
#include <rlib.h>
2024-11-22 13:45:03 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
2024-11-22 14:51:47 +00:00
#include <unistd.h>
2024-11-22 13:45:03 +00:00
2024-11-22 14:51:47 +00:00
const char *history_filename = ".sorm_history";
2024-11-22 13:45:03 +00:00
2024-11-22 14:51:47 +00:00
int _sorm_readline_accept_line(int count, int key) {
2024-11-22 13:45:03 +00:00
if (strchr(rl_line_buffer, ';')) {
2024-11-22 14:51:47 +00:00
rl_done = 1;
2024-11-22 13:45:03 +00:00
return 0;
}
rl_insert_text("\n");
return 0;
}
2024-11-22 14:51:47 +00:00
char *_sorm_autocompletion_generator(const char *text, int state) {
const char *completions[] = {"exit", sorm_last_query, sorm_last_query_expanded, "python", "history", "memory", "truncate", NULL};
int list_index;
2024-11-22 13:45:03 +00:00
if (!state) {
list_index = 0;
}
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
while (completions[list_index] != NULL) {
if (strncmp(completions[list_index], text, strlen(text)) == 0) {
return strdup(completions[list_index++]);
}
list_index++;
}
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
return NULL;
}
2024-11-22 14:51:47 +00:00
char **_sorm_autocomplete(const char *text, int start, int end) {
2024-11-22 13:45:03 +00:00
rl_attempted_completion_over = 1;
return rl_completion_matches(text, _sorm_autocompletion_generator);
}
2024-11-22 14:51:47 +00:00
int _hs_read_file(const char *filename, char *buffer, size_t size) {
2024-11-22 13:45:03 +00:00
int fd;
ssize_t bytes_read;
2024-11-22 14:51:47 +00:00
fd = open(filename, O_RDONLY);
2024-11-22 13:45:03 +00:00
if (fd < 0)
return -1;
2024-11-22 14:51:47 +00:00
bytes_read = read(fd, buffer, size);
close(fd);
2024-11-22 13:45:03 +00:00
if (bytes_read < 0 || (size_t)bytes_read != size)
return -1;
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
return 0;
}
2024-11-22 14:51:47 +00:00
int sorm_cli_history_dump(const char *filename) {
2024-11-22 13:45:03 +00:00
register int line_start, line_end;
char *input;
struct stat finfo;
size_t file_size;
2024-11-22 14:51:47 +00:00
if (stat(filename, &finfo) < 0)
2024-11-22 13:45:03 +00:00
return -1;
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
file_size = (size_t)finfo.st_size;
2024-11-22 14:51:47 +00:00
input = (char *)malloc(file_size + 1);
2024-11-22 13:45:03 +00:00
if (!input)
return -1;
2024-11-22 14:51:47 +00:00
if (_hs_read_file(filename, input, file_size) < 0) {
free(input);
2024-11-22 13:45:03 +00:00
return -1;
}
input[file_size] = '\0';
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
for (line_start = line_end = 0; line_end < file_size; line_end++) {
if (input[line_end] == '\n') {
input[line_end] = '\0';
2024-11-22 14:51:47 +00:00
printf("%s\n", input + line_start);
2024-11-22 13:45:03 +00:00
line_start = line_end + 1;
}
}
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
if (line_start < file_size)
2024-11-22 14:51:47 +00:00
printf("%s\n", input + line_start);
free(input);
return where_history();
2024-11-22 13:45:03 +00:00
}
2024-11-22 14:51:47 +00:00
char sorm_history_filename[4096];
2024-11-22 13:45:03 +00:00
2024-11-22 14:51:47 +00:00
void sorm_cli_init(const char *history_filename) {
2024-11-22 13:45:03 +00:00
strcpy(sorm_history_filename, history_filename);
2024-11-22 14:51:47 +00:00
rl_bind_key('\n', NULL);
2024-11-22 13:45:03 +00:00
rl_bind_key('\r', NULL);
rl_add_defun("custom-accept-line", _sorm_readline_accept_line, '\n');
rl_add_defun("custom-accept-line-cr", _sorm_readline_accept_line, '\r');
rl_variable_bind("enable-bracketed-paste", "on");
rl_attempted_completion_function = _sorm_autocomplete;
rl_variable_bind("show-all-if-ambiguous", "on");
rl_variable_bind("menu-complete-display-prefix", "on");
2024-11-22 14:51:47 +00:00
2024-11-22 13:45:03 +00:00
using_history();
2024-11-22 14:51:47 +00:00
read_history(sorm_history_filename);
2024-11-22 13:45:03 +00:00
}
char sorm_cli_previous_command[sizeof(rl_line_buffer)];
2024-11-22 14:51:47 +00:00
char *sorm_cli_readline(char *prompt) {
char *result = readline(prompt);
if (strcmp(rl_line_buffer, sorm_cli_previous_command)) {
add_history((const char *)result);
write_history(sorm_history_filename);
}
strcpy(sorm_cli_previous_command, rl_line_buffer);
2024-11-22 13:45:03 +00:00
2024-11-22 14:51:47 +00:00
return result;
}
2024-11-22 13:45:03 +00:00
2024-11-22 14:51:47 +00:00
bool sormrepl_handle_command(char *command) {
if (!strncmp(command, "history", 7)) {
sorm_cli_history_dump(history_filename);
return true;
}
2024-11-22 13:45:03 +00:00
return false;
}
2024-11-22 14:51:47 +00:00
void sormrepl(int sorm) {
sorm_t *db = sormg(sorm);
2024-11-22 13:45:03 +00:00
char sql[4097];
sorm_cli_init(history_filename);
2024-11-22 14:51:47 +00:00
char *query;
while ((query = sorm_cli_readline("sql> "))) {
if (sormrepl_handle_command(query))
2024-11-22 13:45:03 +00:00
continue;
2024-11-22 14:51:47 +00:00
sorm_ptr res = sormq(sorm, query);
if (res) {
if (sormqt(query) == SORM_SELECT) {
int length = sormlv(res);
sormfmtd(res);
free(res);
} else if (sormqt(query) == SORM_DELETE) {
printf("%d records affected.\n", res);
} else if (sormqt(query) == SORM_INSERT) {
printf("Last insert id: %d.\n", res);
2024-11-22 13:45:03 +00:00
}
}
2024-11-22 14:51:47 +00:00
printf("Rows: %lld, Execute %s, Format: %s\n", sorm_row_count, format_time(_sorm_query_duration),
format_time(_sorm_result_format_duration));
printf("%s\n", rmalloc_stats());
}
2024-11-22 13:45:03 +00:00
}
#endif