Skip to content

Commit

Permalink
Merge pull request #53 from cofyc/sub-cmd
Browse files Browse the repository at this point in the history
add sub command test and example
  • Loading branch information
cofyc-bot authored Feb 10, 2022
2 parents 1509171 + c5c640b commit ef7b3a9
Show file tree
Hide file tree
Showing 12 changed files with 177 additions and 156 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
build/
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
tags
test_argparse
*.[ao]
*.dylib
*.so
Expand Down
13 changes: 0 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,3 @@ endif()
if(NOT (ARGPARSE_STATIC OR ARGPARSE_SHARED))
add_library(argparse OBJECT ${sources})
endif()

option(ENABLE_TESTS "Enable tests" OFF)
if((ENABLE_TESTS OR CMAKE_TESTING_ENABLED) AND UNIX)
enable_testing()

add_executable(test_argparse test_argparse.c ${sources})
add_test(NAME argparse_test COMMAND ${CMAKE_SOURCE_DIR}/test.sh)
add_custom_command(
TARGET test_argparse
COMMENT "Running tests"
POST_BUILD WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION> --output-on-failures)
endif()
11 changes: 3 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ endif
all: $(DYLIBNAME) $(STLIBNAME)

OBJS += argparse.o
OBJS += test_argparse.o

$(OBJS): %.o: %.c argparse.h
$(CROSS_COMPILE)gcc -o $*.o -c $(ALL_CFLAGS) $<
Expand All @@ -40,15 +39,11 @@ $(DYLIBNAME): argparse.o
$(STLIBNAME): argparse.o
$(STLIB_MAKE_CMD) $^

test: test_argparse
@echo "###### Unit Test #####"
@./test.sh

test_argparse: $(OBJS)
$(CROSS_COMPILE)gcc $(ALL_CFLAGS) -o $@ $^ $(ALL_LDFLAGS)
test:
make -C tests/ test

clean:
rm -rf test_argparse
rm -rf *.[ao]
rm -rf *.so
rm -rf *.dylib
make -C tests/ clean
67 changes: 5 additions & 62 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# argparse [![Build Status](https://travis-ci.org/cofyc/argparse.png)](https://travis-ci.org/cofyc/argparse)
# argparse

[![Build Status](https://github.com/cofyc/argparse/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/cofyc/argparse/actions/workflows/ci.yaml)

argparse - A command line arguments parsing library in C (compatible with C++).

Expand Down Expand Up @@ -41,64 +43,5 @@ Options and non-option arguments can clearly be separated using the `--` option.

## Examples

```c
#include <stdio.h>
#include "argparse.h"

static const char *const usage[] = {
"test_argparse [options] [[--] args]",
"test_argparse [options]",
NULL,
};

#define PERM_READ (1<<0)
#define PERM_WRITE (1<<1)
#define PERM_EXEC (1<<2)

int
main(int argc, const char **argv)
{
int force = 0;
int test = 0;
int num = 0;
const char *path = NULL;
int perms = 0;
struct argparse_option options[] = {
OPT_HELP(),
OPT_GROUP("Basic options"),
OPT_BOOLEAN('f', "force", &force, "force to do"),
OPT_BOOLEAN('t', "test", &test, "test only"),
OPT_STRING('p', "path", &path, "path to read"),
OPT_INTEGER('n', "num", &num, "selected num"),
OPT_GROUP("Bits options"),
OPT_BIT(0, "read", &perms, "read perm", NULL, PERM_READ, OPT_NONEG),
OPT_BIT(0, "write", &perms, "write perm", NULL, PERM_WRITE),
OPT_BIT(0, "exec", &perms, "exec perm", NULL, PERM_EXEC),
OPT_END(),
};

struct argparse argparse;
argparse_init(&argparse, options, usage, 0);
argparse_describe(&argparse, "\nA brief description of what the program does and how it works.", "\nAdditional description of the program after the description of the arguments.");
argc = argparse_parse(&argparse, argc, argv);
if (force != 0)
printf("force: %d\n", force);
if (test != 0)
printf("test: %d\n", test);
if (path != NULL)
printf("path: %s\n", path);
if (num != 0)
printf("num: %d\n", num);
if (argc != 0) {
printf("argc: %d\n", argc);
int i;
for (i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, *(argv + i));
}
}
if (perms) {
printf("perms: %d\n", perms);
}
return 0;
}
```
- [basic](tests/basic.c)
- [subcommands](tests/subcommands.c)
69 changes: 0 additions & 69 deletions test.sh

This file was deleted.

2 changes: 2 additions & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
basic
subcommands
15 changes: 15 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
all:: test

OBJS += $(patsubst %.c,%,$(wildcard *.c))

${OBJS}: %: %.c ../argparse.c
$(CC) -I../ -o $@ ${DEP_LIBS} $^

test: ${OBJS}
prove *.sh
.PHONY: test

clean:
rm -f ${OBJS}
find . -name '.o' -exec rm \;
.PHONY: clean
4 changes: 2 additions & 2 deletions test_argparse.c → tests/basic.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
#include "argparse.h"

static const char *const usages[] = {
"test_argparse [options] [[--] args]",
"test_argparse [options]",
"basic [options] [[--] args]",
"basic [options]",
NULL,
};

Expand Down
69 changes: 69 additions & 0 deletions tests/basic.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash

. $(dirname ${BASH_SOURCE[0]})/tap-functions
plan_no_plan

is "$(./basic -f --path=/path/to/file a 2>&1)" 'force: 1
path: /path/to/file
argc: 1
argv[0]: a'

is "$(./basic -f -f --force --no-force 2>&1)" 'force: 2'

is "$(./basic -i 2>&1)" 'error: option `-i` requires a value'

is "$(./basic -i 2 2>&1)" 'int_num: 2'

is "$(./basic -i2 2>&1)" 'int_num: 2'

is "$(./basic -ia 2>&1)" 'error: option `-i` expects an integer value'

is "$(./basic -i 0xFFFFFFFFFFFFFFFFF 2>&1)" \
'error: option `-i` numerical result out of range'

is "$(./basic -s 2.4 2>&1)" 'flt_num: 2.4'

is "$(./basic -s2.4 2>&1)" 'flt_num: 2.4'

is "$(./basic -sa 2>&1)" 'error: option `-s` expects a numerical value'

is "$(./basic -s 1e999 2>&1)" \
'error: option `-s` numerical result out of range'

is "$(./basic -f -- do -f -h 2>&1)" 'force: 1
argc: 3
argv[0]: do
argv[1]: -f
argv[2]: -h'

is "$(./basic -tf 2>&1)" 'force: 1
test: 1'

is "$(./basic --read --write 2>&1)" 'perms: 3'

help_usage='Usage: basic [options] [[--] args]
or: basic [options]
A brief description of what the program does and how it works.
-h, --help show this help message and exit
Basic options
-f, --force force to do
-t, --test test only
-p, --path=<str> path to read
-i, --int=<int> selected integer
-s, --float=<flt> selected float
Bits options
--read read perm
--write write perm
--exec exec perm
Additional description of the program after the description of the arguments.'

is "$(./basic -h)" "$help_usage"

is "$(./basic --help)" "$help_usage"

is "$(./basic --no-help 2>&1)" 'error: unknown option `--no-help`'$'\n'"$help_usage"
71 changes: 71 additions & 0 deletions tests/subcommands.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "argparse.h"

#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

static const char *const usages[] = {
"subcommands [options] [cmd] [args]",
NULL,
};

struct cmd_struct {
const char *cmd;
int len;
int (*fn) (int, const char **);
const char *help;
};

int
cmd_foo(int argc, const char **argv)
{
printf("executing subcommand foo\n");
for (int i = 0; i < argc; i++) {
printf("argv[%d]: %s\n", i, *(argv + i));
}
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));
}
return 0;
}

static struct cmd_struct commands[] = {
{"foo", 3, cmd_foo, NULL},
{"bar", 3, cmd_bar, NULL},
};

int
main(int argc, const char **argv)
{
struct argparse argparse;
struct argparse_option options[] = {
OPT_HELP(),
OPT_END(),
};
argparse_init(&argparse, options, usages, 0);
argc = argparse_parse(&argparse, argc, argv);
if (argc < 1) {
argparse_usage(&argparse);
return -1;
}

/* Try to run command with args provided. */
struct cmd_struct *cmd = NULL;
for (int i = 0; i < ARRAY_SIZE(commands); i++) {
if (!strcmp(commands[i].cmd, argv[0])) {
cmd = &commands[i];
}
}
if (cmd) {
return cmd->fn(argc, argv);
}
return 0;
}
7 changes: 7 additions & 0 deletions tests/subcommands.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

. $(dirname ${BASH_SOURCE[0]})/tap-functions
plan_no_plan

is "$(./subcommands foo)" 'executing subcommand foo
argv[0]: foo'
File renamed without changes.

0 comments on commit ef7b3a9

Please sign in to comment.