asciimatics icon indicating copy to clipboard operation
asciimatics copied to clipboard

Left to right rendering effect

Open mjip opened this issue 5 years ago • 11 comments
trafficstars

Is your feature request related to a problem? Please describe. I would like for an effect to render text (or ASCII characters) from left to right, like it's being typed out.

Describe the solution you'd like Similar to the mirage effect (where text can be rendered one character at a time, only randomly), it would be cool to have text rendered one letter at a time from left to right, so it appears to be typed in real-time.

mjip avatar Jul 12 '20 23:07 mjip

Makes sense. I get the idea... Would you be interested in implementing it? Should be relatively easy to use Mirage as a template for the new Effect and change the logic to maintain a count of where you've got to in the text to be displayed and just print up to that (then increment the counter for the next update)...

peterbrittain avatar Jul 13 '20 08:07 peterbrittain

Yep, PR incoming :^) It was relatively easy using the Mirage class as a template

mjip avatar Jul 13 '20 18:07 mjip

I was able to implement this by extending DynamicRenderer. The bars.py really helped in understanding how DynamicRenderer works, thanks for all the examples!

When I instantiate an object of the class mentioned above, I pass in the text I want to be printed one character at a time, and save the state of how much of that text has been consumed inside an instance attribute, each time DynamicRenderer is called. This could be another way of adding the Typewriter effect to asciimatics, I would love to see this in the basics.py example! It looks like this:

gif

The API to use this class looks similar to this:

Print(
    screen,
    Typewriter(text="import os", width=100, height=100),
    y,
    x=x,
    colour=Screen.COLOUR_WHITE,
    bg=Screen.COLOUR_BLACK,
    transparent=False,
    speed=4,
)

@peterbrittain What do you think about the implementation? I can work on creating a PR based on the fixes / API changes that you suggest. Also, I'm not sure how it should work with FigletText.

Should it also have an option to print the text all at once instead of one character at a time? Or should that be left to another Print() with static text?

vinayak-mehta avatar Aug 25 '20 12:08 vinayak-mehta

Thanks @vinayak-mehta . That looks great! Sorry for the delay... I've been thinking about the best way to handle these things.

After much musing, I think that it makes most sense for this to be a chained renderer that takes another renderer as input and gradually displays the content of that renderer using similar logic to your existing renderer. Key benefit is that this allows more composition (e.g. for another renderer that supports coloured text, which could be the existing StaticRenderer right now or a future syntax highlighting renderer for your code example).

This slightly complicates your simple case (just type some pre-defined text), but only by adding one more function call. For example:

Print(
    screen,
    Typewriter(text=StaticRenderer(images=["import os"]), width=100, height=100),
    y
)

What do you think? Is that worth the change to your code?

BTW - I don't think we should worry about FigletText. Frankly, doing that a letter at a time will require detailed knowledge of the figlet font and so will be a separate custom renderer (which we can worry about another day).

peterbrittain avatar Aug 26 '20 22:08 peterbrittain

@peterbrittain Sorry for the late reply, this week has been hectic but I'm planning to work on this over the weekend!

After much musing, I think that it makes most sense for this to be a chained renderer that takes another renderer as input and gradually displays the content of that renderer using similar logic to your existing renderer. Key benefit is that this allows more composition (e.g. for another renderer that supports coloured text, which could be the existing StaticRenderer right now or a future syntax highlighting renderer for your code example).

This is a great suggestion and makes a lot of sense, I hadn't thought about this. A future syntax highlightning renderer would be awesome! Can you give me some pointers on how to make something like syntax highlighting work? Right now I'm using DynamicRenderer's _write() method to do something like self._write(text, x, y, colour=Screen.COLOUR_GREEN) to print colored text. Would syntax highlighting involve doing multiple self._write calls for different parts of the code at different coordinates with different colors? Is there another way?

What do you think? Is that worth the change to your code?

The suggestion makes a lot of sense. I guess instead of extending DynamicRenderer in the implementation I mention above, I could just use Typewriter and have a list of static and dynamic Print objects to simulate a terminal session playback.

BTW - I don't think we should worry about FigletText. Frankly, doing that a letter at a time will require detailed knowledge of the figlet font and so will be a separate custom renderer (which we can worry about another day).

:+1:

vinayak-mehta avatar Aug 28 '20 14:08 vinayak-mehta

@vinayak-mehta I'm not quite sure what you're getting at for possible implementation... Let me try to elucidate what I meant.

Have a look at the Rainbow renderer and how it is used. You could use something similar for a Typewriter renderer. Instead of adding volours, you could use the full text and colour map and just return an extra character each time. Using a dynamic renderer that writes directly to the buffer would be more memory efficient and so better.

To create a syntax colouring option, I suggest we create a renderer that can use a parser to convert a blob of text into text/colour map. The next step would be to create a pygments parser to use in that renderer.

peterbrittain avatar Aug 29 '20 14:08 peterbrittain

Thanks for the pointer! I'll have to look into the Rainbow renderer and learn how color maps work. I took a look at the xmas.py example to see how the ${c,a,b} syntax works and it makes sense to me now! I didn't know about this syntax before. I was able to use it to add text formatting support to present!

I'll try to work on the Typewriter PR today.

On a separate note, would you like a PR to add a Screen.A_ITALIC attr (and maybe some other attrs too)? I saw that Python 3.7 added A_ITALIC in the curses module. I guess this change would have to be added in a backwards compatible way.

vinayak-mehta avatar Aug 29 '20 23:08 vinayak-mehta

Thanks for the offer, but I don't think we should add more attributes. I've tried to keep asciimatics limited to stuff that you can do in all environments and deliberately avoided the less well supported ones. In the case for italics, it is only possible to do that in recent builds of Windows 10 (that support ansi escape codes). It might make sense to try that out once I have added support for that screen type, but not just yet.

peterbrittain avatar Aug 30 '20 08:08 peterbrittain

Makes sense :+1:

Sorry for being inactive on the implementation. I've been busy with some other deadlines + a medical emergency at home. I will get back to this as soon as I can find time.

vinayak-mehta avatar Sep 01 '20 22:09 vinayak-mehta

NP. Real life always comes first...

peterbrittain avatar Sep 02 '20 08:09 peterbrittain

This issue has various ideas in it, which are still worth doing at some point. For now I just wanted to flag that the AnsiArtPlayer and AsciinemaPlayer renderers may do what you want in some cases.

peterbrittain avatar Jun 23 '21 21:06 peterbrittain