diff --git a/.gitignore b/.gitignore index d2e05475..c0ce76f5 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ config.status configure i3blocks-config.h* stamp-h1 - +cscope.out diff --git a/Makefile.am b/Makefile.am index d755a2b8..d725f03c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,6 +2,14 @@ DEFS += \ -DSYSCONFDIR=\"$(sysconfdir)\" bin_PROGRAMS = i3blocks + +i3blocks_CFLAGS = \ + $(AM_CFLAGS) \ + $(UTF8PROC_CFLAGS) + +i3blocks_LDADD = \ + $(UTF8PROC_LIBS) + i3blocks_SOURCES = \ bar.c \ bar.h \ @@ -22,7 +30,9 @@ i3blocks_SOURCES = \ map.h \ sys.c \ sys.h \ - term.h + term.h \ + ticker.c \ + ticker.h dist_man1_MANS = \ docs/i3blocks.1 diff --git a/bar.c b/bar.c index 57089561..e8c0fdec 100644 --- a/bar.c +++ b/bar.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "bar.h" #include "block.h" @@ -28,9 +29,9 @@ #include "line.h" #include "log.h" #include "map.h" -#include "sched.h" #include "sys.h" #include "term.h" +#include "ticker.h" static void bar_read(struct bar *bar) { @@ -88,16 +89,16 @@ static void bar_poll_timed(struct bar *bar) static void bar_poll_expired(struct bar *bar) { struct block *block = bar->blocks; + unsigned long now, next_update; + int err; + + err = sys_gettime(&now); + if (err) + return; while (block) { if (block->interval > 0) { - const unsigned long next_update = block->timestamp + block->interval; - unsigned long now; - int err; - - err = sys_gettime(&now); - if (err) - return; + next_update = block->timestamp + block->interval; if (((long) (next_update - now)) <= 0) { block_debug(block, "expired"); @@ -106,6 +107,19 @@ static void bar_poll_expired(struct bar *bar) } } + if (block->ticker && block->ticker->interval > 0) { + next_update = block->ticker->timestamp + block->ticker->interval; + + if (((long) (next_update - now)) <= 0) { + block_debug(block, "ticker expired"); + + if (block->interval == 0 || block->interval == INTERVAL_ONCE) + block_set_full_text_saved(block); + + bar_print(bar); + } + } + block = block->next; } } @@ -148,11 +162,12 @@ static void bar_poll_exited(struct bar *bar) if (block) { block_debug(block, "exited"); block_reap(block); - if (block->interval == INTERVAL_PERSIST) { + + if (block->interval == INTERVAL_PERSIST) block_debug(block, "unexpected exit?"); - } else { + else block_update(block); - } + block_close(block); if (block->interval == INTERVAL_REPEAT) { block_spawn(block); @@ -213,6 +228,14 @@ static int bar_setup(struct bar *bar) sleeptime = block->interval; } + if (block->ticker) + if (sleeptime > 0 && + sleeptime > gcd(sleeptime, block->ticker->interval)) + sleeptime = gcd(sleeptime, block->ticker->interval); + else + if (block->ticker->interval < block->interval) + sleeptime = block->ticker->interval; + block = block->next; } diff --git a/block.c b/block.c index c24fb0a1..382aa99d 100644 --- a/block.c +++ b/block.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "bar.h" #include "block.h" @@ -26,6 +28,7 @@ #include "line.h" #include "log.h" #include "sys.h" +#include "ticker.h" const char *block_get(const struct block *block, const char *key) { @@ -113,8 +116,35 @@ static int block_stdout(struct block *block) /* Deprecated label */ label = block_get(block, "label"); full_text = block_get(block, "full_text"); - if (label && full_text) { - snprintf(buf, sizeof(buf), "%s%s", label, full_text); + + memset(buf, '\0', BUFSIZ); + + if (full_text && (label || block->ticker)) { + char *ticker_output = NULL; + size_t label_strlen = 0; + + if (label) + label_strlen = snprintf(buf, sizeof(buf), "%s", label); + + if (block->ticker && block->format == FORMAT_RAW) { + ticker_output = ticker_output_get(block->ticker, full_text); + + if (block->interval == 0 || block->interval == INTERVAL_ONCE) { + free(block->ticker->full_text_saved); + free(block->ticker->label_saved); + + block->ticker->full_text_saved = strdup(full_text); + if (label) + block->ticker->label_saved = strdup(label); + } + } + + if (ticker_output) { + strncat(buf, ticker_output, BUFSIZ - label_strlen); + free(ticker_output); + } else + strncat(buf, full_text, BUFSIZ - label_strlen); + err = block_set(block, "full_text", buf); if (err) return err; @@ -148,6 +178,36 @@ int block_update(struct block *block) return 0; } +void block_set_full_text_saved(struct block *block) +{ + char buf[BUFSIZ]; + + memset(buf, '\0', BUFSIZ); + + if (block->ticker && block->ticker->full_text_saved) { + size_t label_strlen = 0; + char *ticker_output = NULL; + + if (block->ticker->label_saved) + label_strlen = snprintf(buf, sizeof(buf), "%s", + block->ticker->label_saved); + + if (block->ticker && block->format == FORMAT_RAW) + ticker_output = ticker_output_get(block->ticker, + block->ticker->full_text_saved); + + if (ticker_output) { + strncat(buf, ticker_output, BUFSIZ - label_strlen); + free(ticker_output); + } else + strncat(buf, block->ticker->full_text_saved, BUFSIZ - label_strlen); + } + + block_set(block, "full_text", buf); + + return; +} + static int block_send_key(const char *key, const char *value, void *data) { struct block *block = data; @@ -510,6 +570,39 @@ static int i3blocks_setup(struct block *block) else block->signal = atoi(value); + value = map_get(block->config, TICKER_CONFIG_OPTION); + if (value && strcmp(value, "true") == 0) + block->ticker = ticker_create(); + + if (block->ticker) { + value = map_get(block->config, TICKER_CONFIG_OPTION_DELIMETER); + if (!value || (ticker_delimeter_set(block->ticker, value) + != TICKER_RESULT_SUCCESS)) { + debug("Failed to set ticker delimeter. Setting default delimeter"); + block->ticker->delimeter = TICKER_DELIMETER_DEFAULT; + } + + value = map_get(block->config, TICKER_CONFIG_OPTION_DIRECTION); + if (value && (strcmp(value, "left") == 0 || strcmp(value, "l") == 0)) + block->ticker->direction = TICKER_DIRECTION_LEFT; + else if (value && (strcmp(value, "right") == 0 || strcmp(value, "r") == 0)) + block->ticker->direction = TICKER_DIRECTION_RIGHT; + else + block->ticker->direction = TICKER_DIRECTION_DEFAULT; + + value = map_get(block->config, TICKER_CONFIG_OPTION_CHARS_LIMIT); + if (value && (atoi(value) > 0)) + block->ticker->chars_limit = atoi(value); + else + block->ticker->chars_limit = TICKER_CHARS_LIMIT_DEFAULT; + + value = map_get(block->config, TICKER_CONFIG_OPTION_INTERVAL); + if (value && (atoi(value) > 0)) + block->ticker->interval = atoi(value); + else + block->ticker->interval = TICKER_INTERVAL_DEFAULT; + } + return 0; } @@ -536,9 +629,12 @@ int block_setup(struct block *block) void block_destroy(struct block *block) { + debug("block_destroy"); map_destroy(block->config); map_destroy(block->env); free(block->name); + if (block->ticker) + ticker_destroy(block->ticker); free(block); } @@ -551,6 +647,8 @@ struct block *block_create(struct bar *bar, const struct map *config) if (!block) return NULL; + block->ticker = NULL; + block->bar = bar; block->config = map_create(); diff --git a/block.h b/block.h index a978ee3f..40fae10e 100644 --- a/block.h +++ b/block.h @@ -20,10 +20,12 @@ #define BLOCK_H #include +#include #include "bar.h" #include "log.h" #include "map.h" +#include "ticker.h" #define INTERVAL_ONCE -1 #define INTERVAL_REPEAT -2 @@ -60,6 +62,8 @@ struct block { int code; pid_t pid; + struct ticker *ticker; + struct block *next; }; @@ -107,6 +111,7 @@ int block_spawn(struct block *block); void block_touch(struct block *block); int block_reap(struct block *block); int block_update(struct block *block); +void block_set_full_text_saved(struct block *block); void block_close(struct block *block); #endif /* BLOCK_H */ diff --git a/configure.ac b/configure.ac index 1cab4a07..5db07297 100644 --- a/configure.ac +++ b/configure.ac @@ -7,6 +7,7 @@ PKG_CHECK_MODULES([BASH_COMPLETION], [bash-completion >= 2.0], [BASH_COMPLETION_DIR="$(pkg-config --variable=completionsdir bash-completion)"], [BASH_COMPLETION_DIR="$datadir/bash-completion/completions"] ) +PKG_CHECK_MODULES([UTF8PROC], [libutf8proc]) AC_SUBST([BASH_COMPLETION_DIR]) AM_CONDITIONAL([ENABLE_BASH_COMPLETION],[test "xBASH_COMPLETION_DIR" != "x"]) AC_CONFIG_FILES([ diff --git a/docs/README.adoc b/docs/README.adoc index cf18c1df..fc426ea7 100644 --- a/docs/README.adoc +++ b/docs/README.adoc @@ -63,6 +63,16 @@ make make install ---- +=== Dependencies + +Since ticker feature has been introduced, there is only one package (link:https://github.com/JuliaStrings/utf8proc[libutf8proc]) which is need to be installed. On Debian-based systems it can be obtained via apt: + +[source] +---- +sudo apt-get install libutf8proc-dev +---- + + == Getting started In your i3 configuration file, define {progname} as the link:https://i3wm.org/docs/userguide.html#status_command[status line command] of a new bar block: @@ -316,6 +326,43 @@ format=json interval=1 ---- + +=== ticker + +Optional property. Enable or disable ticker feature. Valid values are `true` & `false`. +This feature only works with the raw format. It will scroll output string char by char with given interval. Offset zeroes if there are changes in the output string. +Default value is `false`. + +[source,ini] +---- +#Output string differs every minute +[ticker_test] +command=echo 'TEST_STRING-'$(date +%M) +interval=1 +ticker=true +ticker_interval=2 +---- + +==== ticker_delimeter + +Optional property (use in conjunction with _ticker_). Delimeter character which separates beginning & ending of the output string. If value is set to a string containing multiple characters, only the first character will be used as the delimeter. +Default value is `|`. + +==== ticker_direction + +Direction of the ticker. Valid values are `right` (shortcut `r`) & `left` (shortcut `l`). +Default value is `left`. + +==== ticker_chars_limit + +Limit of the characters to be displayed if _ticker_ is enabled. `0` or negative values set limit to default value. +Default value is `16`. + +==== ticker_interval + +Optional property. Defines interval of time after which the output string is shifted by a single char. +Default value is `1`. + == Click When you click on a block, data such as the button number and coordinates are merged into the block variables. diff --git a/docs/blocklets.html b/docs/blocklets.html index 56484338..14d0a730 100644 --- a/docs/blocklets.html +++ b/docs/blocklets.html @@ -4,7 +4,7 @@ - + Blocklets