proper argument parsing

This commit is contained in:
anon 2024-08-04 14:38:58 +02:00
parent f6500e6d79
commit a959df320f
7 changed files with 101 additions and 59 deletions

View File

@ -14,7 +14,7 @@ LINKasd += $$(pkgconf --libs ncurses readline sqlite3)
OBJECT.d:=object/
SOURCE.d:=source/
SOURCE:=bash_history.yy.cpp main.cpp cli.cpp tui.cpp storage.cpp damerau_levenshtein.cpp
SOURCE:=argument_yy.tab.cpp bash_history.yy.cpp main.cpp cli.cpp tui.cpp storage.cpp damerau_levenshtein.cpp
OBJECT:=$(addprefix ${OBJECT.d},$(addsuffix .o,$(basename ${SOURCE})))
SOURCE:=$(addprefix ${SOURCE.d},${SOURCE})
@ -24,7 +24,10 @@ ${OUTPUT}: ${OBJECT}
${LINK.cpp} ${OBJECT} ${LINKasd} -o ${OUTPUT}
object/%.yy.cpp: source/%.l
${LEX} --prefix=$*_ --header-file=$(basename $@).hpp -o $@ $<
flex --prefix=$*_ --header-file=$(basename $@).hpp -o $@ $<
object/%.tab.cpp: source/%.y
bison --name-prefix=$*_ --header=$(basename $@).hpp -o $@ $<
object/%.o: object/%.l.cpp
${COMPILE.cpp} $< -o $@

View File

@ -1,3 +1,4 @@
+ make case insensitive search optional
+ make fuzzy searching optional
+ make (potentially slow) queries cancel using multi threading
+ the same suggestion should only show up once

29
source/argument_yy.y Normal file
View File

@ -0,0 +1,29 @@
%token HELP VERSION
%token TUI ENABLE
%token LEVENSTEIN
%{
#include "stdio.h"
extern void usage(void);
extern void version(void);
extern void enable(void);
extern void argument_yy_error(const char * const s);
extern int argument_yy_lex(void);
%}
%%
histui_args: global_args verb_and_args
;
global_args: %empty
| HELP { usage(); exit(0); }
| VERSION { version(); exit(0); }
;
verb_and_args: ENABLE { enable(); exit(0); }
| TUI tui_args { ; }
;
tui_args: %empty
| LEVENSTEIN { ; }
;
%%

View File

@ -4,19 +4,17 @@
#include <stdlib.h>
#include <string.h>
using namespace std;
#include "argument_yy.tab.hpp"
int * arg_tokens;
[[ noreturn ]]
void version() {
puts(
# include "version.inc"
);
exit(0);
}
[[ noreturn ]]
void usage(int exit_value) {
void usage(void) {
// TODO
puts(
"histui [options] <verb>\n"
@ -27,37 +25,56 @@ void usage(int exit_value) {
"\t\tenable : print a bash script to enable histui in the current shell\n"
"\t\ttui : run histui normally\n"
);
exit(exit_value);
}
void parse_global_options(const int argc, const char * const * const argv) {
for(int i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
return;
}
if (not strcmp(argv[i], "-v")
|| not strcmp(argv[i], "--version")) {
version();
}
if (not strcmp(argv[i], "-h")
|| not strcmp(argv[i], "--help")) {
usage();
}
}
int argument_yy_lex(void) {
static int i = 0;
return arg_tokens[i++];
}
verb_t get_verb(const int argc, const char * const * const argv) {
for(int i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
continue;
}
if (not strcmp(argv[i], "tui")) {
return TUI;
}
if (not strcmp(argv[i], "enable")) {
return ENABLE;
}
return ERROR;
}
return ERROR;
void argument_yy_error([[ maybe_unused ]] const char * const s) {
puts("Argument parsing failed.");
usage();
exit(2);
}
void parse_arguments(const int argc, const char * const * const argv) {
if (argc < 2) {
usage();
exit(1);
}
/* Lexical analysis of a poor man.
* Using Flex would be problematic because our input
* is not stored in an actual buffer (not in a defined
* behaviour way anyways).
*/
int tokens[argc];
int token_empty_head = 0;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--help")
|| !strcmp(argv[i], "-h")) {
tokens[token_empty_head++] = HELP;
} else
if (!strcmp(argv[i], "--version")
|| !strcmp(argv[i], "-v")) {
tokens[token_empty_head++] = VERSION;
} else
if (!strcmp(argv[i], "tui")) {
tokens[token_empty_head++] = TUI;
} else
if (!strcmp(argv[i], "enable")) {
tokens[token_empty_head++] = ENABLE;
} else
if (!strcmp(argv[i], "--levenstein")) {
tokens[token_empty_head++] = LEVENSTEIN;
} else {
tokens[token_empty_head++] = YYUNDEF;
}
}
tokens[token_empty_head++] = YYEOF;
arg_tokens = tokens;
argument_yy_parse();
}

View File

@ -1,11 +1,3 @@
#pragma once
typedef enum {
TUI,
ENABLE,
ERROR,
} verb_t;
extern void parse_global_options(const int argc, const char * const * const argv);
extern verb_t get_verb(const int argc, const char * const * const argv);
[[ noreturn ]] void usage(int exit_value = 0);
void parse_arguments(const int argc, const char * const * const argv);

View File

@ -40,17 +40,19 @@ bind -x '"\e[A": _histui_run'
bind -x '"\C-r": _histui_run'
)delim"
);
exit(0);
}
void export_result(const char * const result) {
int fd[2];
pipe(fd);
dprintf(3, result);
close(fd[0]);
close(fd[1]);
}
signed main(int argc, char * argv[]) {
parse_global_options(argc, argv);
verb_t verb = get_verb(argc, argv);
switch (verb) {
case ENABLE: enable();
case ERROR: usage(1);
case TUI: break;
}
// NOTE: never returns on error
parse_arguments(argc, argv);
init();
@ -72,11 +74,7 @@ signed main(int argc, char * argv[]) {
}
query(rl_line_buffer, 1, selection_offset + selection_relative);
int fd[2];
pipe(fd);
dprintf(3, get_entry().command);
close(fd[0]);
close(fd[1]);
export_result(get_entry().command);
deinit();

View File

@ -4,6 +4,8 @@
#include <sqlite3.h>
#include "damerau_levenshtein.hpp"
//const char * * const query_method;
static sqlite3 * db;
static sqlite3_stmt * stmt = NULL;