Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions cli/complete.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,33 @@
#define FLAG(flags, help) with_help(help, EC_NODE_CMD(EC_NO_ID, flags))
#define OPT(opts, help, ...) with_help(help, EC_NODE_CMD(EC_NO_ID, opts, __VA_ARGS__))

struct ec_node *grcli_options_node(void) {
return EC_NODE_SUBSET(
EC_NO_ID,
FLAG("-h|--help", "Show usage help and exit."),
OPT("-s|--socket " SOCK_PATH_ID,
"Path to the control plane API socket.",
ec_node("file", SOCK_PATH_ID)),
FLAG("-e|--err-exit", "Abort on first error."),
FLAG("-x|--trace-commands", "Print executed commands."),
OPT("-f|--file PATH",
"Read commands from _PATH_ instead of standard input.",
ec_node("file", "PATH")),
FLAG("-V|--version", "Print version and exit."),
FLAG("-c|--bash-complete", "For use in bash completion."),
OPT("-m|--man COMMAND",
"Show man page for _COMMAND_ or list all commands if no argument.",
ec_node("str", "COMMAND"))
);
}

static struct ec_node *bash_complete_node(struct ec_node *cmdlist) {
return ec_node_sh_lex_expand(
EC_NO_ID,
EC_NODE_SEQ(
EC_NO_ID,
ec_node("any", "prog_name"),
ec_node_option(
EC_NO_ID,
EC_NODE_SUBSET(
EC_NO_ID,
FLAG("-h|--help", "Show usage help and exit."),
OPT("-s|--socket " SOCK_PATH_ID,
"Path to the control plane API socket.",
ec_node("file", SOCK_PATH_ID)),
FLAG("-e|--err-exit", "Abort on first error."),
FLAG("-x|--trace-commands", "Print executed commands.")
)
),
ec_node_option(EC_NO_ID, grcli_options_node()),
cmdlist
)
);
Expand Down
1 change: 1 addition & 0 deletions cli/complete.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
#include <ecoli.h>

int bash_complete(struct ec_node *cmdlist);
struct ec_node *grcli_options_node(void);
2 changes: 0 additions & 2 deletions cli/ecoli.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
#include <errno.h>
#include <stdarg.h>

#define HELP_ATTR "help"

struct ec_node *with_help(const char *help, struct ec_node *node) {
if (node == NULL)
return NULL;
Expand Down
1 change: 1 addition & 0 deletions cli/gr_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,5 @@ typedef int (*ec_node_dyn_comp_t)(
struct ec_node *ec_node_dyn(const char *id, ec_node_dyn_comp_t cb, void *cb_arg);

#define CLIENT_ATTR "gr_api_client"
#define HELP_ATTR "help"
#define SOCK_PATH_ID "gr_api_sock_path"
23 changes: 21 additions & 2 deletions cli/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "exec.h"
#include "interact.h"
#include "log.h"
#include "man.h"

#include <gr_api.h>
#include <gr_api_client_impl.h>
Expand All @@ -27,6 +28,7 @@
static void usage(const char *prog) {
printf("Usage: %s [-e] [-f PATH] [-h] [-s PATH] [-V] [-x] ...\n", prog);
printf(" %s -c|--bash-complete\n", prog);
printf(" %s -m|--man [COMMAND]\n", prog);
}

static void help(void) {
Expand All @@ -37,6 +39,8 @@ static void help(void) {
puts(" -e, --err-exit Abort on first error.");
puts(" -f PATH, --file PATH Read commands from file instead of stdin.");
puts(" -h, --help Show this help message and exit.");
puts(" -m, --man [COMMAND] Show man page for command or list all");
puts(" commands.");
puts(" -s PATH, --socket PATH Path to the control plane API socket.");
puts(" Default: GROUT_SOCK_PATH from env or");
printf(" %s).\n", GR_DEFAULT_SOCK_PATH);
Expand Down Expand Up @@ -171,8 +175,23 @@ int main(int argc, char **argv) {
if ((cmdlist = init_commands()) == NULL)
goto end;

if (argc >= 2 && (!strcmp(argv[1], "-c") || !strcmp(argv[1], "--bash-complete")))
return bash_complete(cmdlist);
if (argc >= 2 && (!strcmp(argv[1], "-c") || !strcmp(argv[1], "--bash-complete"))) {
ret = bash_complete(cmdlist);
goto end;
}

if (argc >= 2 && (!strcmp(argv[1], "-m") || !strcmp(argv[1], "--man"))) {
if (argc == 2)
ret = print_main_man_page(cmdlist);
else if (argc == 3)
ret = print_man_page(cmdlist, argv);
else {
fprintf(stderr, "Error: --man takes at most one argument\n");
usage(argv[0]);
ret = EXIT_FAILURE;
}
goto end;
}

if ((c = parse_args(argc, argv)) < 0)
goto end;
Expand Down
27 changes: 27 additions & 0 deletions cli/man.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2025 Abhiram R N

#pragma once

#include <ecoli.h>

enum ec_node_type_enum {
NODE_TYPE_STR,
NODE_TYPE_UINT,
NODE_TYPE_INT,
NODE_TYPE_DYN,
NODE_TYPE_RE,
NODE_TYPE_OR,
NODE_TYPE_SEQ,
NODE_TYPE_CMD,
NODE_TYPE_OPTION,
NODE_TYPE_MANY,
NODE_TYPE_SUBSET,
NODE_TYPE_UNKNOWN
};

enum ec_node_type_enum get_node_type(const struct ec_node *node);

int print_man_page(struct ec_node *cmdlist, char **argv);
int print_main_man_page(struct ec_node *cmdlist);
void man_print_title_underline(const char *title);
Loading