Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Style support for status bar #410

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions i3bar.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "log.h"
#include "map.h"
#include "term.h"
#include <stdlib.h>

/* See https://i3wm.org/docs/i3bar-protocol.html for details */

Expand Down Expand Up @@ -104,6 +105,26 @@ static void i3bar_print_term(const struct bar *bar)
fflush(stdout);
}

void amp_escape(const char *value, char *buf, size_t size)
{
int i, k = 0;
for(i = 0; value[i] != '\0'; )
{
buf[k] = value[i];

if(value[i] == '&')
{
buf[++k] = 'a';
buf[++k] = 'm';
buf[++k] = 'p';
buf[++k] = ';';
}

++i; ++k;
}
buf[k] = 0;
}

static int i3bar_print_pair(const char *key, const char *value, void *data)
{
unsigned int index = i3bar_indexof(key);
Expand Down Expand Up @@ -143,11 +164,91 @@ static int i3bar_print_pair(const char *key, const char *value, void *data)
if ((*pcount)++)
fprintf(stdout, ",");

// escape [& -> &amp;]
if(strncmp(key, "full_text", strlen(key)) == 0 && strchr(value, '&') != NULL)
{
static char buf1[BUFSIZ]={0};
amp_escape(value, buf1, sizeof(buf1));
value = buf1;
}

fprintf(stdout, "\"%s\":%s", key, value);

return 0;
}

static const char* i3bar_get_value_by_ref(const char *value, struct block *block)
{
if(value == NULL || block == NULL)
return NULL;

if(value[0] == '#') // color
{
return value;
}
if(value[0] == '&') // reference
{
const char *ref = map_get(block->env, value + 1);
if(ref != NULL)
{
// reccursive reference lookup
return i3bar_get_value_by_ref(ref, block);
}
else
{
block_debug(block, "Cannot found reference %s.", value);
return value;
}
}

return value;
}

static int i3bar_parse_pattern(struct block *block, const char *pattern, char *res)
{
char pattern_copy[BUFSIZ] = {0};

// TODO: parametrize wia block->conf
char delim[] = "%";

// copy, because strtok modifies input string
// TODO: use strdup
strcpy(pattern_copy, pattern);

char *key = strtok(pattern_copy, delim);
bool token = false;
while(key != NULL)
{
if(token)
{
const char *value = map_get(block->env, key);
if(value != NULL)
{
const char *final_value = i3bar_get_value_by_ref(value, block);
if(final_value)
strcat(res, final_value);
else
{
block_error(block, "Something wrong with %s", value); // should not hit there
return 2;
}
}
else
{
block_debug(block, "Key %s is not defined.", key);
return 1;
}
}
else
strcat(res, key);

token = !token;
key = strtok(NULL, delim);
}

return 0;
}

static int i3bar_print_block(struct block *block, void *data)
{
const char *full_text = map_get(block->env, "full_text");
Expand All @@ -161,13 +262,34 @@ static int i3bar_print_block(struct block *block, void *data)
return 0;
}

char *full_text_copy = NULL;

const char *full_text_pattern = map_get(block->config, "full_text_pattern");
if(full_text_pattern)
{
char buf[BUFSIZ] = {0};

if(i3bar_parse_pattern(block, full_text_pattern, buf) == 0)
{
full_text_copy = strdup(full_text);
if(full_text_copy != NULL)
map_set(block->env, "full_text", buf);
}
}

if ((*mcount)++)
fprintf(stdout, ",");

fprintf(stdout, "{");
err = map_for_each(block->env, i3bar_print_pair, &pcount);
fprintf(stdout, "}");

if(full_text_copy)
{
map_set(block->env, "full_text", full_text_copy);
free(full_text_copy);
}

return err;
}

Expand Down