Sub-Command Management

The Argtable3 library provides a robust API for managing sub-commands in command-line applications. This API allows developers to define, register, and dispatch sub-commands, making it easier to implement multi-command interfaces similar to tools like git or docker.

Sub-commands are individual commands within a larger command-line application, each with its own arguments and behavior. The functions in this API enable the creation, iteration, and management of these sub-commands, offering flexibility and control over their lifecycle.

Overview of Functions

  • Initialization and Cleanup: Functions like arg_cmd_init and arg_cmd_uninit handle the setup and teardown of the sub-command system.

  • Registration and Unregistration: Use arg_cmd_register and arg_cmd_unregister to add or remove sub-commands dynamically.

  • Dispatching Commands: The arg_cmd_dispatch function executes the appropriate sub-command based on user input.

  • Command Information: Retrieve details about registered sub-commands using arg_cmd_info or count them with arg_cmd_count.

  • Iterators: Functions such as arg_cmd_itr_create, arg_cmd_itr_destroy, arg_cmd_itr_advance, arg_cmd_itr_key, arg_cmd_itr_value, and arg_cmd_itr_search provide tools for iterating over and searching through sub-commands.

This API is designed to simplify the implementation of complex command-line interfaces, enabling developers to focus on the functionality of their commands rather than the underlying infrastructure. Below is a detailed reference for each function in the sub-command management API.

Data Types

typedef int arg_cmdfn(int argc, char *argv[], arg_dstr_t res, void *ctx)

Function pointer type for sub-command handler functions.

The arg_cmdfn type defines the signature for functions that implement the logic of a sub-command in a multi-command command-line application. When a sub-command is dispatched (for example, via arg_cmd_dispatch), the corresponding handler function is called with the command-line arguments, a dynamic string buffer for output or error messages, and an optional user-defined context pointer.

This function pointer is primarily intended for developers who want to implement custom sub-commands and register them with Argtable3. The handler should return 0 on success, or a nonzero error code on failure.

Param argc:

The number of command-line arguments for the sub-command.

Param argv:

The array of command-line arguments for the sub-command.

Param res:

Dynamic string buffer for output or error messages.

Param ctx:

User-defined context pointer, as provided during registration.

Return:

0 on success, or a nonzero error code on failure.

typedef struct arg_cmd_info arg_cmd_info_t

Structure for storing sub-command information.

The arg_cmd_info struct is used to represent metadata and handler information for a sub-command in a multi-command command-line application. Each sub-command can have its own name, description, handler function, and context pointer, allowing you to build flexible interfaces similar to tools like git or docker.

The name field stores the sub-command name, while the description provides a short summary for help and usage messages. The proc field is a pointer to the function that implements the sub-command’s behavior, and ctx is a user-defined context pointer that can be used to pass additional data to the handler.

Example usage:

// Define a handler function for the "list" sub-command
int list_cmd(int argc, char* argv[], arg_dstr_t res, void* ctx) {
    // Implementation for the "list" command
    return 0;
}

// Register the sub-command
arg_cmd_register("list", list_cmd, "List all items", NULL);

// Retrieve sub-command info
arg_cmd_info_t* info = arg_cmd_info("list");
if (info) {
    printf("Sub-command: %s - %s\n", info->name, info->description);
}

See also

arg_cmd_register, arg_cmd_info, arg_cmd_dispatch

API

void arg_cmd_init(void)

Initializes the sub-command mechanism.

The arg_cmd_init function sets up the internal data structures required for sub-command support in Argtable3. It must be called before registering, dispatching, or iterating over sub-commands in your application.

This function is typically called once at program startup, before any sub-commands are registered. It ensures that the sub-command API is ready for use. After initialization, you can use functions such as arg_cmd_register, arg_cmd_dispatch, and arg_cmd_itr_create.

When sub-command support is no longer needed (e.g., at program shutdown), call arg_cmd_uninit to release resources and prevent memory leaks.

Example usage:

arg_cmd_init();
// Register and use sub-commands...
arg_cmd_uninit();

See also

arg_cmd_uninit, arg_cmd_register, arg_cmd_unregister, arg_cmd_count

void arg_cmd_uninit(void)

Releases resources and cleans up the sub-command mechanism.

The arg_cmd_uninit function deinitializes the sub-command infrastructure, freeing any memory or resources allocated for sub-command registration, lookup, and iteration. After calling this function, all registered sub-commands are removed, and the sub-command API can no longer be used until arg_cmd_init is called again.

This function should be called at program shutdown or when you no longer need sub-command support, to prevent memory leaks and ensure proper cleanup.

Example usage:

arg_cmd_init();
// Register and use sub-commands...
arg_cmd_uninit();

See also

arg_cmd_init, arg_cmd_register, arg_cmd_unregister, arg_cmd_count

void arg_cmd_register(const char *name, arg_cmdfn *proc, const char *description, void *ctx)

Registers a new sub-command with the application.

The arg_cmd_register function adds a sub-command to the application’s sub-command table, associating it with a handler function, a description, and an optional context pointer. This enables applications to support multiple commands (such as git or docker-style interfaces), where each sub-command can have its own logic and help text.

The handler function (proc) will be called when the sub-command is dispatched via arg_cmd_dispatch. The description is used in help and usage messages. The context pointer (ctx) can be used to pass user-defined data to the handler.

If a sub-command with the same name already exists, its registration will be replaced with the new handler, description, and context.

Example usage:

// Register a "list" sub-command
arg_cmd_register("list", list_cmd, "List all items", NULL);

// Register a "remove" sub-command with context
arg_cmd_register("remove", remove_cmd, "Remove an item", my_context_ptr);

See also

arg_cmd_unregister, arg_cmd_dispatch, arg_cmd_info, arg_cmd_count

Parameters:
  • name – The name of the sub-command (null-terminated string).

  • proc – Pointer to the handler function for the sub-command.

  • description – A short description of the sub-command for help output.

  • ctx – Optional user-defined context pointer (may be NULL).

void arg_cmd_unregister(const char *name)

Unregisters a sub-command by name.

The arg_cmd_unregister function removes a previously registered sub-command from the application’s sub-command table. After calling this function, the specified sub-command will no longer be available for dispatch, iteration, or help output.

This function is useful for applications that support dynamic registration and removal of sub-commands at runtime, such as plugin-based tools or interactive shells.

If the sub-command with the given name does not exist, the function has no effect.

Example usage:

arg_cmd_register("remove", remove_cmd, "Remove an item", NULL);
// ... later ...
arg_cmd_unregister("remove");

See also

arg_cmd_register, arg_cmd_dispatch, arg_cmd_count, arg_cmd_info

Parameters:
  • name – The name of the sub-command to unregister (null-terminated string).

int arg_cmd_dispatch(const char *name, int argc, char *argv[], arg_dstr_t res)

Dispatches a registered sub-command by name.

The arg_cmd_dispatch function locates the sub-command with the specified name and invokes its handler function, passing the provided command-line arguments and a dynamic string buffer for output or error messages.

This function is typically used in applications that support multiple sub-commands (such as git or docker-style interfaces), allowing you to delegate command-line processing to the appropriate handler based on the user’s input.

If the sub-command is found, its handler function is called with the given arguments and context. If the sub-command is not found, an error message may be written to the result buffer, and a nonzero error code is returned.

Example usage:

// Register sub-commands
arg_cmd_register("list", list_cmd, "List items", NULL);
arg_cmd_register("add", add_cmd, "Add an item", NULL);

// Dispatch based on argv[1]
arg_dstr_t res = arg_dstr_create();
int ret = arg_cmd_dispatch(argv[1], argc - 1, argv + 1, res);
if (ret != 0) {
    fprintf(stderr, "%s\n", arg_dstr_cstr(res));
}
arg_dstr_destroy(res);

See also

arg_cmd_register, arg_cmd_info, arg_cmd_count, arg_dstr_create, arg_dstr_cstr

Parameters:
  • name – The name of the sub-command to dispatch (null-terminated string).

  • argc – The number of command-line arguments for the sub-command.

  • argv – The array of command-line arguments for the sub-command.

  • res – Pointer to a dynamic string buffer for output or error messages.

Returns:

0 if the sub-command was found and executed successfully, nonzero if the sub-command was not found or an error occurred.

unsigned int arg_cmd_count(void)

Returns the number of registered sub-commands.

The arg_cmd_count function returns the total number of sub-commands currently registered in the application. This is useful for applications that support multiple commands (such as git or docker-style interfaces) and need to enumerate, display, or manage the available sub-commands.

You can use this function to determine the size of the sub-command table, iterate over all registered sub-commands, or display a summary of available commands to the user.

Example usage:

unsigned int count = arg_cmd_count();
printf("There are %u sub-commands registered.\n", count);

See also

arg_cmd_register, arg_cmd_info, arg_cmd_itr_create

Returns:

The number of sub-commands currently registered.

arg_cmd_info_t *arg_cmd_info(const char *name)

Retrieves information about a registered sub-command by name.

The arg_cmd_info function returns a pointer to the arg_cmd_info_t structure for the sub-command with the specified name. This structure contains metadata such as the sub-command’s name, description, handler function, and context pointer.

This function is useful for querying details about a specific sub-command, such as when generating help output, dispatching commands, or inspecting available sub-commands in applications that support multiple commands (e.g., git or docker-style interfaces).

If the sub-command is not found, the function returns NULL.

Example usage:

arg_cmd_info_t* info = arg_cmd_info("list");
if (info) {
    printf("Sub-command: %s - %s\n", info->name, info->description);
}

See also

arg_cmd_register, arg_cmd_count, arg_cmd_itr_create, arg_cmd_info_t

Parameters:
  • name – The name of the sub-command to look up (null-terminated string).

Returns:

Pointer to the arg_cmd_info_t structure for the sub-command, or NULL if the sub-command is not found.

arg_cmd_itr_t arg_cmd_itr_create(void)

Creates a new sub-command iterator for traversing registered sub-commands.

The arg_cmd_itr_create function allocates and initializes a sub-command iterator, which can be used to traverse all registered sub-commands in the application. This iterator provides a convenient way to enumerate, search, or process sub-commands, especially in applications that support multiple commands (such as git or docker-style interfaces).

After creating the iterator, you can use functions like arg_cmd_itr_advance to move through the sub-command table, and arg_cmd_itr_key or arg_cmd_itr_value to access the current sub-command’s name or metadata. When finished, call arg_cmd_itr_destroy to release resources.

Example usage:

arg_cmd_itr_t itr = arg_cmd_itr_create();
while (arg_cmd_itr_advance(itr)) {
    const char* key = arg_cmd_itr_key(itr);
    printf("Sub-command: %s\n", key);
}
arg_cmd_itr_destroy(itr);

See also

arg_cmd_itr_destroy, arg_cmd_itr_advance, arg_cmd_itr_key, arg_cmd_itr_value

Returns:

A handle to the newly created sub-command iterator, or NULL if allocation fails.

void arg_cmd_itr_destroy(arg_cmd_itr_t itr)

Destroys the sub-command iterator and releases associated resources.

The arg_cmd_itr_destroy function deallocates any memory or resources associated with a sub-command iterator created by arg_cmd_itr_create. After calling this function, the iterator is no longer valid and must not be used.

This function should be called when you are finished iterating over sub-commands to prevent memory leaks and ensure proper cleanup.

Example usage:

arg_cmd_itr_t itr = arg_cmd_itr_create();
while (arg_cmd_itr_advance(itr)) {
    // process sub-commands
}
arg_cmd_itr_destroy(itr);

See also

arg_cmd_itr_create, arg_cmd_itr_advance, arg_cmd_itr_key, arg_cmd_itr_value

Parameters:
  • itr – The sub-command iterator to destroy.

int arg_cmd_itr_advance(arg_cmd_itr_t itr)

Advances the sub-command iterator to the next entry.

The arg_cmd_itr_advance function moves the sub-command iterator to the next sub-command in the table. This allows you to iterate over all registered sub-commands in your application, enabling tasks such as listing available commands, generating help output, or performing batch operations.

This function is typically used in a loop, where you repeatedly call arg_cmd_itr_advance and retrieve the current sub-command’s key or value using arg_cmd_itr_key or arg_cmd_itr_value.

Example usage:

arg_cmd_itr_t itr = arg_cmd_itr_create();
while (arg_cmd_itr_advance(itr)) {
    const char* key = arg_cmd_itr_key(itr);
    printf("Sub-command: %s\n", key);
}
arg_cmd_itr_destroy(itr);

See also

arg_cmd_itr_create, arg_cmd_itr_key, arg_cmd_itr_value, arg_cmd_info_t

Parameters:
  • itr – The sub-command iterator.

Returns:

1 if the iterator was advanced to a valid entry, 0 if there are no more entries (end of the sub-command table).

char *arg_cmd_itr_key(arg_cmd_itr_t itr)

Retrieves the key (name) of the sub-command at the current iterator position.

The arg_cmd_itr_key function returns a pointer to the key (typically the sub-command name as a null-terminated string) at the current position of the sub-command iterator. This allows you to access the identifier for the sub-command currently referenced by the iterator, which is useful for displaying, comparing, or processing sub-commands in applications that support multiple commands.

This function is typically used when iterating over all registered sub-commands or after searching for a specific sub-command using the iterator.

Example usage:

arg_cmd_itr_t itr = arg_cmd_itr_create();
while (arg_cmd_itr_advance(itr)) {
    const char* key = arg_cmd_itr_key(itr);
    printf("Sub-command: %s\n", key);
}
arg_cmd_itr_destroy(itr);

See also

arg_cmd_itr_create, arg_cmd_itr_advance, arg_cmd_itr_value, arg_cmd_info_t

Parameters:
  • itr – The sub-command iterator.

Returns:

Pointer to the key (sub-command name) at the current iterator position, or NULL if the iterator is not valid or at the end.

arg_cmd_info_t *arg_cmd_itr_value(arg_cmd_itr_t itr)

Retrieves the value (sub-command information) at the current iterator position.

The arg_cmd_itr_value function returns a pointer to the arg_cmd_info_t structure at the current position of the sub-command iterator. This allows you to access metadata and handler information for the sub-command found or iterated to by the iterator.

This function is typically used after advancing the iterator or searching for a specific sub-command, enabling you to inspect the sub-command’s name, description, handler function, and context pointer.

Example usage:

arg_cmd_itr_t itr = arg_cmd_itr_create();
if (arg_cmd_itr_search(itr, "list")) {
    arg_cmd_info_t* info = arg_cmd_itr_value(itr);
    printf("Found sub-command: %s - %s\n", info->name, info->description);
}
arg_cmd_itr_destroy(itr);

See also

arg_cmd_itr_create, arg_cmd_itr_advance, arg_cmd_itr_search, arg_cmd_info_t

Parameters:
  • itr – The sub-command iterator.

Returns:

Pointer to the arg_cmd_info_t structure at the current iterator position, or NULL if the iterator is not valid or at the end.

Searches for a sub-command by key using the sub-command iterator.

The arg_cmd_itr_search function searches the sub-command table for a sub-command whose key matches the specified value, starting from the current position of the iterator. If a match is found, the iterator is positioned at the found entry.

This function is useful for efficiently locating a specific sub-command in applications that support multiple commands (such as git or docker-style interfaces), especially when iterating over or managing a dynamic set of sub-commands.

Example usage:

arg_cmd_itr_t itr = arg_cmd_itr_create();
if (arg_cmd_itr_search(itr, "list")) {
    arg_cmd_info_t* info = arg_cmd_itr_value(itr);
    printf("Found sub-command: %s - %s\n", info->name, info->description);
}
arg_cmd_itr_destroy(itr);

See also

arg_cmd_itr_create, arg_cmd_itr_value, arg_cmd_info_t

Parameters:
  • itr – The sub-command iterator.

  • k – The key to search for (typically a string with the sub-command name).

Returns:

1 if the key is found and the iterator is positioned at the entry, 0 otherwise.