This commit is contained in:
anon 2024-08-18 15:52:10 +02:00
parent 8e6f183116
commit bc107d59a7
5 changed files with 83 additions and 48 deletions

@ -1,12 +1,16 @@
%token HELP VERSION EXECUTE
%token TUI ENABLE
%token FUZZY CASELESS GROUP
%token FUZZY CASELESS GROUP INPUT
%{
#include <stdlib.h>
#include "cli.h"
#include "tui.h"
#include "storage.h"
extern bool do_execute;
extern bool is_expecting_argument;
%}
%union { const char * strval; }
%token<strval> ARGUMENT
%%
histui_args: global_args verb_and_args
;
@ -25,6 +29,8 @@ tui_args: %empty
| FUZZY tui_args { is_fuzzy = true; }
| CASELESS tui_args { is_caseless = true; }
| GROUP tui_args { is_grouped = true; }
| input ARGUMENT tui_args { initial_text = $2; }
;
input: INPUT { is_expecting_argument = true; }
%%

@ -6,7 +6,11 @@
#include "argument_yy.tab.h"
int * arg_tokens;
bool is_expecting_argument = false;
static int yy_argc;
static const char * const * yy_argv;
static int yy_i;
void version() {
puts(
@ -41,7 +45,7 @@ void enable(void) {
" if ! [ -v HISTUICMD ]; then\n"
" HISTUICMD=\"histui tui\"\n"
" fi\n"
" HISTFILE=$HISTFILE ${HISTUICMD} 3> \"${COMMANDFILE}\"\n"
" HISTFILE=$HISTFILE ${HISTUICMD} --input \"${READLINE_LINE}\" 3> \"${COMMANDFILE}\"\n"
" READLINE_LINE=$(cat \"${COMMANDFILE}\")\n"
" READLINE_POINT=${#READLINE_LINE}\n"
"}\n"
@ -51,9 +55,54 @@ void enable(void) {
);
}
/* 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).
*/
#define YIELD(v) ++yy_i; return v
int argument_yy_lex(void) {
static int i = 0;
return arg_tokens[i++];
for (; yy_i < yy_argc;) {
if (is_expecting_argument) {
is_expecting_argument = false;
argument_yy_lval.strval = yy_argv[yy_i];
YIELD(ARGUMENT);
}
if (!strcmp(yy_argv[yy_i], "--help")
|| !strcmp(yy_argv[yy_i], "-h")) {
YIELD(HELP);
} else
if (!strcmp(yy_argv[yy_i], "--version")
|| !strcmp(yy_argv[yy_i], "-v")) {
YIELD(VERSION);
} else
if (!strcmp(yy_argv[yy_i], "tui")) {
YIELD(TUI);
} else
if (!strcmp(yy_argv[yy_i], "enable")) {
YIELD(ENABLE);
} else
if (!strcmp(yy_argv[yy_i], "--execute")) {
YIELD(EXECUTE);
} else
if (!strcmp(yy_argv[yy_i], "--fuzzy")) {
YIELD(FUZZY);
} else
if (!strcmp(yy_argv[yy_i], "--caseless")) {
YIELD(CASELESS);
} else
if (!strcmp(yy_argv[yy_i], "--group")) {
YIELD(GROUP);
} else
if (!strcmp(yy_argv[yy_i], "--input")) {
YIELD(INPUT);
} else {
YIELD(YYUNDEF);
}
}
YIELD(YYEOF);
}
void argument_yy_error([[ maybe_unused ]] const char * const s) {
@ -63,51 +112,17 @@ void argument_yy_error([[ maybe_unused ]] const char * const s) {
}
void parse_arguments(const int argc, const char * const * const argv) {
#if 0
argument_yy_debug = 1;
#endif
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], "--execute")) {
tokens[token_empty_head++] = EXECUTE;
} else
if (!strcmp(argv[i], "--fuzzy")) {
tokens[token_empty_head++] = FUZZY;
} else
if (!strcmp(argv[i], "--caseless")) {
tokens[token_empty_head++] = CASELESS;
} else
if (!strcmp(argv[i], "--group")) {
tokens[token_empty_head++] = GROUP;
} else {
tokens[token_empty_head++] = YYUNDEF;
}
}
tokens[token_empty_head++] = YYEOF;
arg_tokens = tokens;
yy_argc = argc - 1;
yy_argv = argv + 1;
argument_yy_parse();
}

@ -92,7 +92,7 @@ signed main(const int argc, const char * const * const argv) {
do_redisplay = false;
if (is_input_changed) {
is_input_changed = false;
query(rl_line_buffer, entry_lines, selection_offset);
query(get_input_line(), entry_lines, selection_offset);
} else {
requery();
}
@ -106,7 +106,7 @@ signed main(const int argc, const char * const * const argv) {
}
pthread_join(query_thread, NULL);
query(rl_line_buffer, 1, selection_offset + selection_relative);
query(get_input_line(), 1, selection_offset + selection_relative);
export_result(get_entry().command);
deinit();

@ -8,6 +8,17 @@
extern bool do_execute;
/* I fucking hate readline.
* Apparently the only way to set an initial value is using a hook.
* What makes this extra painful is that readline cannot be explicitly
* initialized nor is it documented clearly that shit will segfault
* otherwise.
* If I ever find out what is a sensible alternative im ditching it forever.
*/
const char * initial_text;
const char * get_input_line(void) { return rl_line_buffer; }
/* "Cursor" position; the entry selected by the user
*/
size_t selection_relative = 0;
@ -71,8 +82,10 @@ int init_tui(void) {
int getc_function([[maybe_unused]] FILE* ignore) { input_available = false; return (int)(input); }
int return_input_available(void) { return input_available; }
int initializer(void) { rl_insert_text(initial_text); return 0; }
rl_getc_function = getc_function;
rl_input_available_hook = return_input_available;
rl_startup_hook = initializer;
/* Due to this bug: https://mail.gnu.org/archive/html/bug-readline/2013-09/msg00021.html ;
* we cannot null this function.
* Im seriously questioning why readline is still the """default""" library in the wild

@ -4,7 +4,8 @@
#include <stddef.h>
#include "entry.h"
extern char * rl_line_buffer;
extern const char * initial_text;
extern const char * get_input_line(void);
extern size_t entry_lines;
extern size_t selection_offset;