mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
properties: add color support for dumping properties
This commit is contained in:
parent
dd21ebf6b8
commit
2d388c6908
3 changed files with 80 additions and 44 deletions
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <spa/utils/ansi.h>
|
||||
#include <spa/utils/json.h>
|
||||
#include <spa/utils/string.h>
|
||||
|
||||
|
|
@ -640,10 +642,27 @@ const char *pw_properties_iterate(const struct pw_properties *properties, void *
|
|||
return pw_array_get_unchecked(&impl->items, index, struct spa_dict_item)->key;
|
||||
}
|
||||
|
||||
static int encode_string(FILE *f, const char *val, int size)
|
||||
#define NORMAL(c) ((c)->colors ? SPA_ANSI_RESET : "")
|
||||
#define LITERAL(c) ((c)->colors ? SPA_ANSI_BRIGHT_MAGENTA : "")
|
||||
#define NUMBER(c) ((c)->colors ? SPA_ANSI_BRIGHT_CYAN : "")
|
||||
#define STRING(c) ((c)->colors ? SPA_ANSI_BRIGHT_GREEN : "")
|
||||
#define KEY(c) ((c)->colors ? SPA_ANSI_BRIGHT_BLUE : "")
|
||||
#define CONTAINER(c) ((c)->colors ? SPA_ANSI_BRIGHT_YELLOW : "")
|
||||
|
||||
struct dump_config {
|
||||
FILE *file;
|
||||
int indent;
|
||||
const char *sep;
|
||||
bool colors;
|
||||
bool recurse;
|
||||
};
|
||||
|
||||
static int encode_string(struct dump_config *c, const char *before,
|
||||
const char *val, int size, const char *after)
|
||||
{
|
||||
FILE *f = c->file;
|
||||
int i, len = 0;
|
||||
len += fprintf(f, "\"");
|
||||
len += fprintf(f, "%s\"", before);
|
||||
for (i = 0; i < size; i++) {
|
||||
char v = val[i];
|
||||
switch (v) {
|
||||
|
|
@ -673,16 +692,10 @@ static int encode_string(FILE *f, const char *val, int size)
|
|||
break;
|
||||
}
|
||||
}
|
||||
len += fprintf(f, "\"");
|
||||
len += fprintf(f, "\"%s", after);
|
||||
return len-1;
|
||||
}
|
||||
|
||||
struct dump_config {
|
||||
FILE *file;
|
||||
int indent;
|
||||
const char *sep;
|
||||
};
|
||||
|
||||
static int dump(struct dump_config *c, int indent, struct spa_json *it, const char *value, int len)
|
||||
{
|
||||
FILE *file = c->file;
|
||||
|
|
@ -690,8 +703,11 @@ static int dump(struct dump_config *c, int indent, struct spa_json *it, const ch
|
|||
int count = 0;
|
||||
char key[1024];
|
||||
|
||||
if (value == NULL) {
|
||||
fprintf(file, "null");
|
||||
if (value == NULL || len == 0) {
|
||||
fprintf(file, "%snull%s", LITERAL(c), NORMAL(c));
|
||||
} else if (spa_json_is_container(value, len) && !c->recurse) {
|
||||
len = spa_json_container_len(it, value, len);
|
||||
fprintf(file, "%s%.*s%s", CONTAINER(c), len, value, NORMAL(c));
|
||||
} else if (spa_json_is_array(value, len)) {
|
||||
fprintf(file, "[");
|
||||
spa_json_enter(it, &sub);
|
||||
|
|
@ -712,7 +728,7 @@ static int dump(struct dump_config *c, int indent, struct spa_json *it, const ch
|
|||
fprintf(file, "%s%s%*s",
|
||||
count++ > 0 ? "," : "",
|
||||
c->sep, indent, "");
|
||||
encode_string(file, key, strlen(key));
|
||||
encode_string(c, KEY(c), key, strlen(key), NORMAL(c));
|
||||
fprintf(file, ": ");
|
||||
if ((len = spa_json_next(&sub, &value)) <= 0)
|
||||
break;
|
||||
|
|
@ -721,19 +737,20 @@ static int dump(struct dump_config *c, int indent, struct spa_json *it, const ch
|
|||
indent -= c->indent;
|
||||
fprintf(file, "%s%*s}", count > 0 ? c->sep : "",
|
||||
count > 0 ? indent : 0, "");
|
||||
} else if (spa_json_is_string(value, len) ||
|
||||
spa_json_is_null(value, len) ||
|
||||
spa_json_is_bool(value, len) ||
|
||||
spa_json_is_int(value, len) ||
|
||||
} else if (spa_json_is_null(value, len) ||
|
||||
spa_json_is_bool(value, len)) {
|
||||
fprintf(file, "%s%.*s%s", LITERAL(c), len, value, NORMAL(c));
|
||||
} else if (spa_json_is_int(value, len) ||
|
||||
spa_json_is_float(value, len)) {
|
||||
fprintf(file, "%.*s", len, value);
|
||||
fprintf(file, "%s%.*s%s", NUMBER(c), len, value, NORMAL(c));
|
||||
} else if (spa_json_is_string(value, len)) {
|
||||
fprintf(file, "%s%.*s%s", STRING(c), len, value, NORMAL(c));
|
||||
} else {
|
||||
encode_string(file, value, len);
|
||||
encode_string(c, STRING(c), value, len, NORMAL(c));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
SPA_EXPORT
|
||||
int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t flags)
|
||||
{
|
||||
|
|
@ -742,8 +759,10 @@ int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t
|
|||
struct dump_config cfg = {
|
||||
.file = f,
|
||||
.indent = flags & PW_PROPERTIES_FLAG_NL ? 2 : 0,
|
||||
.sep = flags & PW_PROPERTIES_FLAG_NL ? "\n" : " "
|
||||
};
|
||||
.sep = flags & PW_PROPERTIES_FLAG_NL ? "\n" : " ",
|
||||
.colors = SPA_FLAG_IS_SET(flags, PW_PROPERTIES_FLAG_COLORS),
|
||||
.recurse = SPA_FLAG_IS_SET(flags, PW_PROPERTIES_FLAG_RECURSE),
|
||||
}, *c = &cfg;
|
||||
const char *enc = flags & PW_PROPERTIES_FLAG_ARRAY ? "[]" : "{}";
|
||||
|
||||
if (SPA_FLAG_IS_SET(flags, PW_PROPERTIES_FLAG_ENCLOSE))
|
||||
|
|
@ -751,37 +770,28 @@ int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t
|
|||
|
||||
spa_dict_for_each(it, dict) {
|
||||
char key[1024];
|
||||
int len = it->value ? strlen(it->value) : 0;
|
||||
int len;
|
||||
const char *value;
|
||||
struct spa_json sub;
|
||||
|
||||
fprintf(f, "%s%s%*s", count == 0 ? "" : ",", cfg.sep, cfg.indent, "");
|
||||
fprintf(f, "%s%s%*s", count == 0 ? "" : ",", c->sep, c->indent, "");
|
||||
|
||||
if (!(flags & PW_PROPERTIES_FLAG_ARRAY)) {
|
||||
if (spa_json_encode_string(key, sizeof(key)-1, it->key) >= (int)sizeof(key)-1)
|
||||
continue;
|
||||
fprintf(f, "%s: ", key);
|
||||
fprintf(f, "%s%s%s: ", KEY(c), key, NORMAL(c));
|
||||
}
|
||||
value = it->value;
|
||||
|
||||
if (it->value == NULL) {
|
||||
fprintf(f, "null");
|
||||
} else if (SPA_FLAG_IS_SET(flags, PW_PROPERTIES_FLAG_RECURSE)) {
|
||||
struct spa_json sub;
|
||||
spa_json_init(&sub, it->value, len);
|
||||
if ((len = spa_json_next(&sub, &value)) <= 0)
|
||||
break;
|
||||
dump(&cfg, cfg.indent, &sub, value, len);
|
||||
} else if (spa_json_is_null(it->value, len) ||
|
||||
spa_json_is_float(it->value, len) ||
|
||||
spa_json_is_bool(it->value, len) ||
|
||||
spa_json_is_container(it->value, len) ||
|
||||
spa_json_is_string(it->value, len)) {
|
||||
fprintf(f, "%s", it->value);
|
||||
} else {
|
||||
encode_string(f, it->value, len);
|
||||
}
|
||||
len = value ? strlen(value) : 0;
|
||||
spa_json_init(&sub, value, len);
|
||||
if ((len = spa_json_next(&sub, &value)) < 0)
|
||||
break;
|
||||
|
||||
dump(c, c->indent, &sub, value, len);
|
||||
count++;
|
||||
}
|
||||
if (SPA_FLAG_IS_SET(flags, PW_PROPERTIES_FLAG_ENCLOSE))
|
||||
fprintf(f, "%s%c", cfg.sep, enc[1]);
|
||||
fprintf(f, "%s%c", c->sep, enc[1]);
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,6 +140,7 @@ pw_properties_iterate(const struct pw_properties *properties, void **state);
|
|||
#define PW_PROPERTIES_FLAG_RECURSE (1<<1)
|
||||
#define PW_PROPERTIES_FLAG_ENCLOSE (1<<2)
|
||||
#define PW_PROPERTIES_FLAG_ARRAY (1<<3)
|
||||
#define PW_PROPERTIES_FLAG_COLORS (1<<4)
|
||||
int pw_properties_serialize_dict(FILE *f, const struct spa_dict *dict, uint32_t flags);
|
||||
|
||||
static inline bool pw_properties_parse_bool(const char *value) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ struct data {
|
|||
const char *opt_cmd;
|
||||
bool opt_recurse;
|
||||
bool opt_newline;
|
||||
bool opt_colors;
|
||||
struct pw_properties *conf;
|
||||
struct pw_properties *assemble;
|
||||
int count;
|
||||
|
|
@ -35,6 +36,7 @@ static void print_all_properties(struct data *d, struct pw_properties *props)
|
|||
&props->dict,
|
||||
(d->opt_newline ? PW_PROPERTIES_FLAG_NL : 0) |
|
||||
(d->opt_recurse ? PW_PROPERTIES_FLAG_RECURSE : 0) |
|
||||
(d->opt_colors ? PW_PROPERTIES_FLAG_COLORS : 0) |
|
||||
(d->array ? PW_PROPERTIES_FLAG_ARRAY : 0) |
|
||||
PW_PROPERTIES_FLAG_ENCLOSE);
|
||||
fprintf(stdout, "\n");
|
||||
|
|
@ -124,7 +126,9 @@ static void show_help(const char *name, bool error)
|
|||
" -n, --name Config Name (default '%2$s')\n"
|
||||
" -p, --prefix Config Prefix (default '%3$s')\n"
|
||||
" -L, --no-newline Omit newline after values\n"
|
||||
" -r, --recurse Dump values recursively\n",
|
||||
" -r, --recurse Dump values recursively\n"
|
||||
" -N, --no-colors disable color output\n"
|
||||
" -C, --color[=WHEN] whether to enable color support. WHEN is `never`, `always`, or `auto`\n",
|
||||
name, DEFAULT_NAME, DEFAULT_PREFIX);
|
||||
}
|
||||
|
||||
|
|
@ -140,6 +144,8 @@ int main(int argc, char *argv[])
|
|||
{ "prefix", required_argument, NULL, 'p' },
|
||||
{ "no-newline", no_argument, NULL, 'L' },
|
||||
{ "recurse", no_argument, NULL, 'r' },
|
||||
{ "no-colors", no_argument, NULL, 'N' },
|
||||
{ "color", optional_argument, NULL, 'C' },
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
|
|
@ -147,11 +153,13 @@ int main(int argc, char *argv[])
|
|||
d.opt_prefix = NULL;
|
||||
d.opt_recurse = false;
|
||||
d.opt_newline = true;
|
||||
if (isatty(fileno(stdout)) && getenv("NO_COLOR") == NULL)
|
||||
d.opt_colors = true;
|
||||
d.opt_cmd = "paths";
|
||||
|
||||
pw_init(&argc, &argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hVn:p:Lr", long_options, NULL)) != -1) {
|
||||
while ((c = getopt_long(argc, argv, "hVn:p:LrNC", long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
case 'h':
|
||||
show_help(argv[0], false);
|
||||
|
|
@ -176,6 +184,23 @@ int main(int argc, char *argv[])
|
|||
case 'r':
|
||||
d.opt_recurse = true;
|
||||
break;
|
||||
case 'N' :
|
||||
d.opt_colors = false;
|
||||
break;
|
||||
case 'C' :
|
||||
if (optarg == NULL || !strcmp(optarg, "auto"))
|
||||
break; /* nothing to do, tty detection was done
|
||||
before parsing options */
|
||||
else if (!strcmp(optarg, "never"))
|
||||
d.opt_colors = false;
|
||||
else if (!strcmp(optarg, "always"))
|
||||
d.opt_colors = true;
|
||||
else {
|
||||
fprintf(stderr, "Unknown color: %s\n", optarg);
|
||||
show_help(argv[0], true);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
show_help(argv[0], true);
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue