sway
sway copied to clipboard
swaybar shows multiple status lines at once
- Sway Version:
sway version 1.2-rc2 (Aug 23 2019, Arch Linux)
- Configuration File:
bar {
status_command tail -f ~/sway-status.txt
}
When status command initially immediately outputs multiple lines, they all are shown on the swaybar. When after that the command outputs more lines, only the last line is shown.
Swaybar should always display only the last status line.
To reproduce, create a file ~/sway-status.txt with multiple short lines of text. Set status_command to output that file:
swaymsg bar bar-0 status_command "tail -f ~/sway-status.txt"
I cannot seem to reproduce your issue. screenshot of what I managed to reproduce
Also, could we get a little bit more information regarding what you are trying to achieve? It seems a little unorthodox to be creating a status bar in this way (running tail on a text file).
@samerickson Your screenshot shows exactly the issue. You should only see the last line, "sizth line" as the status.
What I'm trying to achieve
Status command may want to output information as soon as it's available. If shortly after that another piece of information is available, it will output another line. Normally, it works fine. Only if multiple updates happened during the bar startup, both old and new status appear together.
As an example, my program is affected. https://github.com/shibe2/sklt
I misunderstood the issue, I thought you were having multiple status bars. Status bars will display newline characters inline. This is useful if you want something like lsblk to be displayed, which is normally a block of text, but in a status bar, you need that information to be in a single line.
In your case, if you are trying to only display the last line of the file, you need to change your tail command. Tail defaults to showing the last 10 lines of a file, to make it display Only the last line, use: tail -n 1.
As for getting your project to function correctly, I have created an issue https://github.com/shibe2/sklt/issues/1, as I cannot seem to make your project function.
You can change your bar config to link to a script containing the following:
#!/bin/bash
while true;
printf "%s %s\n" "$(date +%D)" "$(date +%r)"
sleep 1
done
As for getting it to display the current keyboard layout, you can have a look at this project as well: https://gitlab.com/racy/sway-keyboard-layout/blob/master/sway-keyboard-layout. This makes your code footprint a lot smaller, but I am unsure of the resource consumption differences.
Thanks for your prompt reply on the sklt issue. Everything appears to work, though for the first minute you have the time listed twice. To circumvent this, it would be best to remove the date in your project its self, rather than trying to remove it using command-line utilities such as tail
Status bars will display newline characters inline. This is useful if you want something like lsblk to be displayed, which is normally a block of text, but in a status bar, you need that information to be in a single line.
This is not useful with line protocol, where each line is a new status. But even if it was useful, it is currently inconsistent: if the command outputs multiple lines immediately, they appear together; but if it does after some delay, only the last line appears.
In your case, if you are trying to only display the last line of the file, you need to change your tail command.
To be clear, my tail example is purely for reproduction of the issue.
I also have a program that only outputs time. It uses less resources and it is more precise than a simple script. I.e. the time on screen updates almost exactly when the second changes on the computer clock.
As for your suggestion about keyboard layout, it seems to use xkblayout command, and I can't find it in Arch Linux repositories. Also, I tried to use X protocol for getting the current keyboard layout, but the change notification did not work under Wayland. And polling requires a compromise between CPU usage and indicator lag, so I'd like to avoid it. With Sway 1.2 it is possible to get proper notifications about keyboard layout switching, which I used in my program.
This seems like an easy fix for anyone interested; just add some logic here: https://github.com/swaywm/sway/blob/master/swaybar/status_line.c#L117 to find the last line that was read.
@ianyfan, for testing purposes, how can I get my built (but not installed) sway branch to stop using the system swaybar? Doesn't seem to respect $PATH
It should use PATH. You can also set swaybar_command.
Or start it manually. For example, if you've compiled it in a directory called build, then you should be able to invoke it like build/swaybar/swaybar -b bar-0 (replacing the bar id appropriately).
:eyes:
This seems like an easy fix for anyone interested; just add some logic here: https://github.com/swaywm/sway/blob/master/swaybar/status_line.c#L117 to find the last line that was read.
Hello. Based on what I understood from the issue and the comment above, I believe I solved the issue with the following code (starting from https://github.com/swaywm/sway/blob/master/swaybar/status_line.c#L114):
sway_log(SWAY_DEBUG, "Using text protocol.");
status->protocol = PROTOCOL_TEXT;
// Gets starting address (relative to buffer) of last line on file
size_t i;
size_t lastline = i = 0;
while(status->buffer[i] != '\0' && i <= status->buffer_size) {
if(status->buffer[i] == '\n' && status->buffer[i+1] != '\0') {
lastline = i + 1;
}
i++;
}
status->text = status->buffer + lastline; // <== ASSIGN HERE
// intentional fall-through
case PROTOCOL_TEXT:
while (true) {
if (status->buffer[read_bytes - 1] == '\n') {
status->buffer[read_bytes - 1] = '\0';
}
errno = 0;
read_bytes = getline(&status->buffer,
&status->buffer_size, status->read);
if (errno == EAGAIN) {
clearerr(status->read);
return true;
} else if (errno) {
status_error(status, "[error reading from status command]");
return true;
}
status->text = status->buffer; // <== REASSIGN HERE
}
case PROTOCOL_I3BAR:
status->text = status->buffer; // <== REASSIGN HERE
return i3bar_handle_readable(status);
Notice I had to reassign status->text three times in the code, otherwise the pointer would get stuck and the output wouldn't update correctly (obviously I would remove the comments in upper case on PR). I believe the logic here is correct, but is the code appropriate for merging? And if not, how would I write the code to be more secure/appropriate to the project? Since this would be my first time contributing, and I didn't find any specifications on how to do so, I figured it would be better to ask than to bother anyone with phony PRs. Thank you!