Skip to content

Support for newer rubies#82

Open
trinistr wants to merge 7 commits intoAndyObtiva:masterfrom
trinistr:support-for-newer-rubies
Open

Support for newer rubies#82
trinistr wants to merge 7 commits intoAndyObtiva:masterfrom
trinistr:support-for-newer-rubies

Conversation

@trinistr
Copy link

@trinistr trinistr commented Jan 20, 2026

Closes #81

In general, it seems that everything works mostly as-is. This PR was mostly about adding missing dependencies (for libraries that became gems) and relaxing stringio's dependency.

  • Update Bundler to latest version compatible with Ruby 3.0 to reduce possible bugs.
  • Relax stringio's requirements and update locked version. 3.0.7 is required for Ruby 3.3, 3.4 and 3.1.7 is required for 4.0.
  • Add csv and logger gems which have been extracted.
  • 🤷 Bundler changed versions of faraday and nokogiri, and I don't know why. I thought bundle install shouldn't do it, but it just did. But a newer nokogiri is certainly required. Why faraday got downgraded, I've got no idea.
  • Normalize platforms in lockfile. Versions of Darwin are ignored and so unneeded.
  • Add a GitHub Actions workflow to run tests on Ruby 3.2-4.0. Probably macOS and Windows also need to run at least some tests. 3.0 and 3.1 require older nokogiri and would need more complicated setup.
    • It would probably be a good idea to allow Bundler to re-resolve everything (not use lockfile).
  • Fix some bugs in examples:
    • Add horizontal_boxes to tables and some other places. Many of these were previously removed as unneeded, but they are needed on Linux, otherwise tables are so narrow as to be unusable.
    • Flush stdout in basic_child_window example.
    • Fix locale for top call in cpu_percentage example. Locale with a decimal comma causes isssues.
    • Reduce number of rows in lazy_table examples from 10 million to 100 thousand. Let's just say that I thought it didn't start and started the example many times.

Some remarks on examples:

  • basic_code_area and basic_code_entry don't work: libUI errors with ** (ruby:867087): CRITICAL **: 20:44:19.326: [libui] ../common/control.c:88:uiControlVerifySetParent() You have a bug: You cannot give a uiControl a parent while it already has one. (control: 0x564cba69e7a0; current parent: 0x564cbb2bae20; new parent: 0x564cba6ad2e0) and process exits.
  • basic_table_image and basic_table_image_text seem to hang. Is it because image is really-really slow? basic_image examples take a second or two to load already.
  • basic_table_selection and basic_table_selection2 crash Ruby completely. Version 3 seems to work.
  • I didn't check examples requiring extra dependencies.

Further work:

  • Review current dependencies and update them. equalizer, for example, should be replaced with dry-core (there were already two replacements) and facets had last release almost 10 years ago.
  • More tests and testing.

- Add minimum version of stringio: 3.0.7 is required for Ruby 3.3 and 3.4.
  - 3.1.7 will be required for Ruby 4.0.
- Normalize platforms in lockfile, add linux and ruby platforms.
  - Though bundler keeps updating nokogiri to the latest version for some reason.
- Update bundler to latest version compatible with Ruby 3.0.
- Fix cpu_percentage example's dependance on locale.
- Add `horizontal_box`es to tables and simple_notepad example.
- Flush $stdout in basic_child_window example.
- Disable logout buttons in login examples.
10 million rows took way too long to show the window.
Bundler keeps changing versions of locked gems, and I don't know why.
- Update nokogiri to be compatible with 3.2-4.0.
- Update .ruby-version to latest 3.2.
gem 'psych', '4.0.3'
gem 'json', '2.6.1'
gem 'rspec', '~> 3.0'
gem 'coveralls', '= 0.8.23', require: false
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be locked? Also, repository has a token for Coveralls. I'm not familiar with it, is that normal? Any tokens in git look suspicious.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The repo token is valid as it enabled me in the past to submit code coverage results to a Coveralls cloud account, but I don't use Coveralls much anymore for the time being (it ran with Travis CI long time ago, which is no longer free).

If this line is not causing problems, you can keep it. If it's causing you problems, you can adjust it or remove it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not seem to cause problems. It's just strange that it's pinned.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'm worried that anybody can just snatch the token and use it for whatever they desire.

@trinistr trinistr force-pushed the support-for-newer-rubies branch from c6388f6 to 0dead47 Compare January 20, 2026 20:05
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file needs to be on master branch to actually run here. Here is a previous run: https://github.com/trinistr/glimmer-dsl-libui/actions/runs/21185287370.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point is 1) dependencies can be installed, 2) at least some tests run.

@AndyObtiva
Copy link
Owner

Thank you. I am sorry I was unavailable last week. I'll take a look at this this week for sure, probably Monday.

Copy link
Owner

@AndyObtiva AndyObtiva left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for the effort that went into this PR. I really appreciate it.

I did an initial review and added a few comments.

Here are also responses to some things you noted:

Concerning basic_code_area and basic_code_entry, they are experimental code, so if they are not working, it is not a big deal. They did work before, but in a limited fashion. I might just remove them.

Regarding basic_table_image and basic_table_image_text, they are supposed to be slow because they pull data over the Internet to display table images. So, I would give them more time to run upon launching them (up to a minute).

Regarding basic_table_selection and basic_table_selection2, they are supposed to just work. If they crash Ruby completely in version 4 only, maybe try to find out what line of code they crash at. It might be a Ruby 4 compatibility issue that requires some code changes.

Regarding equalizer and facets, my mentality about them is "why fix 'em if they ain't broken", following the YAGNI Software Engineering principle. What they do is very simple for the needs of the library, not rocket science. So, they don't really need any crazy ongoing updates. They're good enough for the library's needs as they are.

Before I make a release with the PR's changes, assuming all the PR comments are addressed eventually, I will do some testing of my own too.

Thanks again for the PR and all the effort that went into it! I look forward to you addressing the PR's code feedback.

window('Child Window') { |child_window|
on_focus_changed do
puts 'Child window is focused' if child_window.focused?
$stdout.flush
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$stdout.flush is only needed on Windows because its Ruby IO implementation relies on buffering by default for performance reasons instead of immediately flushing output:
https://www.rubyguides.com/2019/02/ruby-io/

It is becoming painful and ugly to add that flush call everywhere though. It seems time to start looking into a different solution.

The page above suggests the following code to change the Windows setting:

$stdout.sync = true

I think it is worth exploring adding that line to the top of every example file as a start, with a comment explaining what it does.

require 'glimmer-dsl-libui'
$stdout.sync = true if OS.windows? # Disabling buffering because Windows buffers IO by default, which prevents puts from printing immediately.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprisingly, this is also needed on my Linux system. I've not found why exactly, usually it's not needed, as stdin/stdout are connected to a terminal, so underlying IO should be in line-buffered mode; but it seems that for whatever reason IO gets switched to full-buffered mode on C side. Maybe libUI does that? I'm not even sure that stdin/stdout are actually connected to the terminal, maybe there is some internal proxying going on.

I think enabling $stdout.sync = true is fine for examples, it shouldn't matter much. Though it may cause cargo cult programming 🤷

new_animals = @animals.clone
new_animals.delete_at(row)
self.animals = new_animals # automatically loses deleted table row due to explicit data-binding
horizontal_box {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At one point in the past, I used to automatically add horizontal_box (or vertical_box) on Linux to prevent this problem and keep allowing the programmer to use the simpler syntax when there is only 1 element under window. But, I thought that a libui update removed the need for that. It seems I was wrong, so I will eventually add back the automatic code that did that as a default on linux.

I will accept your example changes for now, but I might adjust them again in the future once I add the automation mentioned above back.

text_column('City')
text_column('State')

cell_rows ContactGenerator.new(1_000_000)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is supposed to demonstrate an exaggerated example with 1 million rows to illustrate how by using a generator, the app starts in less than 10 seconds (on a Mac M2 chip) because it would only generate visible rows as needed. Whereas, without using a generator, the app would take minutes or much longer to start because it would end up generating all invisible rows too.

1000 rows would not be a good test sample because the app starts fast with 1000 rows EVEN WITHOUT using a generator. So, that number defeats the point of the example.

Of course, I say 1 million is exaggerated because in real apps, seeing that much data all at once is impractical for users. But, support for generators is provided as a solution option just in case it is needed. I use it in this Sidekiq desktop UI for example (Sidekiq data is unpredictable; as sometimes I get a few rows, and other times I get many more rows depending on what's going on, so this feature works well for it):
https://github.com/mperham/kuiq

In summary, this example is meant to take about 10 seconds to start, but much less than minutes.

Was it taking you more than 10 seconds to start? (How long, if so?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've timed it, and indeed it takes about 12 seconds for me with 1 million rows. The main problem is that there is no indication whether the example has actually been started, or how longstarting it should take. Maybe a big comment at the top of the file should be added?

1000 rows would not be a good test sample

I think you misread? It's 100 000. Though that's also not a good sample, because...

I've tried this with ContactGenerator.new(1_000_000).to_a, which should be the non-lazy version, and it took about 20 seconds, also not minutes. Probably because Array is also Enumerable, so it is lazy-loaded too? However, on the 100_000 version, both take around the same time, so indeed such number does not show the difference.

So I'm unsure now how to best deal with this example, but it certainly needs more explanation. Maybe both a comment in the file and also an output like "This example should take around 10 seconds to start, please wait..."?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reverted the change in table sizes.

gem 'psych', '4.0.3'
gem 'json', '2.6.1'
gem 'rspec', '~> 3.0'
gem 'coveralls', '= 0.8.23', require: false
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The repo token is valid as it enabled me in the past to submit code coverage results to a Coveralls cloud account, but I don't use Coveralls much anymore for the time being (it ran with Travis CI long time ago, which is no longer free).

If this line is not causing problems, you can keep it. If it's causing you problems, you can adjust it or remove it.

@trinistr
Copy link
Author

trinistr commented Feb 3, 2026

Thank you for reviewing! I'll probably return to this tomorrow.

@trinistr
Copy link
Author

trinistr commented Feb 5, 2026

Sorry, had some stuff come up, couldn't get back to this yesterday.

Concerning basic_code_area and basic_code_entry, they are experimental code, so if they are not working, it is not a big deal. They did work before, but in a limited fashion. I might just remove them.

I'm worried that there is a bug in CustomControl somewhere, as these examples don't seem to contain anything incriminating.

Regarding basic_table_selection and basic_table_selection2, they are supposed to just work. If they crash Ruby completely in version 4 only, maybe try to find out what line of code they crash at. It might be a Ruby 4 compatibility issue that requires some code changes.

Sorry for confusion, they crash on all versions, including 3.2, so this is probably a bug in libUI.

Regarding equalizer and facets, my mentality about them is "why fix 'em if they ain't broken"

Understandable. However, equalizer in particular has performance issue in #hash, which was fixed in dry-equalizer, so I would suggest updating to it. dry-equalizer also has no dependencies (unlike its replacement dry-core), so should be fine as a drop-in.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Newer Ruby versions support status

2 participants