From 939a485d411c644020cfacfeda17994e4573172f Mon Sep 17 00:00:00 2001
From: ivan <522518+ivanmilov@users.noreply.github.com>
Date: Sun, 3 Nov 2019 20:29:07 +0100
Subject: [PATCH 1/2] added style support
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
With this PR you can make statusbar output looks like e.g. powerline.
Example there: https://i.redd.it/13a2zz2ifjw31.png
New field in config: full_text_pattern
Value of this pattern will be parsed and all values surrounded by '%' will be used as parameter keys.
Values started with '&' - are references on another parameter keys.
Demo config example:
```
command=~/.config/i3/i3blocksScripts/$BLOCK_NAME
separator_block_width=0
markup=pango
color1=#ffffffa0
color2=#000000a0
background=#000000a0
separator_glyph=
full_text_pattern=%separator_glyph%%full_text%
gbg=&fg
gfg=&bg
[foo]
command=echo foo
bg=&color1
fg=&color2
interval=once
[bar]
command=echo bar
bg=&color2
fg=&color1
interval=once
```
i3 config:
```
bar {
position top
i3bar_command i3bar -t 0.1
colors{
background #000000a0
}
status_command i3blocks -c demo.conf
}
```
---
i3bar.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/i3bar.c b/i3bar.c
index 30fb989b..3af5fd77 100644
--- a/i3bar.c
+++ b/i3bar.c
@@ -23,6 +23,7 @@
#include "log.h"
#include "map.h"
#include "term.h"
+#include
/* See https://i3wm.org/docs/i3bar-protocol.html for details */
@@ -148,6 +149,78 @@ static int i3bar_print_pair(const char *key, const char *value, void *data)
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 *ptr = strtok(pattern_copy, delim);
+ bool token = false;
+ while(ptr != NULL)
+ {
+ if(token)
+ {
+ const char *value = map_get(block->env, ptr);
+ 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.", ptr);
+ return 1;
+ }
+ }
+ else
+ strcat(res, ptr);
+
+ token = !token;
+ ptr = 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");
@@ -161,6 +234,21 @@ 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, ",");
@@ -168,6 +256,12 @@ static int i3bar_print_block(struct block *block, void *data)
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;
}
From 96e69299b13c54c507409e7eb085a699f5debd41 Mon Sep 17 00:00:00 2001
From: Ivan Milov <522518+ivanmilov@users.noreply.github.com>
Date: Tue, 9 Feb 2021 17:07:21 +0100
Subject: [PATCH 2/2] escape ampersand
---
i3bar.c | 40 ++++++++++++++++++++++++++++++++++------
1 file changed, 34 insertions(+), 6 deletions(-)
diff --git a/i3bar.c b/i3bar.c
index 3af5fd77..ba57b344 100644
--- a/i3bar.c
+++ b/i3bar.c
@@ -105,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);
@@ -144,6 +164,14 @@ static int i3bar_print_pair(const char *key, const char *value, void *data)
if ((*pcount)++)
fprintf(stdout, ",");
+ // escape [& -> &]
+ 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;
@@ -187,13 +215,13 @@ static int i3bar_parse_pattern(struct block *block, const char *pattern, char *r
// TODO: use strdup
strcpy(pattern_copy, pattern);
- char *ptr = strtok(pattern_copy, delim);
+ char *key = strtok(pattern_copy, delim);
bool token = false;
- while(ptr != NULL)
+ while(key != NULL)
{
if(token)
{
- const char *value = map_get(block->env, ptr);
+ const char *value = map_get(block->env, key);
if(value != NULL)
{
const char *final_value = i3bar_get_value_by_ref(value, block);
@@ -207,15 +235,15 @@ static int i3bar_parse_pattern(struct block *block, const char *pattern, char *r
}
else
{
- block_debug(block, "Key %s is not defined.", ptr);
+ block_debug(block, "Key %s is not defined.", key);
return 1;
}
}
else
- strcat(res, ptr);
+ strcat(res, key);
token = !token;
- ptr = strtok(NULL, delim);
+ key = strtok(NULL, delim);
}
return 0;