swiftbar / SwiftBar

Powerful macOS menu bar customization tool
https://swiftbar.app
MIT License
2.93k stars 92 forks source link

fix(streamable): Append read stream buffer to ongoing response for long items #372

Closed peanball closed 1 year ago

peanball commented 1 year ago

Process output is streamed into a buffer. By default this buffer fits 4k characters, which is too short for image data.

With this change, if this block does not contain a stream separator, the complete block is appended to the in-progress content stored so far.

Fixes #371.

peanball commented 1 year ago

Added conditional check for a future "SwiftBar 1.5.0" in https://github.com/peanball/music-swiftbar. The plugin falls back to not putting the artwork if SwiftBar is older than that. I will adapt to the correct version, in which this functionality is included.

melonamin commented 1 year ago

Hi @peanball, thanks for working on this ❤️

By default this buffer fits 4k characters

Do you happen to have a reference to documentation for this? I remember debugging this at some point, but couldn't make heads or tails of it.

The change itself looks straigthforward enough 👍

peanball commented 1 year ago

Observation in the debugger. And 4K seemed reasonable as default set limit.

There is some docs on the the behaviour of reading data, which is limited to a buffer when reading from a stream, or until end of file when reading from a file. In this case the first applies. I can find the reference later if needed.

While working on the plug-in with streaming album set the image NSData kept ending up with just shy of 4K bytes, then I dug a bit deeper.

I've tested it now with streaming plugins that do more and less than 4K bytes per update and both work as expected.

Edit, found the bit of documentation I mention above: FileHandle.availableData:

Discussion The data currently available through the receiver, up to the maximum size that can be represented by an NSData object.
If the receiver is a file, this method returns the data obtained by reading the file from the current file pointer to the end of the file. If the receiver is a communications channel, this method reads up to a buffer of data and returns it; if no data is available, the method blocks. Returns an empty data object if the end of file is reached. This method raises NSFileHandleOperationException if attempts to determine the file-handle type fail or if attempts to read from the file or channel fail.

The buffer size is not documented explicitly though.

peanball commented 1 year ago

Regarding the streamSeparator, you expect for ~~~ to show up, where the separator in the stream would actually be (^|\n)~~~(\n|$), i.e. should be in its own line. Right now this would match some string~~~here | sfimage=:cloud.fill: I think. But that's a different issue altogether.

peanball commented 1 year ago

I'm reviewing this again and I think adding it to the guard where I added it is not the right place. Debugging some more to get the right place. Will put it back to ready for review when I'm done.

It's fine after all. The guard acts when either there is only a single line in the next chunk read from the stream (what was there before), or there is no separator at all in the block.

The no separator in the block condition applies to leading and trailing separator equally and can thus be done before evaluating that condition.

.content is not set in this case on purpose, as there is potentially no complete separated set of items to display.

melonamin commented 1 year ago

Can you please share the plugin you’re working on? I want to test it.

peanball commented 1 year ago

It's the one I mention above, https://github.com/peanball/music-swiftbar

And the swift script version of that, not the python version. I don't think I'll keep the python version around for much longer.