dep

Package manager for embedded C libraries
git clone git://git.finwo.net/app/dep
Log | Files | Refs | README | LICENSE

commit 2c336985c79c2f60711f42ba902932a992da59b8
parent 3d3644c0cbcf34731bd9dd8076f377eb7ece5a74
Author: finwo <finwo@pm.me>
Date:   Sat, 14 Mar 2026 03:27:03 +0100

Restructure help

Diffstat:
Msrc/command/add/main.c | 25++++++++++++++++++++++++-
Msrc/command/command.h | 3+++
Asrc/command/help/main.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/command/init/main.c | 18+++++++++++++++++-
Msrc/command/install/main.c | 19++++++++++++++++++-
Msrc/command/license/main.c | 12+++++++++++-
Msrc/command/repository/main.c | 28+++++++++++++++++++++++++++-
Msrc/main.c | 62++++++++++++++++++++++++++------------------------------------
8 files changed, 222 insertions(+), 41 deletions(-)

diff --git a/src/command/add/main.c b/src/command/add/main.c @@ -393,5 +393,28 @@ void __attribute__((constructor)) cmd_add_setup(void) { cmd->fn = cmd_add; static const char *add_names[] = {"add", "a", NULL}; cmd->name = add_names; - commands = cmd; + cmd->display = "a(dd)"; + cmd->description = "Add a new dependency to the project"; + cmd->help_text = + "dep add - Add a new dependency to the project\n" + "\n" + "Usage:\n" + " dep add <name>\n" + " dep add <name> <version>\n" + " dep add <name> <url>\n" + "\n" + "Description:\n" + " Add a package to the project's .dep file.\n" + "\n" + " If a version is not specified, the latest version from the repository\n" + " will be used, or the default branch from GitHub.\n" + "\n" + " You can also add a dependency with a direct URL.\n" + "\n" + "Examples:\n" + " dep add finwo/palloc # Latest from repo or GitHub main branch\n" + " dep add finwo/palloc edge # Specific version/branch\n" + " dep add finwo/palloc v1.0.0 # Specific tag\n" + " dep add mylib https://example.com/mylib.tar.gz\n"; + commands = cmd; } diff --git a/src/command/command.h b/src/command/command.h @@ -1,6 +1,9 @@ struct cmd_struct { void *next; const char **name; + const char *display; + const char *description; + const char *help_text; int (*fn)(int, const char **); }; diff --git a/src/command/help/main.c b/src/command/help/main.c @@ -0,0 +1,96 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "command/command.h" + +static void print_global_help(void) { + printf("Usage: dep [global options] <command> [command options]\n"); + printf("\n"); + printf("Global options:\n"); + printf(" n/a\n"); + printf("\n"); + printf("Commands:\n"); + + struct cmd_struct *cmd = commands; + while (cmd) { + printf(" %-16s %s\n", cmd->display ? cmd->display : cmd->name[0], cmd->description ? cmd->description : ""); + cmd = cmd->next; + } + + printf("\n"); + printf("Help topics:\n"); + printf(" global This help text\n"); + + cmd = commands; + while (cmd) { + printf(" %-16s More detailed explanation on the %s command\n", cmd->name[0], cmd->name[0]); + cmd = cmd->next; + } +} + +static int cmd_help(int argc, const char **argv) { + if (argc < 1) { + print_global_help(); + return 0; + } + + if (argc == 1 && (!strcmp(argv[0], "help") || !strcmp(argv[0], "h") || !strcmp(argv[0], "global"))) { + print_global_help(); + return 0; + } + + const char *topic = (argc > 1) ? argv[1] : argv[0]; + + if (!strcmp(topic, "global")) { + print_global_help(); + return 0; + } + + struct cmd_struct *cmd = commands; + while (cmd) { + if (!strcmp(topic, cmd->name[0])) { + if (cmd->help_text) { + printf("%s\n", cmd->help_text); + } else { + printf("dep %s - %s\n\n", cmd->name[0], cmd->description); + printf(" %s\n", cmd->display); + } + return 0; + } + cmd = cmd->next; + } + + fprintf(stderr, "Error: unknown help topic '%s'\n", topic); + fprintf(stderr, "Run 'dep help' for available topics.\n"); + return 1; +} + +void __attribute__((constructor)) cmd_help_setup(void) { + struct cmd_struct *cmd = calloc(1, sizeof(struct cmd_struct)); + if (!cmd) { + fprintf(stderr, "Failed to allocate memory for help command\n"); + return; + } + cmd->next = commands; + cmd->fn = cmd_help; + static const char *help_names[] = {"help", "h", NULL}; + cmd->name = help_names; + cmd->display = "help [topic]"; + cmd->description = "Show this help or the top-level info about a command"; + cmd->help_text = + "dep help - Show this help or the top-level info about a command\n" + "\n" + "Usage:\n" + " dep help\n" + " dep help <command>\n" + "\n" + "Description:\n" + " Show general help or detailed help for a specific command.\n" + "\n" + "Examples:\n" + " dep help # Show general help\n" + " dep help add # Show help for add command\n" + " dep help install # Show help for install command\n"; + commands = cmd; +} diff --git a/src/command/init/main.c b/src/command/init/main.c @@ -54,5 +54,21 @@ void __attribute__((constructor)) cmd_init_setup(void) { cmd->fn = cmd_init; static const char *init_names[] = {"init", NULL}; cmd->name = init_names; - commands = cmd; + cmd->display = "init"; + cmd->description = "Initialize a new project with a .dep file"; + cmd->help_text = + "dep init - Initialize a new project with a .dep file\n" + "\n" + "Usage:\n" + " dep init\n" + " dep init <directory>\n" + "\n" + "Description:\n" + " Create an empty .dep file in the current directory or a specified directory.\n" + " The .dep file is used to list dependencies for the project.\n" + "\n" + "Examples:\n" + " dep init # Create .dep in current directory\n" + " dep init /path/to/project # Create .dep in specified directory\n"; + commands = cmd; } diff --git a/src/command/install/main.c b/src/command/install/main.c @@ -442,5 +442,22 @@ void __attribute__((constructor)) cmd_install_setup(void) { cmd->fn = cmd_install; static const char *install_names[] = {"install", "i", NULL}; cmd->name = install_names; - commands = cmd; + cmd->display = "i(nstall)"; + cmd->description = "Install all the project's dependencies"; + cmd->help_text = + "dep install - Install all the project's dependencies\n" + "\n" + "Usage:\n" + " dep install\n" + "\n" + "Description:\n" + " Install all dependencies listed in the .dep file in the current directory.\n" + "\n" + " Dependencies are installed to the lib/ directory by default.\n" + "\n" + " Each dependency is downloaded and extracted to lib/<owner>/<name>/.\n" + "\n" + " If a dependency itself has dependencies listed in its own .dep file,\n" + " those will be installed recursively.\n"; + commands = cmd; } diff --git a/src/command/license/main.c b/src/command/license/main.c @@ -20,5 +20,15 @@ void __attribute__((constructor)) cmd_license_setup() { cmd->fn = cmd_license; static const char *license_names[] = {"license", NULL}; cmd->name = license_names; - commands = cmd; + cmd->display = "license"; + cmd->description = "Show license information"; + cmd->help_text = + "dep license - Show license information\n" + "\n" + "Usage:\n" + " dep license\n" + "\n" + "Description:\n" + " Display the license information for dep.\n"; + commands = cmd; } diff --git a/src/command/repository/main.c b/src/command/repository/main.c @@ -309,5 +309,31 @@ void __attribute__((constructor)) cmd_repository_setup(void) { cmd->fn = cmd_repository; static const char *repository_names[] = {"repository", "repo", "r", NULL}; cmd->name = repository_names; - commands = cmd; + cmd->display = "r(epo(sitory))"; + cmd->description = "Repository management"; + cmd->help_text = + "dep repository - Repository management\n" + "\n" + "Usage:\n" + " dep repository list\n" + " dep repository add <name> <url>\n" + " dep repository remove <name>\n" + " dep repository clean-cache\n" + "\n" + "Description:\n" + " dep can use custom repositories to discover packages. Repositories are\n" + " configured in ~/.config/finwo/dep/repositories.d/.\n" + "\n" + "Subcommands:\n" + " list List the names of the configured repositories\n" + " add Add a repository: dep repository add <name> <url>\n" + " remove Remove a repository: dep repository remove <name>\n" + " clean-cache Remove all cached manifest files\n" + "\n" + "Examples:\n" + " dep repository add myorg https://example.com/path/to/manifest\n" + " dep repository list\n" + " dep repository remove myorg\n" + " dep repository clean-cache\n"; + commands = cmd; } diff --git a/src/main.c b/src/main.c @@ -11,46 +11,36 @@ struct cmd_struct *commands = NULL; -static const char *const usages[] = { - "subcommands [options] [cmd] [args]", - NULL, -}; +static void print_global_usage(void) { + printf("Usage: dep [global options] <command> [command options]\n"); + printf("\n"); + printf("Global options:\n"); + printf(" n/a\n"); + printf("\n"); + printf("Commands:\n"); -int cmd_foo(int argc, const char **argv) { - printf("executing subcommand foo\n"); - printf("argc: %d\n", argc); - for (int i = 0; i < argc; i++) { - printf("argv[%d]: %s\n", i, *(argv + i)); - } - int force = 0; - int test = 0; - const char *path = NULL; - struct argparse_option options[] = { - OPT_HELP(), - OPT_BOOLEAN('f', "force", &force, "force to do", NULL, 0, 0), - OPT_BOOLEAN('t', "test", &test, "test only", NULL, 0, 0), - OPT_STRING('p', "path", &path, "path to read", NULL, 0, 0), - OPT_END(), - }; - struct argparse argparse; - argparse_init(&argparse, options, usages, 0); - argc = argparse_parse(&argparse, argc, argv); - printf("after argparse_parse:\n"); - printf("argc: %d\n", argc); - for (int i = 0; i < argc; i++) { - printf("argv[%d]: %s\n", i, *(argv + i)); + struct cmd_struct *cmd = commands; + while (cmd) { + printf(" %-16s %s\n", cmd->display ? cmd->display : cmd->name[0], cmd->description ? cmd->description : ""); + cmd = cmd->next; } - return 0; -} -int cmd_bar(int argc, const char **argv) { - printf("executing subcommand bar\n"); - for (int i = 0; i < argc; i++) { - printf("argv[%d]: %s\n", i, *(argv + i)); + printf("\n"); + printf("Help topics:\n"); + printf(" global This help text\n"); + + cmd = commands; + while (cmd) { + printf(" %-16s More detailed explanation on the %s command\n", cmd->name[0], cmd->name[0]); + cmd = cmd->next; } - return 0; } +static const char *const usages[] = { + "dep [global options] <command> [command options]", + NULL, +}; + int main(int argc, const char **argv) { struct argparse argparse; struct argparse_option options[] = { @@ -60,8 +50,8 @@ int main(int argc, const char **argv) { argparse_init(&argparse, options, usages, ARGPARSE_STOP_AT_NON_OPTION); argc = argparse_parse(&argparse, argc, argv); if (argc < 1) { - argparse_usage(&argparse); - return -1; + print_global_usage(); + return 0; } /* Try to run command with args provided. */