Linux 0.11 rewritten in idiomatic Rust, boots in QEMU | Hacker News Fark’n hell, this is some ~50k SLOC of Rust code compared to the original ~8k SLOC of C of the original this was based off of. No doubt this was “vibe coded” for sure, there is no way a human can write 50k SLOC, not in a reasonable timeframe anyway 😅
Just thought it an interesting Hacker News article that caught my eye 👁️
@kat@yarn.girlonthemoon.xyz You did! 🎉
Hell yeah 👍 🙌
@lyse@lyse.isobeef.org None. I rejected ithe invite request 🤣
@david@daiwei.me Well… I can’t! becuase the email supplied was nobody@invalid or some shit™ 💩
@prologic@twtxt.net You also have to tell us the username!
@david@daiwei.me I agree, the App (https://twtxt.app) really does work quite nicely 👌
@david@daiwei.me that was literally one of the messages I got this morning with an invite request to join this pod 😱
gg instead of g to go to the top in tt. Much better! :-) Other multi-key combinations are also easily possible now.
Nice!
Hell yeah, @kat@yarn.girlonthemoon.xyz is back! \o/
@yarn_police@twtxt.net LOL 😂
Hurray, I can now press gg instead of g to go to the top in tt. Much better! :-) Other multi-key combinations are also easily possible now.
I should probably write a real article about this at some point, but here we go. The only downside with my new key binding system is that it breaks tview’s established pattern. You’ve got an InputHandler(), that is implemented using WrapInputHandler(…). It typically then directly implements the switching logic depending on the key press. Something like this:
func (w *Widget) InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// WrapInputHandler allows for intercepting key events with SetInputCapture(…)
// from the outside for customization. This handles the default key bindings.
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
switch event.Key() {
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'k':
w.scrollUp()
return // we already handled the event, stop processing
case 'j':
w.scrollDown()
return
}
}
}
// We didn't handle the key event. Maybe the parent
// widget knows what to do with it.
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
})
}
From the outside, you can intercept and either stop or continue the widget’s original key handling with a potentially rewritten key event using SetInputCapture(…):
w := NewWidget()
// customized or additional key bindings
w.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
case tcell.KeyUp:
// Rewrite the event, so the "cursor up" key is an alias
// for the vim key binding "k", that is handled by the
// wrapped input handler above. (I know, I know, this is a
// completely unrealistic example, why would anyone use
// cursor keys when there are vim key bindings available?!)
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
case tcell.KeyRune:
if event.Modifiers() == tcell.ModNone {
switch event.Rune() {
case 'q':
app.Stop()
// we already handled the event, do not pass it
// to the wrapped input handler above
return nil
case 'r':
toggleMessageReadStatus()
return nil
}
}
}
// we didn't handle the event, pass it to the wrapped
// input handler above
return event
}
Since they all expect a single key, I’ve noticed that using multiple dedicated KeyBindings of mine on these different levels kinda breaks multi-key handling with common prefixes. The outer-most KeyBinding captures the prefix, but it can’t transfer it to the inner one if not handled by the outer one. At least not without some more (potentially ugly) changes. So, I now have to work with just a single KeyBindings object for the entire widget chain (if it consists of multiple other widgets or the regular input handler and input capture are in the game). The outside needs to register all its key bind customizations or extensions at the same level that the original widget handles its default ones. Doable by exposing the widget’s KeyBindings instance, but not pretty. You always have to keep this in mind.
With the KeyBindings, it will look like that:
type Widget struct {
parent tview.Primitive
// make it available to children or the outside either by
// direct field access or by providing a getter method
KeyBindings *bind.KeyBindings
}
func NewWidget() *Widget {
w := &Widget{KeyBindings: &bind.KeyBindings{}}
w.KeyBindings. // default key bindings
Bind0(bind.KeySequence('k', w.scrollUp).
Bind0(bind.KeySequence('j', w.scrollDown)
return w
}
func (w *Widget) InputHandler() InputHandler() func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
return t.WrapInputHandler(func(event *tcell.EventKey, setFocus func(p tview.Primitive)) {
// also note the missing support for focus transfer at the moment
event = w.KeyBindings.Capture(event)
if event == nil {
return
}
if handler := w.parent.InputHandler(); handler != nil {
handler(event, setFocus)
}
}
}
And then from the outside, or in a child widget:
w := NewWidget()
w.KeyBindings. // additional or customized key bindings
Bind1(bind.KeySequence(tcell.KeyUp), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyRune, 'k', tcell.ModNone)
}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind0(bind.KeySequence('r'), toggleMessageReadStatus)
When directly working with tview primitives that are not part of custom widget implementations, the following works well so far:
textView := tview.NewTextView().
SetWordWrap(true).
SetText("…")
SetScrollable(true)
textView.SetInputCapture((&bind.KeyBindings{}).
Bind0(bind.KeySequence('q'), app.Stop).
Bind1(bind.KeySequence('g', 'g'), func(*tcell.EventKey) *tcell.EventKey {
return tcell.NewEventKey(tcell.KeyHome, 0, tcell.ModNone)
}).
Capture)
I need to sleep on this some more.
Also, writing very long messages like this one is really not all that fun in tt’s editor. I should absolutely provide a way to shell out to vim.
(Took me about one and a half hours to compose, holy crap. But not only because of not using vim. Although, that might have saved me a quarter hour or so for sure. Proof-reading this message also uncovered quite a few bugs in my real documentation. So, that’s a big win!) Good night!
@lyse@lyse.isobeef.org Quite effective then eh? 🤣
@kat@yarn.girlonthemoon.xyz Welcome back!!!! 🎉 Did you upgrade your yarnd? 🤔
@david@daiwei.me Yeah the search engine/crawler has only found 28 active users in the ecosystem so far 😅
Just for security as required by law.
LOL 🤣 Was this someone’s idea of a joke? 🤔
@prologic@twtxt.net this is so epic!!!
anyway thank you to @prologic@twtxt.net for the email heads up to upgrade this pod! we SHOULD be on the latest version, if i did it right…
@kat@yarn.girlonthemoon.xyz omg i haven’t been here in FOREVER i’m sorry yarn friends!!! i’ve had a lot going on including being extremely depressed :(
@kat@yarn.girlonthemoon.xyz REAL SHIT?
test
@david@daiwei.me Not so keen on the mowing part. :-)
@prologic@twtxt.net That’s a good way to keep spammers out:
Your browser did not pass the anti-spam check! Please make sure JavaScript is enabled and try again.
It was turned on.
@david@daiwei.me Haha, great response!
@movq@www.uninformativ.de Hottest room is still at 24°C. But that will change in this week, no doubt. :-(
Back at 29-30 °C in my apartment. 🥳🙄
@david@daiwei.me It’s all fixed now, for good 😌
Yeah this is my fault sorry! In this case i’ve axtually found yarns to be soex non-compliant 😱 Twtxt.app is doing yhe right thing🤣 As is Jammy 👌
Yeah this is my fault sorry !
@david@daiwei.me This is another dangling thread:
Trying to fetch "#kyjhiwcxeknm" from Yarn pod https://txt.sour.is ...
Trying to fetch "#kyjhiwcxeknm" from Yarn pod https://twtxt.net ...
Twt could not be found
LOL 🤣
it’s just a human gate / vibe
@balloon-fu-sen@tw.fus.f5.si You don’t really need to! The crawler will discover your feed on it’s own 😅
🎉 This pod, twtxt.net is now open to the general public again to join. However it is invite-only with admin review and approval/rejection. Welcome ! 🙏
@-mentions), unread dots, Back keeps your spot, and it'll now guide you to install it as a proper app 📱 Reload https://twtxt.app and have a play! Thanks @quark and @balloon-fu-sen for all the reports 🙏
Self-hosting twtd? Pull prologic/twtd:latest too — the Avatar URL field in the app now actually writes # avatar = into your feed (needed changes on both sides)
Shipped a bunch of Twtxt App fixes & polish today 🥳 One-tap Refresh that actually refreshes, duplicate follows fixed, Reply/Fork buttons (with proper @-mentions), unread dots, Back keeps your spot, and it’ll now guide you to install it as a proper app 📱 Reload https://twtxt.app and have a play! Thanks @quark@ferengi.one and @balloon-fu-sen@tw.fus.f5.si for all the reports 🙏
@itsericwoodward@itsericwoodward.com Ill weirw it up and share it shortly 👌