Permalink
Browse files

strings "true"/"false" now default to booleans

  • Loading branch information...
Jan-Piet Mens
Jan-Piet Mens committed Mar 9, 2016
1 parent 5d50cb3 commit b185ed9141a2ceb5b26f5609742880e6ea02e9fa
Showing with 99 additions and 32 deletions.
  1. +2 −0 ChangeLog
  2. +2 −2 Makefile.am
  3. +1 −1 configure.ac
  4. +23 −1 jo.1
  5. +38 −25 jo.c
  6. +20 −2 jo.md
  7. +13 −1 jo.pandoc
View
@@ -1,4 +1,6 @@
2016-03-09 0.7
- NEW: strings "true"/"false" now default to booleans; avoid with -B (#17)
- FIX: test.sh get quotes to prevent failures with pdksh (#16)
- FIX: pretty-print Version if requested (#15)
- FIX: Add cast to suppress warning when compiling with GCC 4.8.4 (#14)
View
@@ -17,7 +17,7 @@ jo.1: jo.pandoc
jo.md: jo.pandoc
@test -n "$(PANDOC)" || \
{ echo 'pandoc' not found during configure.; exit 1; }
$(PANDOC) -s -w man -o $@ $<
$(PANDOC) -s -w markdown -o $@ $<
endif
@@ -26,4 +26,4 @@ endif
TESTS = tests.sh
EXTRA_DIST = $(TESTS)
EXTRA_DIST = $(TESTS) $(jo_EXTRA)
View
@@ -1,5 +1,5 @@
AC_PREREQ([2.69])
AC_INIT([jo], [0.6], [jpmens@gmail.com])
AC_INIT([jo], [0.7], [jpmens@gmail.com])
AC_CONFIG_SRCDIR([jo.c])
# Checks for programs.
View
24 jo.1
@@ -4,7 +4,7 @@
jo \- JSON output from a shell
.SH SYNOPSIS
.PP
jo [\-p] [\-a] [\-v] [\-V] [word ...]
jo [\-p] [\-a] [\-B] [\-v] [\-V] [word ...]
.SH DESCRIPTION
.PP
\f[I]jo\f[] creates a JSON string on \f[I]stdout\f[] from \f[I]word\f[]s
@@ -84,6 +84,20 @@ $\ jo\ \-p\ name=JP\ object=$(jo\ fruit=Orange\ hungry\@0\ point=$(jo\ x=10\ y=2
}
\f[]
.fi
.PP
Booleans as strings or as boolean (pay particular attention to
\f[I]switch\f[]; the \f[C]\-B\f[] option disables the default detection
of the "\f[C]true\f[]" and "\f[C]false\f[]" strings):
.IP
.nf
\f[C]
$\ jo\ switch=true\ morning\@0
{"switch":true,"morning":false}
$\ jo\ \-B\ switch=true\ morning\@0
{"switch":"true","morning":false}
\f[]
.fi
.SH OPTIONS
.PP
\f[I]jo\f[] understands the following options.
@@ -94,6 +108,14 @@ array instead of an object.
.RS
.RE
.TP
.B \-B
By default \f[I]jo\f[] interprets the strings "\f[C]true\f[]" and
"\f[C]false\f[]" as meaning boolean elements \f[C]true\f[] and
\f[C]false\f[] respectively.
Disable with this option.
.RS
.RE
.TP
.B \-p
Pretty\-print the JSON string on output instead of the terse one\-line
output it prints by default.
View
63 jo.c
@@ -30,12 +30,17 @@
# define FALSE (0)
#endif
#define SPACER " "
#define FLAG_ARRAY 0x01
#define FLAG_PRETTY 0x02
#define FLAG_NOBOOL 0x04
/*
* Attempt to "sniff" the type of data in `str' and return
* a JsonNode of the correct JSON type.
*/
JsonNode *vnode(char *str)
JsonNode *vnode(char *str, int flags)
{
if (strlen(str) == 0) {
@@ -59,10 +64,12 @@ JsonNode *vnode(char *str)
return json_mknumber(num);
}
if (strcmp(str, "true") == 0) {
return json_mkbool(true);
} else if (strcmp(str, "false") == 0) {
return json_mkbool(false);
if (!(flags & FLAG_NOBOOL)) {
if (strcmp(str, "true") == 0) {
return json_mkbool(true);
} else if (strcmp(str, "false") == 0) {
return json_mkbool(false);
}
}
if (*str == '{' || *str == '[') {
@@ -101,14 +108,16 @@ JsonNode *boolnode(char *str)
int usage(char *prog)
{
fprintf(stderr, "Usage: %s [-a] [-p] [-v] [-V] [word...]\n", prog);
fprintf(stderr, "Usage: %s [-a] [-p] [-v] [-V] [-B] [word...]\n", prog);
fprintf(stderr, "\tword is key=value or key@value\n");
fprintf(stderr, "\t-a creates an array of words, -p pretty-prints\n");
fprintf(stderr, "\t-a creates an array of words\n");
fprintf(stderr, "\t-B disable boolean true/false\n");
fprintf(stderr, "\t-p pretty-prints\n");
return (-1);
}
int member_to_object(JsonNode *object, char *kv)
int member_to_object(JsonNode *object, int flags, char *kv)
{
/* we expect key=value or key:value (boolean on last) */
char *p = strchr(kv, '=');
@@ -121,7 +130,7 @@ int member_to_object(JsonNode *object, char *kv)
if (p) {
*p = 0;
json_append_member(object, kv, vnode(p+1));
json_append_member(object, kv, vnode(p+1, flags));
} else {
*q = 0;
json_append_member(object, kv, boolnode(q+1));
@@ -133,12 +142,12 @@ int member_to_object(JsonNode *object, char *kv)
* Append kv to the array or object.
*/
void append_kv(JsonNode *object_or_array, int isarray, char *kv)
void append_kv(JsonNode *object_or_array, int flags, char *kv)
{
if (isarray) {
json_append_element(object_or_array, vnode(kv));
if (flags & FLAG_ARRAY) {
json_append_element(object_or_array, vnode(kv, flags));
} else {
if (member_to_object(object_or_array, kv) == -1) {
if (member_to_object(object_or_array, flags, kv) == -1) {
fprintf(stderr, "Argument `%s' is neither k=v nor k@v\n", kv);
}
}
@@ -217,7 +226,7 @@ char* locale_from_utf8(const char *utf8, size_t len)
# define locale_free(p)
#endif
int version(char *pretty)
int version(int flags)
{
JsonNode *json = json_mkobject();
char *js;
@@ -227,7 +236,7 @@ int version(char *pretty)
json_append_member(json, "repo", json_mkstring("https://github.com/jpmens/jo"));
json_append_member(json, "version", json_mkstring(PACKAGE_VERSION));
if ((js = json_stringify(json, pretty)) != NULL) {
if ((js = json_stringify(json, (flags & FLAG_PRETTY) ? SPACER : NULL)) != NULL) {
printf("%s\n", js);
free(js);
}
@@ -237,20 +246,24 @@ int version(char *pretty)
int main(int argc, char **argv)
{
int c, isarray = FALSE, showversion = FALSE;
char *kv, *js_string, *progname, *pretty = NULL, buf[BUFSIZ], *p;
int c, showversion = FALSE;
char *kv, *js_string, *progname, buf[BUFSIZ], *p;
int ttyin = isatty(fileno(stdin)), ttyout = isatty(fileno(stdout));
int flags = 0;
JsonNode *json;
progname = (progname = strrchr(*argv, '/')) ? progname + 1 : *argv;
while ((c = getopt(argc, argv, "apvV")) != EOF) {
while ((c = getopt(argc, argv, "aBpvV")) != EOF) {
switch (c) {
case 'a':
isarray = TRUE;
flags |= FLAG_ARRAY;
break;
case 'B':
flags |= FLAG_NOBOOL;
break;
case 'p':
pretty = " ";
flags |= FLAG_PRETTY;
break;
case 'v':
printf("jo %s\n", PACKAGE_VERSION);
@@ -264,31 +277,31 @@ int main(int argc, char **argv)
}
if (showversion) {
return(version(pretty));
return(version(flags));
}
argc -= optind;
argv += optind;
json = (isarray) ? json_mkarray() : json_mkobject();
json = (flags & FLAG_ARRAY) ? json_mkarray() : json_mkobject();
if (argc == 0) {
while (fgets(buf, sizeof(buf), stdin) != NULL) {
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = 0;
p = ttyin ? utf8_from_locale(buf, -1) : buf;
append_kv(json, isarray, p);
append_kv(json, flags, p);
if (ttyin) utf8_free(p);
}
} else {
while ((kv = *argv++)) {
p = utf8_from_locale(kv, -1);
append_kv(json, isarray, p);
append_kv(json, flags, p);
utf8_free(p);
}
}
if ((js_string = json_stringify(json, pretty)) == NULL) {
if ((js_string = json_stringify(json, (flags & FLAG_PRETTY) ? SPACER : NULL)) == NULL) {
fprintf(stderr, "Invalid JSON\n");
exit(2);
}
View
22 jo.md
@@ -1,3 +1,7 @@
---
title: 'JO(1) User Manuals'
...
NAME
====
@@ -6,7 +10,7 @@ jo - JSON output from a shell
SYNOPSIS
========
jo [-p] [-a] [-v] [-V] [word ...]
jo [-p] [-a] [-B] [-v] [-V] [word ...]
DESCRIPTION
===========
@@ -73,6 +77,16 @@ remainder as JSON. Beware spaces in strings ...
"sunday": false
}
Booleans as strings or as boolean (pay particular attention to *switch*;
the `-B` option disables the default detection of the "`true`" and
"`false`" strings):
$ jo switch=true morning@0
{"switch":true,"morning":false}
$ jo -B switch=true morning@0
{"switch":"true","morning":false}
OPTIONS
=======
@@ -82,6 +96,11 @@ OPTIONS
: Interpret the list of *words* as array values and produce an array
instead of an object.
-B
: By default *jo* interprets the strings "`true`" and "`false`" as
meaning boolean elements `true` and `false` respectively. Disable
with this option.
-p
: Pretty-print the JSON string on output instead of the terse one-line
output it prints by default.
@@ -137,4 +156,3 @@ AUTHOR
======
Jan-Piet Mens <http://jpmens.net>
View
@@ -6,7 +6,7 @@ jo - JSON output from a shell
# SYNOPSIS
jo [-p] [-a] [-v] [-V] [word ...]
jo [-p] [-a] [-B] [-v] [-V] [word ...]
# DESCRIPTION
@@ -65,6 +65,14 @@ Create objects within objects; this works because if the first character of valu
"sunday": false
}
Booleans as strings or as boolean (pay particular attention to _switch_; the `-B` option disables the default detection of the "`true`" and "`false`" strings):
$ jo switch=true morning@0
{"switch":true,"morning":false}
$ jo -B switch=true morning@0
{"switch":"true","morning":false}
# OPTIONS
*jo* understands the following options.
@@ -73,6 +81,10 @@ Create objects within objects; this works because if the first character of valu
: Interpret the list of _words_ as array values and produce an array instead of
an object.
-B
: By default *jo* interprets the strings "`true`" and "`false`" as meaning boolean elements
`true` and `false` respectively. Disable with this option.
-p
: Pretty-print the JSON string on output instead of the terse one-line output it
prints by default.

0 comments on commit b185ed9

Please sign in to comment.