mikaelpatel / Cosa

An Object-Oriented Platform for Arduino/AVR
https://mikaelpatel.github.io/Cosa/
GNU Lesser General Public License v2.1
338 stars 76 forks source link

Enhancement request: IOStream "position" query - beginning of line #424

Closed jeditekunum closed 9 years ago

jeditekunum commented 9 years ago

Since Cosa is not constrained by standards, this would be useful.

Consider an application that has a "Shell" that uses a prompt. The application also produces asynchronous output to the same stream that the shell uses. This output fragment demonstrates an example display (prompt is $ and <cr> means hitting the return key):

$ asynchronous message 1
asynchronous message 2
asynchronous message 3
<cr>
$ 

Wouldn't it be nice if the output looked like this (message 1 & 2 occur within one pass of loop for example):

$
asynchronous message 1
asynchronous message 2
$
asynchronous message 3
$ 

This should be really easy to do in Cosa by enhancing IOStream. Either keep an indicator of whether the last character(s) output to the stream was a CR/LF/CRLF (depending on Mode) or a count of the number of characters output since the last CR/LF/CRLF.

Application code producing the async messages could then check the state to know if a EOL needs to be output first. The Shell could do the same.

Obviously not terribly important at all - but something I've always desired on all platforms!

mikaelpatel commented 9 years ago

Hum, this actually sounds a lot like IOEvent. https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/IOEvent.hh. There is a short demo https://github.com/mikaelpatel/Cosa/blob/master/examples/Sandbox/CosaIOEvent/CosaIOEvent.ino.

This might be a starting point?

mikaelpatel commented 9 years ago

Hum, this is output handling. Not input :)

mikaelpatel commented 9 years ago

There is a mechanism in Linux to flush output/wait for write to compilete when a read is issued if the device is a tty. This is basically to start the read when the prompt is completed, etc. It can be view as a coupling between io-streams.

How would non-completed input lines be handled? Obviously there is an echo issue. Should the line with prompt be written (echoed) again? All this has to happen when the async message(s) is completed.

Anyway, I will do some thinking. Cheers!

jeditekunum commented 9 years ago

Its interesting that this kind of thing has never been solved broadly, if at all. Probably because of all the issues :smile:

Yes, I would think that reproducing the entire input line is the only way to handle input in progress.

The more I think about it, the character position within the line is not a perfect indicator. As the asynchronous message is being output, at some point it could be at the same position as the input expects. Perhaps a "line" counter in combination with position would help.

And then there is the possibility that the asynchronous message doesn't do EOL.

Perhaps a different tack is required... what if the shell was able to "push" itself as a "handler" in the output path? It could then "pause" the passing of output.

Long ago I implemented a replacement C library that allowed the stacking of io streams (think of the VFS mechanism for file systems). For example, I could push a timestamping handler on an output stream - every line of output would then be prefixed with the timestamp.

Perhaps enhancing IOStream to allow stacking of handlers would be a generalized solution that would have interesting applications.

jeditekunum commented 9 years ago

This is too much work for the value.

mikaelpatel commented 9 years ago

"Nja" as the Swedish saying goes. I think you are actually on to something important here but I really need to do some deep thinking and look at some use-cases. Right now I don't now how to approach an implementation. Have not found the "angle" yet :). I think we will get back to this.

jeditekunum commented 9 years ago

On Sep 25, 2015, at 7:33 AM, Mikael Patel notifications@github.com wrote:

"Nja" as the Swedish saying goes. I think you are actually on to something important here but I really need to do some deep thinking and look at some use-cases. Right now I don't now how to approach an implementation. Have not found the "angle" yet :). I think we will get back to this.

I assume you are referring to the idea of generalized stacking of I/O. I’ll give some general info of what I’ve done before in case it is useful.

I had a component called vios (Virtual IO Stream) that was nothing more than the framework and push/pop. Since it was C, a descriptor was a pointer to a set of pointers to handlers for ops, attributes (“ioctl”-like settings for each layer), and stack linkage.

Buffering was done by pushing a buffering component onto a stream.

As I said, I had a timestamping component. Also had a component that added process and thread id.

I suppose a component could do arbitrary translations too.

Never got around to doing anything special with input stacks and never thought of applying to controlling interleaving output.

Wasn’t an original idea by any means. VFS is one example. Even older is STREAMS - Wikipedia, the free encyclopedia https://en.wikipedia.org/wiki/STREAMS. Its a powerful concept although I believe SysV Streams have been removed from some OSes (Solaris?) because of performance issues. Never got into Linux.

Anyway, might be an interesting thing to look at if/when you run out of things to do. ;)