#ifndef SORM_CLI_H
#define SORM_CLI_H
#include <rlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <readline/readline.h>
#include <readline/history.h>
#include "sorm.h"
const char * history_filename = ".sorm_history";
int _sorm_readline_accept_line(int count, int key) {
if (strchr(rl_line_buffer, ';')) {
rl_done = 1;
return 0;
}
rl_insert_text("\n");
return 0;
}
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;
if (!state) {
list_index = 0;
}
while (completions[list_index] != NULL) {
if (strncmp(completions[list_index], text, strlen(text)) == 0) {
return strdup(completions[list_index++]);
}
list_index++;
}
return NULL;
}
char** _sorm_autocomplete(const char* text, int start, int end) {
rl_attempted_completion_over = 1;
return rl_completion_matches(text, _sorm_autocompletion_generator);
}
int
_hs_read_file (const char *filename, char *buffer, size_t size)
{
int fd;
ssize_t bytes_read;
fd = open (filename, O_RDONLY);
if (fd < 0)
return -1;
bytes_read = read (fd, buffer, size);
close (fd);
if (bytes_read < 0 || (size_t)bytes_read != size)
return -1;
return 0;
}
int
sorm_cli_history_dump (const char *filename)
{
register int line_start, line_end;
char *input;
struct stat finfo;
size_t file_size;
if (stat (filename, &finfo) < 0)
return -1;
file_size = (size_t)finfo.st_size;
input = (char *)malloc (file_size + 1);
if (!input)
return -1;
if (_hs_read_file (filename, input, file_size) < 0) {
free (input);
return -1;
}
input[file_size] = '\0';
for (line_start = line_end = 0; line_end < file_size; line_end++) {
if (input[line_end] == '\n') {
input[line_end] = '\0';
printf ("%s\n",input + line_start);
line_start = line_end + 1;
}
}
if (line_start < file_size)
printf ("%s\n",input + line_start);
free (input);
return where_history ();
}
char sorm_history_filename[4096];
void sorm_cli_init(const char * history_filename){
strcpy(sorm_history_filename, history_filename);
rl_bind_key('\n',NULL);
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");
using_history();
read_history(sorm_history_filename);
}
char sorm_cli_previous_command[sizeof(rl_line_buffer)];
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);
return result;
}
bool sormrepl_handle_command(char * command){
if(!strncmp(command, "history",7)){
sorm_cli_history_dump(history_filename);
return true;
}
return false;
}
void sormrepl(int sorm){
sorm_t * db = sormg(sorm);
char sql[4097];
sorm_cli_init(history_filename);
char * query;
while((query = sorm_cli_readline("sql> "))){
if(sormrepl_handle_command(query))
continue;
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);
}
}
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());
}
}
#endif