commit 2c336985c79c2f60711f42ba902932a992da59b8
parent 3d3644c0cbcf34731bd9dd8076f377eb7ece5a74
Author: finwo <finwo@pm.me>
Date: Sat, 14 Mar 2026 03:27:03 +0100
Restructure help
Diffstat:
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. */