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

ticker: Initial support. Closes #466 #467

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Expand Up @@ -11,4 +11,4 @@ config.status
configure
i3blocks-config.h*
stamp-h1

cscope.out
12 changes: 11 additions & 1 deletion Makefile.am
Expand Up @@ -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 \
Expand All @@ -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
Expand Down
48 changes: 36 additions & 12 deletions bar.c
@@ -1,6 +1,6 @@
/*
* bar.c - status line handling functions
* Copyright (C) 2014-2019 Vivien Didelot
* Copyright (C) 2014-2023 Vivien Didelot, Bogdan Migunov
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -20,6 +20,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdbool.h>

#include "bar.h"
#include "block.h"
Expand All @@ -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)
{
Expand Down Expand Up @@ -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");
Expand All @@ -106,6 +107,20 @@ 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->interval > block->ticker->interval)
block_set_full_text_saved(block);

bar_print(bar);
}
}

block = block->next;
}
}
Expand Down Expand Up @@ -148,11 +163,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);
Expand Down Expand Up @@ -213,6 +229,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;
}

Expand Down
102 changes: 100 additions & 2 deletions block.c
Expand Up @@ -19,13 +19,16 @@
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>

#include "bar.h"
#include "block.h"
#include "json.h"
#include "line.h"
#include "log.h"
#include "sys.h"
#include "ticker.h"

const char *block_get(const struct block *block, const char *key)
{
Expand Down Expand Up @@ -113,8 +116,36 @@ 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 ||
block->interval > block->ticker->interval) {
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;
Expand Down Expand Up @@ -148,6 +179,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;
Expand Down Expand Up @@ -510,6 +571,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;
}

Expand Down Expand Up @@ -542,6 +636,8 @@ void block_destroy(struct block *block)
map_destroy(block->env);
if (block->name)
free(block->name);
if (block->ticker)
ticker_destroy(block->ticker);
free(block);
}

Expand All @@ -554,6 +650,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();
Expand Down
7 changes: 6 additions & 1 deletion block.h
@@ -1,6 +1,6 @@
/*
* block.h - definition of a block
* Copyright (C) 2014-2019 Vivien Didelot
* Copyright (C) 2014-2023 Vivien Didelot, Bogdan Migunov
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -20,10 +20,12 @@
#define BLOCK_H

#include <sys/types.h>
#include <stdbool.h>

#include "bar.h"
#include "log.h"
#include "map.h"
#include "ticker.h"

#define INTERVAL_ONCE -1
#define INTERVAL_REPEAT -2
Expand Down Expand Up @@ -60,6 +62,8 @@ struct block {
int code;
pid_t pid;

struct ticker *ticker;

struct block *next;
};

Expand Down Expand Up @@ -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 */
1 change: 1 addition & 0 deletions configure.ac
Expand Up @@ -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([
Expand Down
47 changes: 47 additions & 0 deletions docs/README.adoc
Expand Up @@ -65,6 +65,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:
Expand Down Expand Up @@ -320,6 +330,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.
Expand Down
2 changes: 1 addition & 1 deletion docs/blocklets.html
Expand Up @@ -480,4 +480,4 @@ <h1>Blocklets</h1>
</div>
</div>
</body>
</html>
</html>