HackerTrans
TopNewTrendsCommentsPastAskShowJobs

d12frosted

no profile record

comments

d12frosted
·hace 6 meses·discuss
This makes a lot of sense now - thanks for the detailed walkthrough.

So the core idea is: ephemeral, inline forms that appear at point, collect structured input, execute, and disappear. Not persistent multi-form buffers, but disposable parameter prompts that don't break document flow or switch context to a modal.

The <query the ps of a given server> example is perfect - you want:

  1. Click/activate the button
  2. Small form expands inline (server selector, maybe filters)
  3. Fill, submit
  4. Form vanishes, result appears (inline or in separate buffer)
This is actually more tractable than what the gist's inline extension was doing. That was about persistent forms with state tracking, cleanup on manual deletion, etc. Your use case is simpler: mount form at point → collect input → unmount → done.

vui.el doesn't support this today, but it's not a huge leap. The pieces are there:

  - Components with state and validation 
  - Controlled rendering 
  - What's missing: mounting into an existing buffer at point (vs taking over a buffer)
I'd need to think through how it interacts with the host buffer's text properties and undo - that's where the gist's widget-before-change advice complexity came from. But for disposable forms that clean up after themselves, it should be simpler.

If you want to experiment with this, I'd be curious to collaborate. It's a use case I hadn't fully considered, but "structured, validated input for in-document interaction" is a good framing.
d12frosted
·hace 6 meses·discuss
Thanks for the detailed breakdown on Pathom and cljfx subscriptions - this is exactly the kind of perspective I was hoping to hear.

The resolver model you describe (dumb functions, map-in → map-out, parallelizable) is appealing. It's similar to what I find elegant about React's model too - components as pure functions of props/state. The difference is where the "smarts" live: in the dependency graph engine vs in the reconciliation/diffing layer.

Your point about the 95% case resonates with vui.el's approach. We do have vui-use-memo for explicit memoization — so expensive computations can be cached with declared dependencies. It's the middle ground: you opt-in to memoization where it matters, rather than having an engine track everything automatically.

For typical Emacs UIs (settings panels, todo lists, file browsers), re-rendering the component tree on state change is fast enough that you rarely need it. But when you do — large derived data, expensive transformations — vui-use-memo is there. The tradeoff is explicit deps vs automatic tracking: you tell it what to cache and when to invalidate, rather than the framework inferring it.

That said, I'm planning to build a more complex UI for https://github.com/d12frosted/vulpea (my note-taking library) - browsing/filtering/viewing notes with potentially large datasets. That'll be a real test of whether my performance claims hold up against reality. So ff vui.el ever needs to go there, the component model doesn't preclude adding finer-grained updates later. The should-update hook already lets you short-circuit re-renders, and memoization could be added at the vnode level.

The caching/invalidation complexity you mention is what made me hesitant to start there. "Explicit deps are easier to trace than magic" was the tradeoff I consciously made. But I'm genuinely curious - if you do experiment with Pathom-backed GUI, I'd love to hear how it goes. Especially around the cache invalidation edge cases you mentioned.
d12frosted
·hace 6 meses·discuss
Glad you like it! I was curious to see the comparison myself, so I asked Claude Code to reimplement it with vui.el - wanted concrete numbers and code rather than just claims. The 60% reduction was a pleasant surprise.

Regarding in-buffer forms: I'd love to understand your use case better. When you say "injecting" forms into a buffer while keeping the rest editable - what's the actual workflow you're building? A few scenarios come to mind:

1. Inline editing in org/markdown - e.g., a structured data block that becomes a form when you enter it? 2. Mixed content - documentation with embedded interactive widgets? 3. Progressive disclosure - expand a section into a form, collapse back when done?

Right now vui.el mounts to a dedicated buffer, so it doesn't support inline injection. But depending on the use case, it might not be too complex to add - or there might be a different approach that works better. Would be interested to hear more about what you're trying to build.

(And yes, feeding vui.el to an agent works surprisingly well - that's exactly how the gist was created!)
d12frosted
·hace 6 meses·discuss
Thanks for the detailed response! This is really helpful feedback.

Looking at your gist, I think the code actually illustrates why I built vui.el in the first place. The schema→widget mapping logic is genuinely interesting work, but a significant chunk of the code (~400 lines) is dedicated to the inline form lifecycle: jsf--inline-forms registry, marker tracking, resync passes, advice on widget-before-change, overlay cleanup, etc. That's exactly the plumbing vui.el handles automatically.

With vui.el, your json-schema-form could potentially be just the schema translation + a component wrapper:

    (vui-defcomponent json-schema-form (schema on-submit)
      :state ((values (schema-defaults schema))
              (errors nil))
      :render
      (vui-vstack
       (render-schema-fields schema values
         :on-change (lambda (path val)
                      (vui-set-state :values (set-at-path values path val))))
       (vui-button "Submit"
         :on-click (lambda ()
                     (let ((errs (validate-schema schema values)))
                       (if errs
                           (vui-set-state :errors errs)
                         (funcall on-submit values)))))))
State tracking, cleanup on close, multiple forms per buffer - all handled by the framework. Your validation logic and schema mapping would be the same, just without the infrastructure code.

On the emacs -q -nw workflow: it works, but you might find eldev + buttercup tests even better for AI-assisted iteration. The agent can run eldev test after changes and self-correct on failures. Byte-compilation catches issues too. Claude Code handles eldev well out of the box.

Anyway, not trying to hard-sell vui.el - your approach clearly works and the schema-form idea is cool. But if you do hit more state/cleanup headaches, might be worth a look. Happy to help if you want to try porting the schema logic over.
d12frosted
·hace 6 meses·discuss
Thanks for sharing! The JSON schema → widget mapping is a solid use case, and your two-tier validation (keystroke + submit-time) is a nice touch.

On the unbalanced parentheses from LLMs - I've found Claude Code with Opus 4.5 is generally quite good at keeping them balanced, fwiw.

Curious about this though:

> after understanding the tradeoffs, I pushed the widget code creation to an LLM

What tradeoffs made you go with raw widget.el over vui.el? Genuine question - that's exactly the kind of feedback that helps me understand if vui.el is solving the right problems or missing something.

Your gist essentially reimplements some things vui.el provides generically (state tracking, inline form lifecycle, cleanup). Would be interesting to see if vui.el could simplify the widget/state parts while you focus on the schema translation - or learn what's missing if it can't.

If having conversation here is not convenient, we can continue under your gist or via email. Let me know if you are interested :) If not - that's also fine :)
d12frosted
·hace 6 meses·discuss
vui-table supports three :border variants at the moment - :ascii, :unicode and nil (i.e. none)

:ascii

  +---------+--------+
  | Summary |        |
  +---------+--------+
  | RMS     | 4.1620 |
  | AVG     | 3.9558 |
  +---------+--------+
:unicode

  ┌─────────┬────────┐
  │ Summary │        │
  ├─────────┼────────┤
  │ RMS     │ 4.1620 │
  │ AVG     │ 3.9558 │
  └─────────┴────────┘
I think there is room for improvement (like use thicker lines for headers in unicode) and I also need to provide a way to override these.
d12frosted
·hace 6 meses·discuss
Good points, thanks for engaging thoughtfully.

On vui.el's approach - yes, the blessing is that widget.el is simple enough to build on. It does the "rendering" and some "behaviour", vui.el handles the rest.

On ECS vs OO - I'll admit I don't have enough experience to speak about UI paradigms in general. But my critique of widget.el is that inheritance hierarchies don't compose well when you need orthogonal behaviors. Composition feels more natural to me - could be just how my brain works, but it scales better in my experience.

On state management being independent - I'd be curious to hear more. Pathom is interesting for data-driven architectures. vui.el's state is intentionally minimal and Emacs-native, but you're right it could potentially be decoupled further.

On "why not full reactive" - to clarify what vui.el has: React-style hooks with explicit dependency tracking (vui-use-effect, vui-use-memo, etc.), state changes trigger re-renders, batching for multiple updates. What it doesn't have: automatic dependency inference or fine-grained reactivity where only specific widgets update. The tradeoff was debuggability - explicit deps are easier to trace than magic. But I'm open to being wrong here. What would you want from a reactive layer?
d12frosted
·hace 6 meses·discuss
Interesting, thanks for sharing! I've had thoughts about making vui.el backend-agnostic so it could target different widget implementations (like xwidgets or even native-GUI). An SDL-based widget library could potentially be one of those backends. Need to dig into appetrosyan's work before I can say anything intelligent about it though. And of course, it was an idea and I am unlikely to dive deep without practical need (time is limited, sadly).
d12frosted
·hace 6 meses·discuss
Good point. Though for widget UIs you're typically rendering structured data you control, not parsing arbitrary text files. The syntax highlighting / validation concern applies to editing code, not to building interactive interfaces.

> Generally though, for everyday use, Emacs feels a lot snappier than VSCode.

+1
d12frosted
·hace 6 meses·discuss
The long-line issue is real, though my statement was specifically about building UIs with widgets/overlays/text properties - not handling arbitrary files. In that context, Emacs's display engine is genuinely well-optimized: it handles overlays, faces, text properties, and redisplay regions efficiently.

When you're building a UI, you control the content. Lines are short by design (form fields, buttons, lists). The pathological case of a 50KB minified JSON line simply doesn't occur.

The long-line problem stems from how Emacs calculates display width for bidirectional text and variable-pitch fonts - it needs to scan the entire line. That's orthogonal to rendering widgets or interactive buffers.
d12frosted
·hace 6 meses·discuss
sorry for that! added a dark theme, feedback is welcome :pray:
d12frosted
·hace 6 meses·discuss
easy :) ask for dark theme; will try to implement one soon ;)

update: added; turns out I almost finished it before on a local branch but didn't push to master