lainchan / λ
Decker
Pris · 2025-12-19 01:41
I'd like to dedicate a thread to Decker:
https://beyondloom.com/decker/
I'm someone who, despite years of programming, had never implemented a graphical program, because of just how damn difficult it is. Decker is like Hypercard, and something like Hypercard is how easy it should be. It's easy to build something in Decker with hardly any code at all.
Decker organizes a project into a deck, and of course decks comprise cards. Cards have widgets that can be buttons, text fields, sliders, canvases, or grids. Contraptions are widgets built from these primitives.
Lil is the language of Decker, and it has features of normal languages, array languages, and declarative languages. Unlike a normal language, it's easy to run an operation on an entire group of data conceptually all at once, or to query it like a database. Unlike an array language, there's no compulsion to fit everything into one concise expression, unless it's particularly easy. Unlike a declarative language, it's easy to be imperative when easier.
Perhaps most importantly, because I'm sure everyone here has seen some cool environment that just needs the eight hundred pound gorilla known as a web browser, Decker has a native implementation in addition to one that can run on the web. I've audited the source code of Decker's native port, and I didn't find any bad things therein.
Unlike some other attempts at creative environments, Decker is high-level, which is really the only sensible way to design something like this, compared to imitating home computers from the 80's.
There's an annual jam about Decker here:
https://itch.io/jam/deck-month-3
I plan to participate, and maybe some of you will too.
SomeLoser · 2025-12-19 05:44
Thank you for sharing this, good person.
Is it like Visual Basic or GAMBAS?
Unidentified · 2025-12-19 11:31
>>43714
Not OP, and I haven't done anything super fancy in it, but my overall impression of Decker is that it's primarily influenced by Smalltalk and Hypercard, with some cues taken from Pico-8.
SomeLoser · 2025-12-19 11:42
>>43716
Interesting, I will probably give it a try. Although I have a pretty long "To-Do list" to complete, I always can reserve space for trying something new. Thank you so much for the information!
Kay · 2025-12-26 04:43
I like a particular kind of pattern, but have never before had a graphical editor for them, and this seemed like an ideal little project I could get done this month. I got it up and working like this to some degree about four days ago now. Here's my GIF export from back then, and I'll post what I've currently got later today or tomorrow, perhaps as an animated GIF next time. The first thing I had to do after setting up the canvas and buttons aligned perfectly was figuring out what the coordinates for drawing should be, and then using a circular brush to avoid wider diagonal lines. I took this brush's image from one of John Earnest's decks about brushes, the tutorial which can be found from my first link, and scaled it down:
image["%%IMG2ACAAIAAOAQUAFwENABIBDwAPARMADAEVAAoBFwAIARkABgEbAAUBGwAEAR0AAgEfAAEBHwABAR8AAQG/AAEBHwABAR8AAQEfAAEBHwACAR0ABAEbAAUBGwAGARkACAEXAAoBFQAMARMADwEPABIBDQAJ"]
The first thing I added after this was the button to clear the canvas, once I got tired of manually clearing it however many times. Here's something close to the original code I used for the clear button:
on click do
points.widgets.points.value:insert index with end
each button in card.widgets
button.text:""
end
pattern.clear[]
end The canvas has no text field, so it ignores this. The first line of the function clears the grid used to store the coordinates, which is something that got changed often as I thought about how best to store them; originally, the coordinates for the canvas were stored directly, but now the button's index is used to make this indirect. I used the Clear button and came back hours later to find its label gone, however, leading me at first to believe I'd encountered some kind of bug. I ignored that feeling and just replaced it. When using the button again, I noticed the button cleared its own label. I'd forgotten about that little detail, and this became the new code:
on click do
points.widgets.points.value:insert index with end
each button in card.widgets
if !me=button button.text:"" end
end
pattern.clear[]
end Here's what the original code for the buttons over the canvas was, the first button as an example, except for that fiddling with the coordinates system:
on click do
if !me.text=count points.widgets.points.value
points.widgets.points.value:
insert index with 1 into points.widgets.points.value
me.text:count points.widgets.points.value
draw[]
end
end The condition prevents the operator from clicking the button and adding it uselessly, repeatedly, by making sure that it wasn't just clicked. The button's index is inserted into the grid, and its text reflects its new index in the sequence. I'd like to make these animated, so they flip between numbers when they've got more than one, but I've not done that yet.
There's a lot more already ready for my next post, but this suffices for now.
Lady Jessica · 2025-12-26 08:22
looks like denote+org-mode+emacs stack, but without elisp as an extension language. At one hand, good, elisp can be fiddly at best. At the other, bad, cause you can't go easy beyond what framework has to offer.
Afaik, decker provides superior interface to graphical stuff, although Emacs /can be/ coerced into at least showing images and provides widgets. The buffer idea is way less malleable than those "cards" though.
All in all, I like it, probably won't switch from denote, because my notes are quite huge as they are and I wrote myself a nice tree view of them, but it might be useful to some less entrenched.
Y.T · 2026-01-04 22:57
I'm preparing a writeup, but here's the evolution of the deck. The second image shows the animation that's part of the interface.
The animation button and its associated slider, alongside the SVG output button, don't currently work. Some customization options are also not present in the second card. Everything else works, however, although I'd like to improve the shifting effect when both buttons are marked.
I'm not pleased with the performance of this deck, which appears particularly bad, and got worse when I removed an optimization to make the undo button work. I'm going to throttle these animations later and see how that improves things.
I'll probably be able to tweak this thing for a while before I stop finding little improvements I can make. I'll show a few basic improvements I've made. So, here's how the Clear button worked for most of its existence now:
on click do
points.widgets.points.value:insert index with end
middleleft.text:""
bottomleft.text:""
bottom.text:""
bottomright.text:""
middleright.text:""
upperright.text:""
upper.text:""
upperleft.text:""
middle.text:""
pattern.clear[]
end There's nothing wrong with this, but it could clearly be improved. Here's what the "Visible buttons" button's script was:
on click do
if !me.value
upperleft.style:"invisible" upperleft.show:"none"
upper.style:"invisible" upper.show:"none"
upperright.style:"invisible" upperright.show:"none"
bottomleft.style:"invisible" bottomleft.show:"none"
bottom.style:"invisible" bottom.show:"none"
bottomright.style:"invisible" bottomright.show:"none"
middleleft.style:"invisible" middleleft.show:"none"
middle.style:"invisible" middle.show:"none"
middleright.style:"invisible" middleright.show:"none"
else
upperleft.style:"round" upperleft.show:"solid"
upper.style:"round" upper.show:"solid"
upperright.style:"round" upperright.show:"solid"
bottomleft.style:"round" bottomleft.show:"solid"
bottom.style:"round" bottom.show:"solid"
bottomright.style:"round" bottomright.show:"solid"
middleleft.style:"round" middleleft.show:"solid"
middle.style:"round" middle.show:"solid"
middleright.style:"round" middleright.show:"solid"
end
end I finally added this code to the card's script, when writing undo:
buttons:upperleft,upper,upperright,
middleleft,middle,middleright,
bottomleft,bottom,bottomright With that simple definition, here's the code for the Clear button, the "Visible buttons" button, and the Undo button:
on click do
properties.widgets.points.value:insert index with end
pattern.clear[]
each button in buttons
button.text:""
end
end
on click do
each button in buttons
if me.value
button.style:"round" button.show:"solid"
else
button.style:"invisible" button.show:"none"
end
end
end
on click do
buttons[-1+first -1 take properties.widgets.points.value.index].text:""
properties.widgets.points.value:-1 drop properties.widgets.points.value
pattern.clear[]
draw[]
end That's much better, and didn't even need me to define a contraption that exposed the buttons through its interface, although if I later make the pattern producer use a contraption, I'll likely do that anyway.