No current version, but I'm preparing it. But actually, to see a really ridiculously minimalist start, this was my starting point, which used a tiny C extension to do the X rendering (though it optimistically included a dummy class intended to be the start for the Ruby X backend). It's awfully limited, and awfully broken, but it shows how little it takes to be able to start writing:
It's totally useless for anything other that testing or expanding on, but it was the starting point for the terminal I now run every day, and I'll be updating that repo as I clean up my current version at some point.
The current version uses this for a pure Ruby (no Xlib) X11 client implementation:
And this pure-Ruby TrueType font renderer (I did the Ruby conversion; the C code it's based on was not mine, and is a beautiful example of compact C - look up libschrift) as I got tired of using the bitmap fonts and didn't want to add a FreeType dependency (the renderer is ~500 lines of code):
i look forward to seeing it! the simple, approachable truetype implementation is very exciting already! i didn't know about libschrift, but one third the code makes Skrift three times as approachable
Also to add that one thing that really inspired me with libschrift is the realization that Trutetype is conceptually really simple. Most of the code is parsing the annoying format. The actual rendering - as long as you don't deal with hinting, is just a matter of rasterising lines and quadratic bezier curves.
Handly OpenType then adds cubic bezier.
If, on the other hand, you want colour emojis, you need to implement a subset of SVG (though the subset is small).. Yikes.
You get 90% for 10% of the effort... As usual, I guess. Part of me want to see how far down full emoji font support can be golfed, but another part of me feels that's downright masochism.
i guess hinting is less important today than it was in the days of monochrome 1152×900 21" monitors and sub-mebibyte framebuggers where you couldn't do antialiasing
(and maybe you can do a decent job of blind "hinting" with smarter dsp algorithms, gradient descent, and orders of magnitude more cpu, and just ignore the tt hints virtual machine)
well-defined subsets of svg are a pretty interesting thing; i feel like a smol computing system might benefit from using something like that as its base graphical layer for things like fonts and windows; then a font engine can delegate the rasterizing down to the svg layer
parsing annoying formats is what https://github.com/abiggerhammer/hammer is for; we were able to get it to parse pdf. unfortunately it's not pure ruby. the smallest i've been able to get a peg parser library is http://canonical.org/~kragen/sw/dev3/tack.py which is 27 lines of python, but i'm not sure it can be reasonably extended to do the kind of binary parsing that hammer does without balooning in size
Similar thoughts on hinting - it's "good enough" for me on full HD w/just the antialiasing. With respect to automatic hinting, as I understand it Freetype has autohinting based on heuristics as hints in the fonts are often poor, but I haven't looked at how complex the auto hinter is.
Thanks for the nile and gezira link - it'd be fun to handle the emoji fonts too, at least as an addon...
Hammer looks interesting. I'm right in the middle of yet another parser combinator library in Ruby, but focused on text (it annoyed me that the Ruby Toml parser pulled in a 1500 line dependency for several hundreds of lines of excessively verbose parser definition for a grammar that can be defined in ca 50 lines) and frankly more an excuse to toy with refinements to see if I can get closer to BNF for specifying it.
I might have a look at hammer for inspiration for ways to shrink the ttf parser later.
yeah, hammer is maybe small for a c parsing library but in absolute terms isn't that small (about 10 kloc if you leave out the bindings) but it might be good as a reference point for api design
because i'm not a fan of excessively verbose things, i've been tossing around ideas for a new non-parser-combinator-based peg parsing system called 'the monkey's paw' whose grammars look like this
which you can make even more bnf-like if you want by putting <digits> and <var> on their own lines
based on my experience with peg-bootstrap i suspect i can probably implement this metacircularly in about 100 lines of code in something like lua, js, or ruby, but getting it built in a non-self-referential way will take another 100 or so. i wasn't planning on doing hammer-style bitfields and stuff, and though i might end up with hammer-style parser combinators for bootstrapping, the idea is to use a host-language-independent grammar syntax as the main way to define grammars
> that's not really closer to bnf so maybe it's not what you're looking for
I'm really toying with a variety of things. One thing is the smaller/cleaner parsing of binary formats.
The other thing I'm playing with is seeing how close I get to cleanly expressing the grammars in pure Ruby, without parsing an external format. The two things are pretty orthogonal, and always enjoy looking at new ideas for parsing in general, not just what I can abuse the Ruby parser to handle directly...
Your format is interesting. I read it as the <name: ...> bit serving as a capture? If were to map that to Ruby, I'd probably use the Hash syntax to try to approximate it, so you'd end up with something "{expr: {first: ...}". Incorporating the actions without some extra clutter would be a bit tricky, because the operator overload's won't let you add a block, and so you're stuck with a minimum of ->() {...} or lambda { ... }, but I think representing it reasonably cleanly would be possible (of course this looks like a simple enough format to just parse directly as well).
For a taste of how close to avoiding "host language noise" you can get when embedding the grammars directly in Ruby (I've not settled on the specific operators, but it's a bit limited since you can't change the precedence, I do think the '/' which came from ABNF might have been a poor choice and I might revert to '|' in particular), here's a small fragment of the Toml grammar that will parse as valid Ruby with the right code:
But that so far excludes captures. I'm tempted to default to simply capturing the terms by name.
The trick to making the above valid Ruby that this is defined inside a class that "uses" a set of refinements[1] that lexically overrides methods on a number of core classes only within the grammar definition, and then it instance_eval's the grammar within an object where method_missing returns an object that acts as a reference to named rules, so each rule is basically just a series of chained method calls (hence the annoying '&' - I think it may be viable to get rid of it by keeping track of state in the object whose method_missing gets invoked, but I'm not sure if it'll be robust enough to be worth the slight reduction in visual clutter)
Without the refinement feature we'd have to wrap the integers etc. if we didn't want to monkey-patch the standard classes and break everything. (This kind of DSL is the only really useful case I've found for the refinements feature so far)
I really should just reproduce that output in its entirety for direct comparison.
If it does not produce pixel for pixel identical output it's a bug. But here is the first pass of code that uses the same approach to integrate it with X and use Xrender to output the rendered glyphs:
(EDIT: Fixed the issue below)
Note that the example contains a hard coded visual. I need to push a fix for that - it was last updated before I added support to the X11 client to look up the visual. In it's current form it probably won't work for you. Will see if I can push a fix for that today.
nice! probably magenta on a red background is undesirable, though; maybe switch to colors with better contrasts, or add a border or drop shadow, or just postprocess with a zero-phase high-pass filter
what do you think an idiomatic ruby binding for yeso would look like? so far i only have lua, c, and python bindings, which are described in https://gitlab.com/kragen/bubbleos/blob/master/yeso/README.m.... my ruby experience is both limited (only a few thousand lines of code) and over a decade ago
Yeah, the colour choices were pretty random, I need to clean it up.
X11 visuals are severely annoying. I get they made sense in the 80's and 90's - I spent time in computer labs where the machines ranged from monochrome to SGI Indy's, with 8-bit palette, and 15 and 16 bit direct color displays in between, but I'm all for just assuming 32-bit bgra is available these days.
Any server supporting XRender needs to support it anyway as it's one of the standard formats for XRender. (I don't know if you've looked at the XRender library code, though, but one of the things that made me facepalm was that even though it requires a handful of standard visuals, the new Xrender call that returns the visuals for Xrender does not just return a list of the handful of standard formats as part of the response - you need to filter the full list of visuals and match them to depths and bit masks... Not that it's a lot of code, but it just so aggravatingly pointless)
> what do you think an idiomatic ruby binding for yeso would look like?
I think a bit of a mix between the Python and Lua would get you pretty close. Don't look at "my" X11 client for idiomatic Ruby :) It was "inherited" from an older client, and it's very closely following the protocol more so than idiomatic Ruby, and I'll eventually try to massage it into something nicer.
To take your examples, we'd probably want to use blocks. E.g. I could see the munching squares example looking something like this in
Ruby:
def munch(t, fb)
fb.each_row do |y|
fb.each_col do |x|
fb[x,y] = ...
end
end
end
You could also use the approach you use more directly, and I'm sure nobody would think that was weird either:
def much (t,fb)
fb.each_row do |y, p|
fb.each_col do |x|
p[x] = ...
end
end
end
For the main bit, "new" will always directly return the window,
but it's not unreasonable to then either `yield self if block_given?` in the constructor to allow similar code to your Python version:
Yeso::Window.new(...) do |w| .. and so on; end
or wrap that in a class method:
Yeso::Window.create(...) do |w|
(0..).each {|t| w.frame {|fb| much(t,fb) } }
end
(Endless infinite range is "new" since 2.6)
The class method vs. constructor only really buys you that you can make it slightly harder to accidentally keep the object around since you can prevent it from being directly returned. I think overall that's probably the most common approach even when the constructor
supports taking a block directly.
Does it sync tracks that you Love in Apple Music? I have liked Apple Music a lot, except for one major thing when I realized that there is no way to view tracks that I have marked with Love, and I'm trying to find a way to get that information out.
That, I'm not sure about. I just use it to maintain an Apple Music copy of my "Liked Songs" via what they call a "Full Library Transfer" shift.
That may be what you're talking about, since clicking on the heart icon is how songs end up in "Liked Songs" to begin with...? Note that I only use it in the Spotify -> AM direction, not vice versa.
I've been searching for a great quality PS5 controller that has the left thumb stick in a neutral position and doesn't cost $250. On the rare days when get a chance to play a longer session, I can use the Xbox or Switch Pro controllers for hours without issues, but I hardly touch my PS5 because the left thumb stick requires such a stretch that my thumb tendon already starts to get sore after 15 minutes.
I understand the business logic, but I wish the console manufacturers would allow more portability between them.
I like web components especially with the nice tooling that comes with lit, but agree that the lack of server-side rendering and hydration makes them impractical to use compared to other server side progressive enhancement libraries like Stimulus and Alpine. Server-side renderable web components would open up a lot of possibilities for better user experience for multi-page apps.
Yeah, other than a project that was still on webpack, I can't think of any time in the last few years where this was a problem. Vite has made JavaScript apps nearly effortless for years now.
I've done and loved at least 15 years of Rails, but not since the new Hotwire/Turbo/Stimulus releases. I've played with it a bit in side projects and it seems interesting, though I'm still skeptical that it's a good model for apps that plan to stick around for a while.
One of the things I've found difficult coming back to Rails is how spread out all of the behavior is in so many different files and partials and helpers. While SPAs have a lot of trade-off, organizing related code into components works so much better than any experience I had with server-side MVC, especially when using something like TypeScript and Remix's islands that very effectively isolate even further into logical modules. What little I've done with Hotwire/Turbo made it seem like very basic behavior is even more spread out and even harder to reason about for someone who didn't write it, which seems like it would make maintenance and refactoring in Rails even more time-consuming and perilous than it already is.
I'm really interested in the technology because I hear such glowing reviews of it, but I'm not sure I see it. I'd love to see a non-dogmatic comparison of SPAs vs Rails with Hotwire/Turbo MPA for post-MVP longer-term projects.
You hereby have permission to organize code as you would like!
I think your complaint is fair but I'm not sure it is a fault with Rails so much as I've rarely seen anyone interested in organizing their Rails code more than the default.
Personally, I think it is really helpful, especially when it's as easy as using modules or having interfaces between modules. If you want feature-based structure, I'm pretty sure you can do it but that'll be a bit more involved. There are some gems out there that support those efforts.
I've found with Stimulus/Hotwire/Turbo that separation of concerns and finely composed partials can help a lot.
I have taught a lot of people in classroom settings and as a leader of companies and teams. By far the best resource that I know of is the video "Git for Ages 4 and Up". https://m.youtube.com/watch?v=3m7BgIvC-uQ
The presenter uses children's construction toys to explain the surprisingly simple and intuitive git internals, and how each of the somewhat obtuse and unintuitive git command operate on their repository structure.
Once people understand the underlying concepts of git, even programming beginners, they can conceptualize what they want to accomplish in their repository, and then and then figure out which tool is the way to get there.