|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
#include "db.h"
|
|
#include "utils.h"
|
|
#include "history.h"
|
|
#include "config.h"
|
|
#include "shell_integration.h"
|
|
#include "tui.h"
|
|
|
|
#define RHISTORY_VERSION "0.1.0"
|
|
|
|
// Command handlers
|
|
int cmd_search(int argc, char **argv);
|
|
int cmd_import(int argc, char **argv);
|
|
int cmd_list(int argc, char **argv);
|
|
int cmd_stats(int argc, char **argv);
|
|
int cmd_delete(int argc, char **argv);
|
|
int cmd_init(int argc, char **argv);
|
|
int cmd_config(int argc, char **argv);
|
|
int cmd_record(int argc, char **argv); // Internal
|
|
void print_help(void);
|
|
void print_version(void);
|
|
|
|
int main(int argc, char **argv) {
|
|
if (argc < 2) {
|
|
return cmd_search(argc, argv);
|
|
}
|
|
|
|
if (strcmp(argv[1], "search") == 0) {
|
|
return cmd_search(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "import") == 0) {
|
|
return cmd_import(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "list") == 0) {
|
|
return cmd_list(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "stats") == 0) {
|
|
return cmd_stats(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "delete") == 0) {
|
|
return cmd_delete(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "init") == 0) {
|
|
return cmd_init(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "config") == 0) {
|
|
return cmd_config(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "record") == 0) {
|
|
return cmd_record(argc - 1, argv + 1);
|
|
} else if (strcmp(argv[1], "help") == 0 || strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) {
|
|
print_help();
|
|
return 0;
|
|
} else if (strcmp(argv[1], "version") == 0 || strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-v") == 0) {
|
|
print_version();
|
|
return 0;
|
|
} else {
|
|
// Default to search if unknown command, or maybe print help?
|
|
// Prompt says "rhistory [OPTIONS] [COMMAND]".
|
|
// If it starts with -, it's options for search probably.
|
|
if (argv[1][0] == '-') {
|
|
return cmd_search(argc, argv);
|
|
}
|
|
fprintf(stderr, "Unknown command: %s\n", argv[1]);
|
|
print_help();
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
void print_help(void) {
|
|
printf("rhistory %s\n", RHISTORY_VERSION);
|
|
printf("Usage: rhistory [COMMAND] [OPTIONS]\n\n");
|
|
printf("Commands:\n");
|
|
printf(" search Search history (default)\n");
|
|
printf(" import Import history from shell file\n");
|
|
printf(" list List history entries\n");
|
|
printf(" stats Show statistics\n");
|
|
printf(" delete Delete entries\n");
|
|
printf(" init Generate shell integration code\n");
|
|
printf(" config Manage configuration\n");
|
|
printf(" help Show this help\n");
|
|
printf(" version Show version\n");
|
|
}
|
|
|
|
void print_version(void) {
|
|
printf("rhistory %s\n", RHISTORY_VERSION);
|
|
}
|
|
|
|
// Database Helper
|
|
bool setup_db(void) {
|
|
char *data_dir = get_data_dir();
|
|
if (!ensure_directory_exists(data_dir)) {
|
|
fprintf(stderr, "Failed to create data directory: %s\n", data_dir);
|
|
free(data_dir);
|
|
return false;
|
|
}
|
|
|
|
char *db_path = join_path(data_dir, "history.db");
|
|
bool success = db_init(db_path);
|
|
|
|
free(db_path);
|
|
free(data_dir);
|
|
return success;
|
|
}
|
|
|
|
// Stub implementations
|
|
#include "shell_integration.h"
|
|
#include "search.h"
|
|
#include <time.h>
|
|
|
|
// ...
|
|
|
|
int cmd_search(int argc, char **argv) {
|
|
if (!setup_db()) return 1;
|
|
|
|
SearchQuery query;
|
|
memset(&query, 0, sizeof(query));
|
|
query.exit_code = -1;
|
|
query.limit = 20;
|
|
|
|
static struct option long_options[] = {
|
|
{"interactive", no_argument, 0, 'i'},
|
|
{"exit", required_argument, 0, 'e'},
|
|
{"cwd", required_argument, 0, 'c'},
|
|
{"host", required_argument, 0, 'h'},
|
|
{"session", required_argument, 0, 's'},
|
|
{"limit", required_argument, 0, 'l'},
|
|
{"reverse", no_argument, 0, 'r'},
|
|
{"cmd-only", no_argument, 0, 1001},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
bool interactive = false;
|
|
bool cmd_only = false;
|
|
|
|
int opt_index = 0;
|
|
int c;
|
|
// Reset getopt
|
|
optind = 1;
|
|
|
|
while ((c = getopt_long(argc, argv, "ie:c:h:s:l:r", long_options, &opt_index)) != -1) {
|
|
switch (c) {
|
|
case 'i': interactive = true; break;
|
|
case 'e': query.exit_code = atoi(optarg); break;
|
|
case 'c': query.cwd = optarg; break;
|
|
case 'h': query.hostname = optarg; break;
|
|
case 's': query.session = optarg; break;
|
|
case 'l': query.limit = atoi(optarg); break;
|
|
case 'r': query.reverse = true; break;
|
|
case 1001: cmd_only = true; break;
|
|
}
|
|
}
|
|
|
|
if (optind < argc) {
|
|
query.query_string = argv[optind];
|
|
}
|
|
|
|
if (interactive) {
|
|
tui_start(&query);
|
|
} else {
|
|
SearchResult *res = search_perform(&query);
|
|
if (!res) {
|
|
fprintf(stderr, "Search failed.\n");
|
|
db_close();
|
|
return 1;
|
|
}
|
|
|
|
for (int i = 0; i < res->count; i++) {
|
|
HistoryEntry *e = res->entries[i];
|
|
if (cmd_only) {
|
|
printf("%s\n", e->command);
|
|
} else {
|
|
// Format timestamp
|
|
time_t t = (time_t)e->timestamp;
|
|
struct tm *tm = localtime(&t);
|
|
char time_str[64];
|
|
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm);
|
|
|
|
printf("%s | %s | %s | %dms | %s\n",
|
|
time_str, e->hostname, e->cwd, e->duration, e->command);
|
|
}
|
|
}
|
|
|
|
search_free_result(res);
|
|
}
|
|
|
|
db_close();
|
|
return 0;
|
|
}
|
|
|
|
int cmd_import(int argc, char **argv) {
|
|
if (!setup_db()) return 1;
|
|
|
|
const char *shell = "auto";
|
|
if (argc > 1) {
|
|
shell = argv[1];
|
|
}
|
|
|
|
history_import(shell);
|
|
|
|
db_close();
|
|
return 0;
|
|
}
|
|
|
|
int cmd_list(int argc, char **argv) {
|
|
if (!setup_db()) return 1;
|
|
printf("List command not implemented yet.\n");
|
|
db_close();
|
|
return 0;
|
|
}
|
|
|
|
int cmd_stats(int argc, char **argv) {
|
|
if (!setup_db()) return 1;
|
|
|
|
int limit = 10;
|
|
|
|
static struct option long_options[] = {
|
|
{"top", required_argument, 0, 't'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
int opt_index = 0;
|
|
int c;
|
|
optind = 1;
|
|
|
|
while ((c = getopt_long(argc, argv, "t:", long_options, &opt_index)) != -1) {
|
|
switch (c) {
|
|
case 't': limit = atoi(optarg); break;
|
|
}
|
|
}
|
|
|
|
history_stats(limit);
|
|
|
|
db_close();
|
|
return 0;
|
|
}
|
|
|
|
int cmd_delete(int argc, char **argv) {
|
|
if (!setup_db()) return 1;
|
|
printf("Delete command not implemented yet.\n");
|
|
db_close();
|
|
return 0;
|
|
}
|
|
|
|
#include "shell_integration.h"
|
|
|
|
// ... (other includes)
|
|
|
|
int cmd_init(int argc, char **argv) {
|
|
if (argc > 1) {
|
|
if (!shell_integration_init(argv[1])) {
|
|
fprintf(stderr, "Unsupported shell: %s. Supported: bash, zsh, fish\n", argv[1]);
|
|
return 1;
|
|
}
|
|
} else {
|
|
printf("Usage: rhistory init [bash|zsh|fish]\n");
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int cmd_config(int argc, char **argv) {
|
|
printf("Config command not implemented yet.\n");
|
|
return 0;
|
|
}
|
|
|
|
int cmd_record(int argc, char **argv) {
|
|
if (!setup_db()) return 1;
|
|
|
|
char *command = NULL;
|
|
char *cwd = NULL;
|
|
int exit_code = 0;
|
|
int duration = 0;
|
|
char *hostname = NULL;
|
|
char *session = NULL;
|
|
char *shell = NULL;
|
|
|
|
static struct option long_options[] = {
|
|
{"command", required_argument, 0, 'c'},
|
|
{"cwd", required_argument, 0, 'w'},
|
|
{"exit-code", required_argument, 0, 'e'},
|
|
{"duration", required_argument, 0, 'd'},
|
|
{"hostname", required_argument, 0, 'H'},
|
|
{"session", required_argument, 0, 's'},
|
|
{"shell", required_argument, 0, 'S'},
|
|
{0, 0, 0, 0}
|
|
};
|
|
|
|
int opt_index = 0;
|
|
int c;
|
|
while ((c = getopt_long(argc, argv, "", long_options, &opt_index)) != -1) {
|
|
switch (c) {
|
|
case 'c': command = optarg; break;
|
|
case 'w': cwd = optarg; break;
|
|
case 'e': exit_code = atoi(optarg); break;
|
|
case 'd': duration = atoi(optarg); break;
|
|
case 'H': hostname = optarg; break;
|
|
case 's': session = optarg; break;
|
|
case 'S': shell = optarg; break;
|
|
}
|
|
}
|
|
|
|
if (command && cwd) {
|
|
history_record(command, cwd, exit_code, duration, hostname, session, shell);
|
|
}
|
|
|
|
db_close();
|
|
return 0;
|
|
}
|