diff options
| author | lonkaars <loek@pipeframe.xyz> | 2024-05-24 15:18:44 +0200 | 
|---|---|---|
| committer | lonkaars <loek@pipeframe.xyz> | 2024-05-24 15:18:44 +0200 | 
| commit | 31c30df2a24a45c69a7c5c2f594fa3a9a835b1fb (patch) | |
| tree | 59d86bac0175a2f6001d0a54aa8f42e43b27d474 /client | |
| parent | b74efcf6c6badcc7dc1937d511a163108f9fac0f (diff) | |
add tab completion + help function
Diffstat (limited to 'client')
| -rw-r--r-- | client/cmd.cpp | 17 | ||||
| -rw-r--r-- | client/cmd.h | 45 | ||||
| -rw-r--r-- | client/rl.cpp | 20 | 
3 files changed, 77 insertions, 5 deletions
| diff --git a/client/cmd.cpp b/client/cmd.cpp index 99a4dd6..0a73dad 100644 --- a/client/cmd.cpp +++ b/client/cmd.cpp @@ -1,3 +1,4 @@ +#include <cstdio>  #include <cstdlib>  #include <string.h> @@ -13,3 +14,19 @@ void cmd_test(char*) {  	i2c_send(0x39, (char*) data, strlen(data));  } +void cmd_help(char*) { +  printf("List of available commands:\n"); +  for (size_t i = 0; i < cmds_length; i++) { +    struct cmd cmd = cmds[i]; +    printf("  %-*s", 10, cmd.name); +    if (cmd.info != NULL) +      printf("  %s", cmd.info); +    printf("\n"); +  } + +  printf( +    "\n" +    "You can also use the TAB key to autocomplete commands\n" +  ); +} + diff --git a/client/cmd.h b/client/cmd.h index 509104a..7ec67fc 100644 --- a/client/cmd.h +++ b/client/cmd.h @@ -5,19 +5,56 @@  typedef void cmd_fn_t(char *);  struct cmd { -	const char* name;  	void (* handle)(char *); +	const char* name;  	const char* info;  	// TODO: tab completion function?  };  cmd_fn_t cmd_exit;  cmd_fn_t cmd_test; +cmd_fn_t cmd_help; +cmd_fn_t cmd_send; +cmd_fn_t cmd_status; +cmd_fn_t cmd_reset; +cmd_fn_t cmd_ls;  static const struct cmd cmds[] = { -	(struct cmd){ .name = "exit", .handle = cmd_exit, .info = NULL, }, -	(struct cmd){ .name = "test", .handle = cmd_test, .info = NULL, }, +	{ +		.handle = cmd_exit, +		.name = "exit", +		.info = "exit pbc", +	}, +	{ +		.handle = cmd_test, +		.name = "test", +		.info = "send a test puzbus message", +	}, +	{ +		.handle = cmd_help, +		.name = "help", +		.info = "show this help", +	}, +	// { +	// 	.handle = cmd_send, +	// 	.name = "send", +	// 	.info = "[debug] send raw message", +	// }, +	// { +	// 	.handle = cmd_status, +	// 	.name = "status", +	// 	.info = "show global puzzle box state (main controller state)", +	// }, +	// { +	// 	.handle = cmd_reset, +	// 	.name = "reset", +	// 	.info = "reset entire game state", +	// }, +	// { +	// 	.handle = cmd_ls, +	// 	.name = "ls", +	// 	.info = "list connected puzzle modules", +	// },  }; -  static const size_t cmds_length = sizeof(cmds) / sizeof(cmds[0]); diff --git a/client/rl.cpp b/client/rl.cpp index b016370..6073500 100644 --- a/client/rl.cpp +++ b/client/rl.cpp @@ -37,16 +37,34 @@ void rl_printf(const char *fmt, ...) {  }  static bool cli_cmd(char* line) { +  char* cmd = strtok(line, " \t\n");  	for (size_t i = 0; i < cmds_length; i++) { -		if (strcmp(line, cmds[i].name) != 0) continue; +		if (strncmp(cmds[i].name, cmd, strlen(cmd)) != 0) continue;  		cmds[i].handle(line);  		return true;  	}  	return false;  } +static char* rl_completion_entries(const char *text, int state) { +  static size_t i = 0; +  if (state == 0) i = 0; + +  while (i < cmds_length) { +    struct cmd cmd = cmds[i]; +    i++; +    if (strncmp(text, cmd.name, strlen(text)) == 0) { +      return strdup(cmd.name); +    } +  } + +  return NULL; +} +  int cli_main() {  	char* input = NULL; +  rl_completion_entry_function = rl_completion_entries; +  	while (1) {  		if (input != NULL) free(input);  		input = readline(CLI_PROMPT); |