mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-18 03:25:55 +00:00
Emit JSON on -J arg to demo #387
Accept -J as a parameter requiring an option to notcurses-demo(1). Update the man page and usage message to reflect this. Open the specified file for binary writing with truncation at option parsing time; fail out if we can't open it. At the end of the demo, write the results out as JSON, using full precision for all values #387.
This commit is contained in:
parent
87cac84db2
commit
0dc5456035
@ -9,7 +9,7 @@ notcurses-demo - Show off some notcurses features
|
||||
# SYNOPSIS
|
||||
|
||||
**notcurses-demo** [**-h|--help**] [**-p path**] [**-d delaymult**]
|
||||
[**-l loglevel**] [**-f renderfile**] [**-ikVc**] demospec
|
||||
[**-l loglevel**] [**-f renderfile**] [**-J jsonfile**] [**-ikVc**] demospec
|
||||
|
||||
# DESCRIPTION
|
||||
|
||||
@ -51,6 +51,8 @@ At any time, press 'q' to quit. The demo is best run in at least an 80x45 termin
|
||||
|
||||
**-f renderfile**: Render each frame to **renderfile** in addition to the screen.
|
||||
|
||||
**-J jsonfile**: Emit JSON summary of run to **jsonfile**.
|
||||
|
||||
**-k**: Inhibit use of the alternate screen. Necessary if you want the output left on your terminal after the program exits.
|
||||
|
||||
**-c**: Do not attempt to seed the PRNG. This is useful when benchmarking.
|
||||
|
@ -120,13 +120,15 @@ static struct {
|
||||
static void
|
||||
usage(const char* exe, int status){
|
||||
FILE* out = status == EXIT_SUCCESS ? stdout : stderr;
|
||||
fprintf(out, "usage: %s [ -hVkc ] [ -p path ] [ -l loglevel ] [ -d mult ] [ -f renderfile ] demospec\n", exe);
|
||||
fprintf(out, "usage: %s [ -hVikc ] [ -p path ] [ -l loglevel ] [ -d mult ] [ -J jsonfile ] [ -f renderfile ] demospec\n", exe);
|
||||
fprintf(out, " -h: this message\n");
|
||||
fprintf(out, " -V: print program name and version\n");
|
||||
fprintf(out, " -l: logging level (%d: silent..%d: manic)\n", NCLOGLEVEL_SILENT, NCLOGLEVEL_TRACE);
|
||||
fprintf(out, " -i: ignore failures, keep going\n");
|
||||
fprintf(out, " -k: keep screen; do not switch to alternate\n");
|
||||
fprintf(out, " -d: delay multiplier (non-negative float)\n");
|
||||
fprintf(out, " -f: render to file in addition to stdout\n");
|
||||
fprintf(out, " -J: emit JSON summary to file\n");
|
||||
fprintf(out, " -c: constant PRNG seed, useful for benchmarking\n");
|
||||
fprintf(out, " -p: data file path (default: %s)\n", NOTCURSES_SHARE);
|
||||
fprintf(out, "if no specification is provided, run %s\n", DEFAULT_DEMO);
|
||||
@ -178,14 +180,16 @@ ext_demos(struct notcurses* nc, const char* spec, bool ignore_failures){
|
||||
// specification, also returns NULL, heh. determine this by argv[optind];
|
||||
// if it's NULL, there were valid options, but no spec.
|
||||
static const char*
|
||||
handle_opts(int argc, char** argv, notcurses_options* opts, bool* ignore_failures){
|
||||
handle_opts(int argc, char** argv, notcurses_options* opts, bool* ignore_failures,
|
||||
FILE** json_output){
|
||||
strcpy(datadir, NOTCURSES_SHARE);
|
||||
char renderfile[PATH_MAX] = "";
|
||||
bool constant_seed = false;
|
||||
*ignore_failures = false;
|
||||
*json_output = NULL;
|
||||
int c;
|
||||
memset(opts, 0, sizeof(*opts));
|
||||
while((c = getopt(argc, argv, "Vhickl:r:d:f:p:")) != EOF){
|
||||
while((c = getopt(argc, argv, "VhickJ:l:r:d:f:p:")) != EOF){
|
||||
switch(c){
|
||||
case 'h':
|
||||
usage(*argv, EXIT_SUCCESS);
|
||||
@ -205,6 +209,16 @@ handle_opts(int argc, char** argv, notcurses_options* opts, bool* ignore_failure
|
||||
}case 'V':
|
||||
printf("notcurses-demo version %s\n", notcurses_version());
|
||||
exit(EXIT_SUCCESS);
|
||||
case 'J':
|
||||
if(*json_output){
|
||||
fprintf(stderr, "Supplied -J twice: %s\n", optarg);
|
||||
usage(*argv, EXIT_FAILURE);
|
||||
}
|
||||
if((*json_output = fopen(optarg, "wb")) == NULL){
|
||||
fprintf(stderr, "Error opening %s for JSON (%s?)\n", optarg, strerror(errno));
|
||||
usage(*argv, EXIT_FAILURE);
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
constant_seed = true;
|
||||
break;
|
||||
@ -288,6 +302,23 @@ table_printf(struct ncdirect* nc, const char* delim, const char* fmt, ...){
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
summary_json(FILE* f, const char* spec, int rows, int cols){
|
||||
int ret = 0;
|
||||
ret |= (fprintf(f, "{\"notcurses-demo\":{\"spec\":\"%s\",\"TERM\":\"%s\",\"rows\":\"%d\",\"cols\":\"%d\",\"runs\":{",
|
||||
spec, getenv("TERM"), rows, cols) < 0);
|
||||
for(size_t i = 0 ; i < strlen(spec) ; ++i){
|
||||
if(results[i].result || !results[i].stats.renders){
|
||||
continue;
|
||||
}
|
||||
ret |= (fprintf(f, "\"%s\":{\"bytes\":\"%ju\",\"frames\":\"%ju\",\"ns\":\"%ju\"}",
|
||||
demos[results[i].selector - 'a'].name, results[i].stats.render_bytes,
|
||||
results[i].stats.renders, results[i].timens) < 0);
|
||||
}
|
||||
ret |= (fprintf(f, "}}}\n") < 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
summary_table(struct ncdirect* nc, const char* spec){
|
||||
bool failed = false;
|
||||
@ -348,7 +379,6 @@ summary_table(struct ncdirect* nc, const char* spec){
|
||||
totalbytes += results[i].stats.render_bytes;
|
||||
totalrenderns += results[i].stats.render_ns;
|
||||
}
|
||||
free(results);
|
||||
qprefix(nsdelta, GIG, timebuf, 0);
|
||||
bprefix(totalbytes, 1, totalbuf, 0);
|
||||
qprefix(totalrenderns, GIG, rtimebuf, 0);
|
||||
@ -384,9 +414,10 @@ int main(int argc, char** argv){
|
||||
sigaddset(&sigmask, SIGWINCH);
|
||||
pthread_sigmask(SIG_SETMASK, &sigmask, NULL);
|
||||
const char* spec;
|
||||
bool ignore_failures;
|
||||
FILE* json = NULL; // emit JSON summary to this file? (-J)
|
||||
bool ignore_failures; // continue after a failure? (-k)
|
||||
notcurses_options nopts;
|
||||
if((spec = handle_opts(argc, argv, &nopts, &ignore_failures)) == NULL){
|
||||
if((spec = handle_opts(argc, argv, &nopts, &ignore_failures, &json)) == NULL){
|
||||
if(argv[optind] != NULL){
|
||||
usage(*argv, EXIT_FAILURE);
|
||||
}
|
||||
@ -458,14 +489,18 @@ int main(int argc, char** argv){
|
||||
}
|
||||
}
|
||||
struct ncdirect* ncd = notcurses_directmode(NULL, stdout);
|
||||
// reinitialize without alternate screen to do some coloring
|
||||
if(!ncd){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(json && summary_json(json, spec, ncdirect_dim_y(ncd), ncdirect_dim_x(ncd))){
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
// reinitialize without alternate screen to do some coloring
|
||||
if(summary_table(ncd, spec)){
|
||||
ncdirect_stop(ncd);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
free(results);
|
||||
ncdirect_stop(ncd);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user