Terminal-Print
Terminal-Print copied to clipboard
Before 1.0
This is just a rough collection of thoughts on what we'd need before we started the drive for 1.0:
- Implementation
- Clean up, fill in, and solidify existing API
- Decide whether we're going to do high-level widgets, layout, styling, etc. in this module or a separate, higher-level module space (I personally am thinking the latter would be wise at this point)
- Whether internal or external, substantially implement high-level API so as to prove out low-level API
- Testing
- Figure out how to reasonably test all this in a non-labor-intense and not-slow-as-heck way
- Fill out the test suite
- Set up CI and other tooling
- Docs
- Document the API (overall structure as well as details)
- Expand readme/contributing/internals docs
- Decide on a mechanism for recognizing contributors, and do so
Regarding recognition: I've added you to both META6.json and the Readme. I was thinking that core contributors should go into META6 and the Readme would be a slightly longer list of people who are active in tickets and the like but haven't yet contributed significant amounts of code.
My apologies for not getting you this kind of formal recognition earlier, by the way!
Thank you!
Yeah, your plan seems reasonable. If we ever have so many contributors that we need a separate doc for it, we'll call that A Good Problem To Have. :-)
~~I've just pushed a new branch no-cell-class that removes the internal/eternal question of "is this a Cell?" introspection.~~
~~It did not have quite as dramatic an improvement on speed as I would have liked, but either I've got confirmation bias or it's rendering a bit more smoothly (or both).~~
~~My motivation in this change from a design standpoint was to reduce the internal complexity a bit while also giving cells a more extreme flexibility.~~
~~For instance, we could special case a render key in the details hash (a named arg which has kind of merged Cell and %c) where end users can put subroutines that take the details hash itself as the arg (ie, my &render = %details<render>:delete; render(%details);).~~
~~I'm curious to hear what you think!~~
EDIT: I have abandoned this approach as none of my attempts have managed a speedup. I thought that maybe this line was a place we could speed up Terminal::Print by removing (supposedly) costly smartmatch introspection and object construction.
Well, the immutable Cell approach was unbeatable in my replacement (using immutable hashes).
The slowness of my branch was to some degree due to having a @!grid full of proxy objects for calling .cell-string and .change-cell as a compatibility layer, but I'm willing to give up the ghost on this one.
It's a good sign that object creation and introspection are not such costly operations these days.
@japhb I think I agree with you on the higher-level widget stuff, but it would also be a bit of a bummer to see them go.. When I originally started Terminal::Print the idea was to write a substrate layer that could be easily used by widget libraries (the name I had in mind for mine was Boxbrain).
But I've come to love your higher level additions quite a bit. If you feel they are best served by living in a different distribution than I support this change.
It occurred to me that it would also be possible to split the current Terminal::Print into sub-distributions, while moving the guts to Terminal::Print::Core. Then use Terminal::Print <T> still brings in all the widgets and animations, but more discerning users can pick and choose what to load.
Hmmm, that's an interesting idea (splitting the current Terminal::Print); I'd have to go through the various modules and think about them carefully, but you may have a point there.
I've been noodling away in a local repository on higher level widgets with my odd hours here and there, and I've just transitioned from "survey of the field" to "experimenting with APIs". My initial designs are kinda heavy, but I'm working through that.
I suspect there will be changes or additions I'll need to make in T::P in order to support the higher-level widgets efficiently and well, and it feels like that border might be useful to maintain in case someone wants to design a very different API than mine, but still have a solid set of primitives from T::P on which to build it. (Frankly it drives me slightly nuts that multiple people keep trying to solve per-codepoint input from scratch all over again. :-/ )
I've been looking at the base module of Terminal::Print and it has a fair number of expectations that might not make much sense anymore (for just one example, using FALLBACK to dispatch to Terminal::Print::Commands instead of $!current-grid) and a lot of grid management that should be clarified (named grids, grid switching and blitting) since they came from before the existence of widgets/compositing.
So the base module Terminal::Print is relatively ripe for a rethink as it stands.
But I agree 100% that the core desire of Terminal::Print has always been to be a substrate-layer that can serve multiple purposes. Perhaps we could make the module respond to the number of Terminal::Print::* distributions you have installed, eg. installing Terminal::Print::Core gets you enough to draw snowflakes or the matrix, while installing Terminal::Print::UI gives you quite a bit more, etc.
External configuration could allow for swapping out the default higher-level library that use Terminal::Print <T> would be instantiated with, while other libraries could just import the building blocks provided by various distributions and use/extend them in their own fashion.
Looking forward to seeing your experiments, by the way!
Hmmm. OK, how much should we consider breaking? I've been trying to keep most APIs roughly compatible (delta bugfixes) as I refactored things underneath, with the major exception of the switch to row-major addressing for the Grid relatively early on. But should we consider going further and doing a full v2 of the API and class factoring, based on the things we know now that we didn't know then?
For that matter, how slushy do you consider the API as it is now?
I've been trying for over a week already to decide which way I'm feeling about the current API and I still haven't been able to fully choose, so I'll stop waffling silently and bring it to this thread already.
Slushiness: Mildly Slippery
Terminal::Print::Grid
I think Terminal::Print::Grid in it's current state presents a pretty good 1.0, to be honest. The only change I would make is to put a has Method &!render on the Cell class and/or a has Method &!render-cell on the Grid. The default value of the former would be the current body of .cell-string.
Terminal::Print::Commands
This one deserves a bit of review. I think the 'universal' name for the move-cursor-template is silly and that profile's name should be tput. I would like to look into to fully separating the two and having one Terminal::Print::Commands::ANSI and one Terminal::Print::Commands::tput. I think there are ANSI equivalents for most of the current commands we intentionally support. It would be interesting if there would be a speed up by removing the conditions and extra layer of dispatch from this code path.
Terminal::Print
Does T.current-grid concept really make that much sense in the light of Widgets and other classes that inherit from Grid and/or implement .composite?
I also think that we should have multi method FALLBACK($command, *@args) { $!grid.$command(@args) } because that seems much more useful than wasting it on dispatching to tput commands considering all the work that has gone into the Grid API .
If we did choose to keep the @!grids array around, it might be interesting to hook the Widget constructor into the bargain and start keeping a list of all the widgets and animations and whatnots that are around.
But at that point I would probably argue that any potential use cases along those lines would fit better into the idea of Terminal::Print being a bit of an API shell that gets its super-powers based on the inclusion of various dists.
In other words, has @!animations might get introduced when you do use Terminal::Print [<Animation>] (the array would make it easier to navigate in the export logic and would distinguish from the use Terminal::Print <T> syntax, but I'm also open to other ideas.)
Even if we never go down that road, we could still reorient the current @!grids concept to refer to all of the Terminal::Print object's associated widgets, animations, and other grids, allowing indexed and named access.
v2 API
I definitely like the idea of incorporating any learnings or painpoints or the like into a v2 API. Any or all of the changes I mention above could arrive in v2, though I think pluggable cell rendering would allow for API shimming and so it might be useful to slide into v1, especially because it's more of an addition than an alteration.
Other parts
As to animations, widgets, and your other (frankly awesome) contributions to the API, I've read through them and gotten to know them more intimately while fiddling with the Grid internals but I don't know them well enough to comment very usefully on them at the moment.
Conclusion
That's it for this brain dump. If you've made it this far, thanks for reading! ;)
Re-reading that, I don't believe I was clear enough-- at all --in answering your questions, @japhb..
Do I support a full v2 API that incorporates all of our (mostly your) learnings?
Yes, please!
I wasn't sure if you meant a 2.0 API, but I'm thinking you probably meant a v2 API which would be officially released via 1.0?
The rest was a bit of what I'd like to see cleaned up. In retrospect it comes off more proscriptive than I intended. My goal was to spark a round of "this is what I find weird/frustrating/suboptimal about the current API" discussion, so my sincere apologies if it came off differently.