i3blocks
i3blocks copied to clipboard
Blocks no longer render when output doesn't end with newline
About half of my blocks stopped rendering after updating today. I looked through i3blocks -vvv
and noticed that only the blocks that were printing were getting log lines from line.c
<7>line.c:line_parse:65: &3:000: {{block output}}
Looking around there it seems i3blocks can only read lines if they end with a newline.
I added an extra echo
to the end of all my missing blocks and they re-appeared.
I think a fix would be to accept the error indicating the end of the file descriptor as a valid endpoint to the line and break. I think this would be sufficient:
if (err) {
if (err == -EAGAIN)
break;
return err;
}
I'm hesitant to submit a PR because I'm having problems getting the build to work.
Edit: I got the build working so I submitted a PR which fixed my problem.
Doesn't it simpler and more straightforward to explicitly tell i3blocks
where your line ends (for example by a new-line character?), than relying on such hacks?
If you have problems with extra echo
-s just add the missing new-line characters to your prints.
@zsugabubus
- I colorize my blocks with a script that doesn't add newlines because it may want to color multiple things on the same line. I would have to print an extra newline after the color script regardless.
- Why tell i3blocks to create a new line? I'm not printing anything else on a new line. All my output is just the one line. As far as I know, i3blocks doesn't support multiple lines.
- I don't think "print the text I give you" is a hack.
I colorize my blocks with a script that doesn't add newlines because it may want to color multiple things on the same line.
My bad, but I hardly can understand your scenario. Could you provide more details/or an example maybe?
Why tell i3blocks to create a new line?
It just marks the end of the text you want to be displayed/updated. Nobody wants multiple lines.
I'm not printing anything else on a new line. I don't think "print the text I give you" is a hack.
while :; do
echo -n a
echo -n b
sleep 1
done
What should it print? ab
, b
, or ababababababababa...
? Perhaps b
, aba
than babababa
...? When do you say that "whew, I'm ready with my line, hey i3blocks, I want it to be displayed on the screen"?
@zsugabubus That would never finish, so i3blocks would never read any of it. It spawns the process, waits for it to finish, then reads the content that was written.
You say "whew, I'm ready with my line, hey i3blocks, I want it to be displayed on the screen" by finishing the script or exit 0
Oh my god... now I see what's everybody's issue. I supposed you use interval=persist
because (I run almost all of my blocklets like this and) you mentioned EAGAIN
and... and... I didn't dare to think about that it could be an issue.
Could you provide more details/or an example maybe?
[time]
command=echo -n $(date +%T)
interval=once
@shreve, fyi:
As far as I know, i3blocks doesn't support multiple lines.
Does not display multiple lines, but i3blocks handles the following (from non-persistent blocks at least):
full text
short text
color
all strings must end with a newline in the 1.5 release.
Sorry but I have trouble understanding where is the problem. Regardless the interval type or format, I expect each line from a block output to be newline terminated, for consistency. Although I should've mentioned that in the release note, and I will.
I colorize my blocks with a script that doesn't add newlines because it may want to color multiple things on the same line.
My bad, but I hardly can understand your scenario. Could you provide more details/or an example maybe?
Why tell i3blocks to create a new line?
It just marks the end of the text you want to be displayed/updated. Nobody wants multiple lines.
I'm not printing anything else on a new line. I don't think "print the text I give you" is a hack.
while :; do echo -n a echo -n b sleep 1 done
What should it print?
ab
,b
, orababababababababa...
? Perhapsb
,aba
thanbabababa
...? When do you say that "whew, I'm ready with my line, hey i3blocks, I want it to be displayed on the screen"?
@zsugabubus nailed it, fetching complex data and printing it as you receive it makes it impossible to know where it ends, and that's not i3blocks job. For example, I could've assumed that once the output buffer is flushed, then the data is considered ready. But 1) you have a race condition (you can have more data written while you're reading the output) 2) it can be complex for the user to deal with buffered I/O, since it requires this programming knowledge and all languages and libraries handle that differently (i.e. some provide buffered I/O, some don't, some flush right away, some don't). So I decided to go with the newline, which is the idiomatic way to tell a program that a line is ready to be processed (pretty much the same as pressing Enter on your keyboard with an interactive program actually).
(Note: with persistent blocks, a user still need to flush its output buffer in order to make it readable by i3blocks, but the line reading code will stop once it encounters a newline and won't consume the text that comes after.)
So in 1.5 I've factorized the code and decided to go entirely line-based, to simplify the processing of (INI-style) config files, json lines (clicks) or block outputs. All text processing now use the same code, which is less error prone. That said, I could've and should've made the code retro-compatible somehow and accept non-newline terminated output for non-persistent blocks. Sorry for the inconvenience.
Closing as it's a duplicate of #393