<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Andy Maleh</title>
    <description>The latest articles on DEV Community by Andy Maleh (@andyobtiva).</description>
    <link>https://dev.to/andyobtiva</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F412144%2F29cbb952-50ac-4671-84cc-fc190f15887c.jpeg</url>
      <title>DEV Community: Andy Maleh</title>
      <link>https://dev.to/andyobtiva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/andyobtiva"/>
    <language>en</language>
    <item>
      <title>2025 Reminder That DHH Is a Total Idiot!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 28 Mar 2025 16:42:32 +0000</pubDate>
      <link>https://dev.to/andyobtiva/2025-reminder-that-dhh-is-a-total-idiot-44h7</link>
      <guid>https://dev.to/andyobtiva/2025-reminder-that-dhh-is-a-total-idiot-44h7</guid>
      <description>&lt;p&gt;Just a reminder that DHH is a total idiot for not adding any Frontend Ruby tech to the Rails stack in recent years. For the last 10 years, he's pretended to be "forward thinking" and "innovative", but has been closed-minded and standing in the way of progress. He is not what he used to be when he was open-minded in the minded-2000s and helped merge Merb with Rails. Nowadays, he is clearly biased towards JavaScript against Ruby to the detriment of the Ruby community. He claims he is "embracing" JavaScript for "pragmatic reasons", which might sound good on paper and might be something I'd normally agree with, but in fact is hurting the Ruby community significantly as illustrated by the attached JS code examples that many Ruby on Rails devs write nowadays as a result of DHH's closed-mindedness and stupidity. His claim for embracing JavaScript would only be true if there weren't huge differences between JavaScript and Ruby, alas there are enormous differences between the two languages. As such, DHH is an idiot and will always be called idiot unless he corrects his ways and apologizes for destroying the Ruby on Rails community by enabling devs to write code like the attached code in the last 10 years. The blood of such crappy code is on DHH's hands! Only bigger idiots would support DHH's idiotic position. They're all enemies of progress and innovation in the Ruby on Rails community. We all know Hotwire isn't enough, and the Stimulus bit is the part that many devs replace with React.js eventually or from the get-go because it doesn't solve everything effectively and conveniently. By the way, I do not necessarily propose that everyone needs Frontend Ruby as Hotwire could be sufficient for more basic Rails projects, but 100% of devs who use JS libraries like React/Angular/Ember/Vue/Svelte have zero excuses not using Frontend Ruby instead to cut their work by half with much better possibilities facilitated only by the Ruby programming language. The fact that DHH doesn't get that demonstrates how much out of depth and out of touch he's become in Ruby over the last 10 years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib0utiyl8vikln8q7y4j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib0utiyl8vikln8q7y4j.png" alt="Image description" width="800" height="1004"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhvllprym2820vspy6xe.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhvllprym2820vspy6xe.jpeg" alt="Image description" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
    </item>
    <item>
      <title>JavaScript is a disease! Ruby is the cure!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 11 Oct 2024 20:05:58 +0000</pubDate>
      <link>https://dev.to/andyobtiva/javascript-is-a-disease-ruby-is-the-cure-4c3</link>
      <guid>https://dev.to/andyobtiva/javascript-is-a-disease-ruby-is-the-cure-4c3</guid>
      <description>&lt;p&gt;In a recent Ruby meetup, I called JavaScript a disease! It is true! Especially, when comparing JavaScript code to much better, more elegant, and more readable Ruby code! JavaScript looks like ugly smelly mold by comparison. Once you see it, you can never unsee it! That's why I wouldn't touch JavaScript with a ten foot pole if I can help it in 2024. I would use Frontend Ruby instead (e.g. Opal Ruby, WASM, or Ruby2JS). Opal Ruby can usually be setup in about 10 minutes in a Rails app (&lt;a href="https://github.com/opal/opal-rails" rel="noopener noreferrer"&gt;https://github.com/opal/opal-rails&lt;/a&gt;), and it yields smaller downloadables than WASM. I am not sure why anyone in 2024 would go through the Hell of JavaScript in their otherwise pristine Ruby on Rails codebase instead of actually entering Heaven by using Frontend Ruby! Opal Ruby has won a &lt;a href="https://www.digitalfukuoka.jp/topics/228?locale=ja" rel="noopener noreferrer"&gt;Fukuoka Ruby 2023 Award&lt;/a&gt; and supports Ruby 3.1 with the ability to use any pure Ruby gems in the Frontend by simply including them in Gemfile. That removes the need for a complicated JavaScript bundling beast like Webpack. In the past, I might have advocated for still using JavaScript in smaller apps, but the barrier of integrating modern Ruby into the Frontend of Rails applications has become so non-existent with Opal, there are no more excuses for using JavaScript in a Ruby on Rails codebase. &lt;/p&gt;

&lt;p&gt;Yahuda Katz mentioned in his keynote speech at RailsConf 2014 (&lt;a href="https://youtu.be/9naDS3r4MbY?t=1195" rel="noopener noreferrer"&gt;https://youtu.be/9naDS3r4MbY?t=1195&lt;/a&gt;), which borrowed ideas from Steve Jobs, that by continuously building more floors for the lower levels of a building in the form of a framework and a community of open-source projects, we enable developers to start development at higher and higher levels than they would have been able to otherwise, thus helping them leapfrog earlier ways of development in ever increasing productivity! In 2024, Frontend Ruby (e.g. Opal) is the next floor level that enables Ruby Software Engineers to start at a higher level of development with much higher productivity and maintainability. I strongly believe that anyone who is not using Frontend Ruby in 2024 is at least half as productive as those who are using Frontend Ruby in their Rails development, regardless of whatever framework they are using. I don't care if someone is enamored by some "cool JavaScript framework xyz"; try to implement that framework in Ruby, and IT WILL BE EVER COOLER AND BETTER IN RUBY! Or, in certain instances, you will discover that Ruby is so much simpler than JavaScript, YOU DO NOT EVEN NEED the "cool" JavaScript frameworks as they are UNCOOL IN RUBYLAND! Glimmer DSL for Web is one Frontend Ruby Framework example that demonstrates the unique simplicity/readability of Ruby that is unmatched by cryptic/too-clever JavaScript code: &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web" rel="noopener noreferrer"&gt;https://github.com/AndyObtiva/glimmer-dsl-web&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;JavaScript is a disease! Ruby is the cure! Don't be part of the problem by using JavaScript in Ruby on Rails codebases! Be part of the solution by using the language we all love, Ruby, isomorphically in Ruby on Rails applications in 2024 and beyond!&lt;/p&gt;

&lt;p&gt;Blog post version for sharing:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2024/10/javascript-is-disease-ruby-is-cure.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2024/10/javascript-is-disease-ruby-is-cure.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Lack of Support and Participation in the Software Engineering Community Violates The Software Engineering Code of Ethics</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Mon, 16 Sep 2024 20:06:14 +0000</pubDate>
      <link>https://dev.to/andyobtiva/lack-of-support-and-participation-in-the-software-engineering-community-violates-the-software-engineering-code-of-ethics-2f1p</link>
      <guid>https://dev.to/andyobtiva/lack-of-support-and-participation-in-the-software-engineering-community-violates-the-software-engineering-code-of-ethics-2f1p</guid>
      <description>&lt;p&gt;Some Software Engineers mention "not being interested" as an excuse not to help someone with something that could benefit customers or the Software Engineering community at large when the real reason is in fact covert discrimination against that person and lack of effort to treat them as an equal and equally respected member of their community. Know that Software Engineers have to abide by the Software Engineering Code of Ethics:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.computer.org/education/code-of-ethics" rel="noopener noreferrer"&gt;https://www.computer.org/education/code-of-ethics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, it includes the statements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Software engineers shall act consistently with the public interest."&lt;/li&gt;
&lt;li&gt;"Software engineers shall be fair to and supportive of their colleagues."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, if someone gives you an excuse of "not being interested" to avoid helping you out with a public interest matter out of discrimination against you, know that they have conducted themselves in an unethical manner and remind them of what they signed up for when they became Software Engineers, whether implicitly or explicitly.&lt;/p&gt;

&lt;p&gt;This even extends to matters like Software Engineers not wanting to check out certain technologies/libraries that could greatly help the public interest just out of discrimination against the technology/library creators. It also covers matters of Software Engineers not wanting to learn and improve certain skills through frequent attendance of local user groups that can improve the practice of their profession.&lt;/p&gt;

&lt;p&gt;After all, that is covered by the statement:&lt;/p&gt;

&lt;p&gt;"Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession."&lt;/p&gt;

&lt;p&gt;I am including the short version of the Software Engineering Code of Ethics below for your convenience:&lt;/p&gt;

&lt;p&gt;Software engineers shall commit themselves to making the analysis, specification, design, development, testing and maintenance of software a beneficial and respected profession. In accordance with their commitment to the health, safety and welfare of the public, software engineers shall adhere to the following Eight Principles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;PUBLIC – Software engineers shall act consistently with the public interest.&lt;/li&gt;
&lt;li&gt;CLIENT AND EMPLOYER – Software engineers shall act in a manner that is in the best interests of their client and employer consistent with the public interest.&lt;/li&gt;
&lt;li&gt;PRODUCT – Software engineers shall ensure that their products and related modifications meet the highest professional standards possible.&lt;/li&gt;
&lt;li&gt;JUDGMENT – Software engineers shall maintain integrity and independence in their professional judgment.&lt;/li&gt;
&lt;li&gt;MANAGEMENT – Software engineering managers and leaders shall subscribe to and promote an ethical approach to the management of software development and maintenance.&lt;/li&gt;
&lt;li&gt;PROFESSION – Software engineers shall advance the integrity and reputation of the profession consistent with the public interest.&lt;/li&gt;
&lt;li&gt;COLLEAGUES – Software engineers shall be fair to and supportive of their colleagues.&lt;/li&gt;
&lt;li&gt;SELF – Software engineers shall participate in lifelong learning regarding the practice of their profession and shall promote an ethical approach to the practice of the profession.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Blog post version for sharing, titled "Lack of Support and Participation in the Software Engineering Community Violates The Software Engineering Code of Ethics":&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2024/09/lack-of-support-and-participation-in.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2024/09/lack-of-support-and-participation-in.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>community</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>10x Developer Puzzle, Solved!!!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Tue, 03 Sep 2024 19:26:51 +0000</pubDate>
      <link>https://dev.to/andyobtiva/10x-developer-puzzle-solved-3ceh</link>
      <guid>https://dev.to/andyobtiva/10x-developer-puzzle-solved-3ceh</guid>
      <description>&lt;p&gt;Here is a thought! The mythical 10x Developer is simply a developer that eliminates 9/10 of unnecessary over-engineered code, and then writes the remaining 1/10 of the code needed at the productivity rate of a 1x Developer!&lt;/p&gt;

&lt;p&gt;Such a developer might come across as a 10x Developer to others when in fact, all they are is a 1x Developer that knows how to cut the fat of over-engineering out and avoid unnecessary overhyped libraries/languages/technologies to eliminate 9/10 of development waste and only do 1/10 of the work otherwise done. &lt;/p&gt;

&lt;p&gt;I believe I have just solved the 10x Developer puzzle for once and for all! The 10x Developer mystery has been demystified for good!!&lt;/p&gt;

&lt;p&gt;Originally posted at the Code Master blog:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2024/09/10x-developer-puzzle-solved.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2024/09/10x-developer-puzzle-solved.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Glimmer DSL for Web Ruby Integration with JavaScript Libraries</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 17 May 2024 21:28:03 +0000</pubDate>
      <link>https://dev.to/andyobtiva/glimmer-dsl-for-web-ruby-integration-with-javascript-libraries-1b32</link>
      <guid>https://dev.to/andyobtiva/glimmer-dsl-for-web-ruby-integration-with-javascript-libraries-1b32</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt; is a &lt;a href="https://www.youtube.com/watch?v=4AdcfbI6A4c"&gt;Ruby-in-the-Browser&lt;/a&gt; Web Frontend Framework that enables Rubyists to finally have Ruby productivity and happiness in the Frontend via a simpler, more intuitive, more straightforward, and more productive library than all JavaScript libraries like React, Angular, Ember, Vue, Svelte, etc.... &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt;'s Rails sample app "&lt;a href="https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app"&gt;Sample Selector&lt;/a&gt;" has been upgraded with Code Syntax Highlighting by integrating with &lt;a href="https://highlightjs.org/"&gt;highlight.js&lt;/a&gt;. It demonstrates how to integrate with JavaScript libraries, how to build Glimmer Web Components in the Frontend, and how to make HTTP calls from a Ruby Frontend to a Ruby Backend in a Rails application, among other things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3_THfJR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/raw/master/sample-glimmer-dsl-web-rails7-app.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3_THfJR7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/raw/master/sample-glimmer-dsl-web-rails7-app.gif" alt="Sample Selector" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app"&gt;Sample Selector&lt;/a&gt; Rails app enables users to list all samples that ship with the glimmer-dsl-web Ruby gem, show each sample's entry point code, and run the sample in the browser. &lt;/p&gt;

&lt;p&gt;Here is a breakdown of the code:&lt;/p&gt;

&lt;p&gt;The Rails layout includes links to the highlight.js javascript CDN URLs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;SampleGlimmerDslOpalRails7App&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width,initial-scale=1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;csrf_meta_tags&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;csp_meta_tag&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/ruby.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.8.0/highlightjs-line-numbers.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;stylesheet_link_tag&lt;/span&gt; &lt;span class="s2"&gt;"application"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"data-turbo-track"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"reload"&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;javascript_importmap_tags&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Rails View renders a Glimmer Web Component using the &lt;code&gt;glimmer_component&lt;/code&gt; Rails helper (this is meant to be a drop-in replacement for JS solutions like &lt;code&gt;react_component&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"text-align: center;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Glimmer DSL for Web Rails 7 Sample App&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="n"&gt;glimmer_component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'sample_selector'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample Selector Top-Level Glimmer Web Component is the entry point to the Frontend application, which simply consists of 2 other Glimmer Web Components, the Samples Table (samples_table) and the Highlighted Code (highlighted_code). It is as simple as the code could get, and way simpler and lighter than alternative JavaScript library approaches like React, thus cutting down on maintainability cost and time to delivery significantly, for both small and large apps alike:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web'&lt;/span&gt;

&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/presenters/sample_selector_presenter'&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/views/back_anchor'&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/views/highlighted_code'&lt;/span&gt;
&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_selector/views/samples_table'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleSelector&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;before_render&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="vi"&gt;@presenter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SampleSelectorPresenter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Run a sample or view a sample's code."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s1"&gt;'text-align: center;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;highlighted_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;language: &lt;/span&gt;&lt;span class="s1"&gt;'ruby'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;model: &lt;/span&gt;&lt;span class="vi"&gt;@presenter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;model_code_attribute: :selected_sample_code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;float: &lt;/span&gt;&lt;span class="s1"&gt;'right'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;samples_table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;presenter: &lt;/span&gt;&lt;span class="vi"&gt;@presenter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;button&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s1"&gt;'margin: 15px 0; padding: 10px; font-size: 1.3em;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;onclick&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prevent_default&lt;/span&gt;
          &lt;span class="n"&gt;markup_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;
          &lt;span class="no"&gt;BackAnchor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;
          &lt;span class="vi"&gt;@presenter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Highlighted Code Glimmer Web Component declaratively handles loading sample code into an HTML View innerHTML through unidirectional data-binding to the Sample Model code attribute, applying syntax highlighting using highlight.js after reading from the Model whenever updates happen to the View. The code has an excellent separation of concerns between the View and Model, and is a lot simpler than equivalent React code, thus much easier to reason about. Additionally, some CSS was written directly in a Ruby DSL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HighlightedCode&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:language&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="s1"&gt;'ruby'&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:model&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:model_code_attribute&lt;/span&gt; &lt;span class="c1"&gt;# name of attribute on model that holds code string to render&lt;/span&gt;
  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;default: &lt;/span&gt;&lt;span class="s1"&gt;'initial'&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;div&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'code-scrollable-container'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s2"&gt;"float: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;float&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;pre&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="vi"&gt;@code_element&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s2"&gt;"language-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;inner_html&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model_code_attribute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="ss"&gt;after_read: &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;highlight_code&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
                        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div.code-scrollable-container'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;overflow&lt;/span&gt; &lt;span class="s1"&gt;'scroll'&lt;/span&gt;
          &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="s1"&gt;'calc(100vw - 410px)'&lt;/span&gt;
          &lt;span class="n"&gt;height&lt;/span&gt; &lt;span class="s1"&gt;'80vh'&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid rgb(209, 215, 222)'&lt;/span&gt;
          &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'div.code-scrollable-container pre'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;margin&lt;/span&gt; &lt;span class="s1"&gt;'0'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'.hljs-ln td.hljs-ln-line.hljs-ln-numbers'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;user_select&lt;/span&gt; &lt;span class="s1"&gt;'none'&lt;/span&gt;
          &lt;span class="n"&gt;text_align&lt;/span&gt; &lt;span class="s1"&gt;'center'&lt;/span&gt;
          &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="s1"&gt;'rgb(101, 109, 118)'&lt;/span&gt;
          &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;'3px 30px'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;highlight_code&lt;/span&gt;
    &lt;span class="vi"&gt;@code_element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dom_element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeAttr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'data-highlighted'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# $$ enables interacting with global JS scope, like top-level hljs variable to use highlight.js library&lt;/span&gt;
    &lt;span class="vg"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hljs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;highlightAll&lt;/span&gt;
    &lt;span class="vg"&gt;$$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hljs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initLineNumbersOnLoad&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Samples Table lists all the samples that are included in the &lt;code&gt;glimmer-dsl-web&lt;/code&gt; Ruby gem, and provides the ability to select a sample and run it. It also interacts with a Sample API Web Service to pull sample code data from the Rails backend, thus ensuring a proper separation of concerns for maximum maintainability. Some CSS is added with a Ruby DSL as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SamplesTable&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="ss"&gt;:presenter&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;class: &lt;/span&gt;&lt;span class="s1"&gt;'samples'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;tbody&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="no"&gt;SampleSelectorPresenter&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;SAMPLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;tr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;td&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;presenter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:selected_sample&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="ss"&gt;on_read: &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s1"&gt;'selected'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
                          &lt;span class="p"&gt;]&lt;/span&gt;

            &lt;span class="n"&gt;onclick&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
              &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prevent_default&lt;/span&gt;
              &lt;span class="n"&gt;presenter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selected_sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="n"&gt;tr&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;# handle this sample differently via links to demonstrate visiting outside pages&lt;/span&gt;
          &lt;span class="n"&gt;td&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Hello, glimmer_component Rails Helper!'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' ( '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Run'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"data-turbo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;href: &lt;/span&gt;&lt;span class="s1"&gt;'/?address=true&amp;amp;full_name=John%20Doe&amp;amp;street=123%20Main%20St&amp;amp;street2=apt%2012&amp;amp;city=San%20Diego&amp;amp;state=California&amp;amp;zip_code=91911'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' | '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Code'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="ss"&gt;target: &lt;/span&gt;&lt;span class="s1"&gt;'_blank'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="ss"&gt;href: &lt;/span&gt;&lt;span class="s1"&gt;'https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app/blob/master/app/views/welcomes/_address_page.html.erb'&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;span&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' ) '&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;style&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border_spacing&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples tr td'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid transparent'&lt;/span&gt;
          &lt;span class="n"&gt;padding&lt;/span&gt; &lt;span class="s1"&gt;'5px'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples tr td:hover'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid gray'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'table.samples tr.selected td'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;border&lt;/span&gt; &lt;span class="s1"&gt;'1px solid lightgray'&lt;/span&gt;
          &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="s1"&gt;'lightblue'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Back Anchor provides a back-link to enable going back to the main page from any run sample:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BackAnchor&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Web&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Component&lt;/span&gt;

  &lt;span class="n"&gt;markup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'&amp;lt;&amp;lt; Back To Samples'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;href: &lt;/span&gt;&lt;span class="s1"&gt;'#'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;style: &lt;/span&gt;&lt;span class="s1"&gt;'display: block; margin-bottom: 10px;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;back_anchor&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;onclick&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;back_anchor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;
        &lt;span class="no"&gt;Element&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'body &amp;gt; *'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:remove&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="no"&gt;SampleSelector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;parent: &lt;/span&gt;&lt;span class="s2"&gt;".sample_selector"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample Selector Presenter provides all the data and actions that the Sample Selector View needs, including how to present sample names, the attribute for storing the selected sample, and the method for running a sample, which delegates to the Sample Model to keep concerns better separated for higher maintainability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'../models/sample'&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleSelectorPresenter&lt;/span&gt;
  &lt;span class="no"&gt;SAMPLE_NAMES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_world'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, World!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_button'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Button!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_form'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Form!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_observer'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Observer!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_observer_data_binding'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Observer (Data-Binding)!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_data_binding'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Data-Binding!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_content_data_binding'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Content Data-Binding!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_component'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Component!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_paragraph'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Paragraph!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_input_date_time'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Input Date/Time!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'hello_form_mvp'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Hello, Form (MVP)!'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'button_counter'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Button Counter'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="no"&gt;SAMPLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SAMPLE_NAMES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="no"&gt;Sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:selected_sample&lt;/span&gt;
  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:selected_sample_code&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selected_sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;SAMPLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;selected_sample&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;# causes selected sample to get highlighted in the View indirectly through data-binding&lt;/span&gt;
    &lt;span class="vi"&gt;@selected_sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;

    &lt;span class="vi"&gt;@selected_sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch_code&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="c1"&gt;# causes selected sample code to display in the View indirectly through data-binding&lt;/span&gt;
      &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;selected_sample_code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
    &lt;span class="n"&gt;selected_sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample Model stores sample specific data like the code and ID, enables fetching sample code from the Rails Backend using a Sample API Web Service, and provides and the ability to run a sample by loading the associated sample Ruby file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require_relative&lt;/span&gt; &lt;span class="s1"&gt;'sample_api'&lt;/span&gt;

&lt;span class="c1"&gt;# Sample Frontend Model&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Sample&lt;/span&gt;
  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:code&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:,&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="vi"&gt;@id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;id&lt;/span&gt;
    &lt;span class="vi"&gt;@name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_code&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;code_processor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="no"&gt;SampleApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="vi"&gt;@code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;code&lt;/span&gt;
      &lt;span class="n"&gt;code_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;
    &lt;span class="c1"&gt;# We must embeded static require/load statements for Opal to pre-load them into page&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="vi"&gt;@id&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_world'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_world.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_world.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_button'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_button.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_button.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_form'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_observer'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_observer_data_binding'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_observer_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_data_binding'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_content_data_binding'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_content_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_content_data_binding.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_component'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_component.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_component.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_paragraph'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_paragraph.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_paragraph.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_input_date_time'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_input_date_time.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_input_date_time.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'hello_form_mvp'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form_mvp.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/hello/hello_form_mvp.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="s1"&gt;'button_counter'&lt;/span&gt;
      &lt;span class="k"&gt;begin&lt;/span&gt;
        &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/regular/button_counter.rb'&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;LoadError&lt;/span&gt; &lt;span class="c1"&gt;# the first time a file is loaded, it raises LoadError and must be required instead&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'glimmer-dsl-web/samples/regular/button_counter.rb'&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Sample API Web Service simply makes HTTP calls to the Rails backend to grab data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Sample Resource HTTP API that calls Rails Backend Samples API Endpoint&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SampleApi&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;sample_processor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/samples/&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="c1"&gt;# Wrapping response body with Native to convert from a JS object to an Opal Ruby object, &lt;/span&gt;
        &lt;span class="c1"&gt;# thus converting JS properties into Ruby methods that facilitate interaction with object.&lt;/span&gt;
        &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Native&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sample_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In conclusion, we demonstrated in the &lt;a href="https://github.com/AndyObtiva/sample-glimmer-dsl-web-rails7-app"&gt;Sample Selector&lt;/a&gt; app a Rails Frontend application that is written fully in Ruby with Ruby DSLs in place of HTML/CSS/JavaScript, is following the Model-View-Presenter pattern (a variation on MVC), includes HTTP calls to a Rails Backend to demonstrate real Business Use-Cases of Frontend/Backend interaction, and integrates with an external JavaScript library (highlight.js) for Code Syntax Highlighting. &lt;/p&gt;

&lt;p&gt;As a result, Rails Software Engineers do not have to be split anymore between those who are afraid of Frontend Development because of JavaScript, and those who prefer to do Frontend Development in spite of JavaScript's pitfalls. Instead, there is a 3rd better way that unites all Rails Software Engineers! Just write the Frontend in the same language you love so much in the Backend due to offering maximum productivity and maintainability: Ruby! This should become the no-brainer future of all Frontend development in Rails!!!&lt;/p&gt;

&lt;p&gt;I will leave you with the &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt; introduction from the project README on GitHub:&lt;/p&gt;

&lt;p&gt;"You can finally have Ruby developer happiness and productivity in the Frontend! No more wasting time splitting your resources across multiple languages, using badly engineered, over-engineered, or premature-optimization-obsessed JavaScript libraries, fighting JavaScript build issues (e.g. webpack), or rewriting Ruby Backend code in Frontend JavaScript. With Ruby in the Browser, you can have an exponential jump in development productivity (2x or higher), time-to-release (1/2 or less time), cost (1/2 or cheaper), and maintainability (~50% the code that is simpler and more readable) over JavaScript libraries like React, Angular, Ember, Vue, and Svelte, while being able to reuse Backend Ruby code as is in the Frontend for faster interactions when needed. Ruby in the Browser finally fulfills every highly-productive Rubyist's dream by bringing Ruby productivity fun to Frontend Development, the same productivity fun you had for years and decades in Backend Development."&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>frontend</category>
      <category>glimmer</category>
    </item>
    <item>
      <title>Montreal.rb 2024/03 - Frontend Ruby with Glimmer DSL for Web - Andy Maleh</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Thu, 07 Mar 2024 18:50:15 +0000</pubDate>
      <link>https://dev.to/andyobtiva/montrealrb-202403-frontend-ruby-with-glimmer-dsl-for-web-andy-maleh-58p6</link>
      <guid>https://dev.to/andyobtiva/montrealrb-202403-frontend-ruby-with-glimmer-dsl-for-web-andy-maleh-58p6</guid>
      <description>&lt;p&gt;The talk video and slides have been posted for the Montreal.rb March 2024 talk "Frontend Ruby with &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-web"&gt;Glimmer DSL for Web&lt;/a&gt;" (Ruby in the Browser Web Frontend Framework).&lt;/p&gt;

&lt;p&gt;YouTube Video :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=rIZ-ILUv9ME&amp;amp;list=PLRAf4zt5oEjc2mqmEN9m_O0JovQCXxvxt&amp;amp;index=11"&gt;https://www.youtube.com/watch?v=rIZ-ILUv9ME&amp;amp;list=PLRAf4zt5oEjc2mqmEN9m_O0JovQCXxvxt&amp;amp;index=11&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Google Slides :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.google.com/presentation/d/e/2PACX-1vQVihtMktOEJ-AJWb1a-uyJfpyn7q92xstcx7QLIUOFONzG5TmKD7_2hSLdwijgw-l6LdK6OLbQPP61/pub?start=false&amp;amp;loop=false&amp;amp;delayms=60000"&gt;https://docs.google.com/presentation/d/e/2PACX-1vQVihtMktOEJ-AJWb1a-uyJfpyn7q92xstcx7QLIUOFONzG5TmKD7_2hSLdwijgw-l6LdK6OLbQPP61/pub?start=false&amp;amp;loop=false&amp;amp;delayms=60000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blog Post Announcement :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://andymaleh.blogspot.com/2024/03/montrealrb-march-2024-frontend-ruby.html"&gt;https://andymaleh.blogspot.com/2024/03/montrealrb-march-2024-frontend-ruby.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Talk Description :&lt;/p&gt;

&lt;p&gt;Rubyists would rather leverage the productivity, readability, and maintainability benefits of Ruby in Frontend Web Development than JavaScript to cut down development cost and time by half compared to using popular yet inferior JavaScript frameworks with bloated JavaScript code as per Matz's suggestion in his RubyConf 2022 keynote speech to replace JavaScript with Ruby. Fortunately, this is possible in 2024!&lt;/p&gt;

&lt;p&gt;This talk is a continuation of the previous Montreal.rb talk "Intro to Ruby in the Browser", which ended by promising a new way in the future for developing Web Frontends that would completely revolutionize the way we think about and do Frontend Development using Ruby instead of JavaScript. The future is now!!! The simplest, most intuitive, most straight-forward, and most productive Frontend Framework in existence is here! It is an open-source Ruby gem called Glimmer DSL for Web.&lt;/p&gt;

&lt;p&gt;Think of Glimmer DSL for Web as the Rails of Frontend Frameworks. With it, you can finally live in Rubyland in both the Frontend and Backend on the Web! That opens up the door to ideas like rendering Frontend Components in the Backend as Server Components in the future, eliminating the conflict between ERB and JS frontend rendering technologies by leveraging highly readable, maintainable, and productive Ruby code isomorphically.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>glimmer</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Slides &amp; Code for RubyConf 2023 Workshop "How To Build Desktop Applications in Ruby"</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Wed, 15 Nov 2023 03:49:21 +0000</pubDate>
      <link>https://dev.to/andyobtiva/slides-code-for-rubyconf-2023-workshop-how-to-build-desktop-applications-in-ruby-2923</link>
      <guid>https://dev.to/andyobtiva/slides-code-for-rubyconf-2023-workshop-how-to-build-desktop-applications-in-ruby-2923</guid>
      <description>&lt;p&gt;Thanks to everyone who attended my RubyConf 2023 2-Hour Workshop "How To Build Desktop Applications in Ruby". For those who missed the event, I posted the presentation slides and code exercises (27 exercises) on GitHub. I also blogged about the new Color The Circles game app that was developed at the RubyConf 2023 Community Day Glimmer Desktop Hacking event.&lt;/p&gt;

&lt;p&gt;More at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://andymaleh.blogspot.com/2023/11/rubyconf-2023-how-to-build-desktop.html"&gt;https://andymaleh.blogspot.com/2023/11/rubyconf-2023-how-to-build-desktop.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitHub Repo Direct Link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby"&gt;https://github.com/AndyObtiva/how-to-build-desktop-applications-in-ruby&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Presentation Slides Direct Link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://bit.ly/rubyconf2023desktop"&gt;https://bit.ly/rubyconf2023desktop&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>conference</category>
      <category>desktop</category>
      <category>workshop</category>
    </item>
    <item>
      <title>Glimmer DSL for LibUI Scaffolding + Snake Game</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Sun, 22 Oct 2023 21:33:29 +0000</pubDate>
      <link>https://dev.to/andyobtiva/glimmer-dsl-for-libui-scaffolding-snake-game-2im7</link>
      <guid>https://dev.to/andyobtiva/glimmer-dsl-for-libui-scaffolding-snake-game-2im7</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui"&gt;Glimmer DSL for LibUI&lt;/a&gt; (Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library) versions 0.9.x include support for a new &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui#glimmer-command"&gt;Glimmer Command&lt;/a&gt;, &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui#scaffold-application"&gt;Application Scaffolding&lt;/a&gt;, Custom Component Scaffolding, Custom Component Gem Scaffolding, and more. These features greatly improve Software Engineering Productivity when building desktop applications with Glimmer DSL for LibUI. Glimmer Scaffolding could be thought of as the "Desktop Application" equivalent of Rails Scaffolding and Generators.&lt;/p&gt;

&lt;p&gt;Application Scaffolding enables automatically generating the directories/files of a new desktop GUI application that follows the MVC architecture and can be packaged as a Ruby gem that includes a binary script for running the app conveniently.&lt;/p&gt;

&lt;p&gt;In fact, I ate my own dog food and used the new Application Scaffolding feature to effortlessly scaffold a Glimmer Snake game (code is included near the bottom of this post):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer_snake"&gt;https://github.com/AndyObtiva/glimmer_snake&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FL1plb0z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer_snake/raw/master/screenshots/glimmer-dsl-libui-mac-snake.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FL1plb0z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer_snake/raw/master/screenshots/glimmer-dsl-libui-mac-snake.gif" alt="glimmer snake" width="302" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the gemified app edition of the &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui/blob/master/docs/examples/GLIMMER-DSL-LIBUI-ADVANCED-EXAMPLES.md#snake"&gt;Snake game example&lt;/a&gt; that is included in &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui"&gt;Glimmer DSL for LibUI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Learn more at this blog post (and at the &lt;a href="https://github.com/AndyObtiva/glimmer_snake"&gt;Glimmer DSL for LibUI&lt;/a&gt; project and &lt;a href="https://github.com/AndyObtiva/glimmer_snake"&gt;Glimmer Snake&lt;/a&gt; game pages):&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2023/10/glimmer-dsl-for-libui-scaffolding-snake.html"&gt;https://andymaleh.blogspot.com/2023/10/glimmer-dsl-for-libui-scaffolding-snake.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy &lt;a href="https://github.com/AndyObtiva/glimmer_snake"&gt;Glimmering&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>desktop</category>
      <category>gui</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Glimmer Wordle 1.1.5 Windows Support</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Wed, 18 Oct 2023 23:12:03 +0000</pubDate>
      <link>https://dev.to/andyobtiva/glimmer-wordle-115-windows-support-2ke5</link>
      <guid>https://dev.to/andyobtiva/glimmer-wordle-115-windows-support-2ke5</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer_wordle" rel="noopener noreferrer"&gt;Glimmer Wordle 1.1.5&lt;/a&gt; (open-source desktop game) has just been released with official support for Windows. Although the game worked on Windows before, thanks to the platform-independent Glimmer DSL for SWT GUI library it was built with, styling was not tweaked for Windows till now in &lt;a href="https://rubygems.org/gems/glimmer_wordle" rel="noopener noreferrer"&gt;version 1.1.5&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAndyObtiva%2Fglimmer_wordle%2Fmaster%2Fscreenshots%2Fglimmer-wordle-windows.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAndyObtiva%2Fglimmer_wordle%2Fmaster%2Fscreenshots%2Fglimmer-wordle-windows.png" alt="Windows Wordle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To give you an idea of how the game flows, here is an animated Gif with it running on the Mac:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAndyObtiva%2Fglimmer_wordle%2Fraw%2Fmaster%2Fscreenshots%2Fglimmer-wordle.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2FAndyObtiva%2Fglimmer_wordle%2Fraw%2Fmaster%2Fscreenshots%2Fglimmer-wordle.gif" alt="Mac Wordle Video"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the Glimmer code of the GUI View:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Wordle&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;View&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppView&lt;/span&gt;
      &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;Glimmer&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;UI&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;CustomShell&lt;/span&gt;

      &lt;span class="no"&gt;COLOR_TO_BACKGROUND_COLOR_MAP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;green:  &lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;106&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;170&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="ss"&gt;yellow: &lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="ss"&gt;gray:   &lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;124&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;126&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="no"&gt;COLOR_TO_TEXT_COLOR_MAP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;green:  :white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;yellow: :white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;gray:   :white&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="no"&gt;ALPHABET_LAYOUTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="ss"&gt;alphabetical: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="sx"&gt;%w[A B C D E F G H I J]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sx"&gt;%w[K L M N O P Q R S]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sx"&gt;%w[T U V W X Y Z]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="ss"&gt;qwerty: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="sx"&gt;%w[Q W E R T Y U I O P]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sx"&gt;%w[A S D F G H J K L]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="sx"&gt;%w[Z X C V B N M]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="no"&gt;CONFIG_FILE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;home&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.glimmer_wordle'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="n"&gt;before_body&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="vi"&gt;@display&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;display&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;on_about&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;display_about_dialog&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="n"&gt;on_preferences&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;display_about_dialog&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="n"&gt;on_swt_keydown&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;
              &lt;span class="n"&gt;do_backspace&lt;/span&gt;
            &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;swt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:arrow_left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="n"&gt;do_left&lt;/span&gt;
            &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;swt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:arrow_right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="n"&gt;do_right&lt;/span&gt;
            &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyCode&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;swt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:cr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@five_letter_word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:in_progress&lt;/span&gt;
                &lt;span class="n"&gt;do_guess&lt;/span&gt;
              &lt;span class="k"&gt;else&lt;/span&gt;
                &lt;span class="n"&gt;do_restart&lt;/span&gt;
              &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="k"&gt;elsif&lt;/span&gt; &lt;span class="n"&gt;valid_character?&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chr&lt;/span&gt; &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="n"&gt;do_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key_event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;keyCode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="vi"&gt;@five_letter_word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;FiveLetterWord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_config&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:alphabet_layout&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="ss"&gt;:alphabetical&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="c1"&gt;## Add widget content inside custom shell body&lt;/span&gt;
      &lt;span class="c1"&gt;## Top-most widget must be a shell or another custom shell&lt;/span&gt;
      &lt;span class="c1"&gt;#&lt;/span&gt;
      &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:no_resize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;grid_layout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;margin_width&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
            &lt;span class="n"&gt;margin_height&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
            &lt;span class="n"&gt;vertical_spacing&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="c1"&gt;# Replace example content below with custom shell content&lt;/span&gt;
          &lt;span class="n"&gt;minimum_size&lt;/span&gt; &lt;span class="mi"&gt;420&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;540&lt;/span&gt;
          &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;APP_ROOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'icons'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'windows'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Glimmer Wordle.ico"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt;
          &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;APP_ROOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'icons'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'linux'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Glimmer Wordle.png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt;
          &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s2"&gt;"Glimmer Wordle"&lt;/span&gt;
          &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="ss"&gt;:white&lt;/span&gt;

          &lt;span class="n"&gt;app_menu_bar&lt;/span&gt;

          &lt;span class="n"&gt;alphabet_container&lt;/span&gt;

          &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;layout_data&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'You have 6 tries to guess a 5-letter word'&lt;/span&gt;
            &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="ss"&gt;:transparent&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="n"&gt;word_guesser&lt;/span&gt;

          &lt;span class="n"&gt;guess_button&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;app_menu_bar&lt;/span&gt;
        &lt;span class="n"&gt;menu_bar&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;Game'&lt;/span&gt;

            &lt;span class="n"&gt;menu_item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;Restart'&lt;/span&gt;

              &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;do_restart&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;menu_item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'E&amp;amp;xit'&lt;/span&gt;

              &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nb"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="n"&gt;menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;View'&lt;/span&gt;

            &lt;span class="n"&gt;menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'Alphabet &amp;amp;Layout'&lt;/span&gt;

              &lt;span class="n"&gt;menu_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:radio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;Alphabetical'&lt;/span&gt;
                &lt;span class="n"&gt;selection&lt;/span&gt; &lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:alphabetical&lt;/span&gt;

                &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alphabet_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:alphabetical&lt;/span&gt;
                  &lt;span class="n"&gt;rebuild_alphabet_container&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;

              &lt;span class="n"&gt;menu_item&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:radio&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;Qwerty'&lt;/span&gt;
                &lt;span class="n"&gt;selection&lt;/span&gt; &lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:qwerty&lt;/span&gt;

                &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;alphabet_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:qwerty&lt;/span&gt;
                  &lt;span class="n"&gt;rebuild_alphabet_container&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="n"&gt;menu&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;Help'&lt;/span&gt;

            &lt;span class="n"&gt;menu_item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;Instructions'&lt;/span&gt;

              &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;display_instructions_dialog&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="n"&gt;menu_item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'&amp;amp;About'&lt;/span&gt;

              &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;display_about_dialog&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;display_instructions_dialog&lt;/span&gt;
        &lt;span class="n"&gt;message_box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'Instructions'&lt;/span&gt;
          &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;~&lt;/span&gt;&lt;span class="no"&gt;MULTI_LINE_STRING&lt;/span&gt;&lt;span class="sh"&gt;
            Make 6 guesses for a 5-letter word.

            If you enter a letter that is part of the word, and at the right location, it becomes green,

            If you enter a letter that is part of the word, but at the wrong location, it becomes yellow.

            If you enter a letter that is not part of the word, it becomes red.
&lt;/span&gt;&lt;span class="no"&gt;          MULTI_LINE_STRING&lt;/span&gt;
        &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;display_about_dialog&lt;/span&gt;
        &lt;span class="n"&gt;message_box&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'About'&lt;/span&gt;
          &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="s2"&gt;"Glimmer Wordle &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;VERSION&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;LICENSE&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;alphabet_container&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;composite&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;layout_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

          &lt;span class="n"&gt;grid_layout&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;margin_width&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;margin_height&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="n"&gt;vertical_spacing&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="ss"&gt;:white&lt;/span&gt;

          &lt;span class="n"&gt;alphabets&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;alphabets&lt;/span&gt;
        &lt;span class="n"&gt;alphabet_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ALPHABET_LAYOUTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;layout_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;width_hint&lt;/span&gt; &lt;span class="mi"&gt;318&lt;/span&gt;
            &lt;span class="n"&gt;height_hint&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;alphabet_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ALPHABET_LAYOUTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;layout_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;width_hint&lt;/span&gt; &lt;span class="mi"&gt;288&lt;/span&gt;
            &lt;span class="n"&gt;height_hint&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;alphabet_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;ALPHABET_LAYOUTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;layout_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;width_hint&lt;/span&gt; &lt;span class="mi"&gt;222&lt;/span&gt;
            &lt;span class="n"&gt;height_hint&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;alphabet_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alphabet_characters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;canvas&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
          &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="ss"&gt;:white&lt;/span&gt;

          &lt;span class="vi"&gt;@alphabet_rectangles&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
          &lt;span class="vi"&gt;@alphabet_borders&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
          &lt;span class="vi"&gt;@alphabet_letters&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
          &lt;span class="n"&gt;alphabet_characters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;alphabet_character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="vi"&gt;@alphabet_rectangles&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@alphabet_row_offset_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="ss"&gt;:transparent&lt;/span&gt;

              &lt;span class="vi"&gt;@alphabet_borders&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rectangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;foreground&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;
                &lt;span class="n"&gt;line_width&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;

              &lt;span class="vi"&gt;@alphabet_letters&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;alphabet_character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linux?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="n"&gt;alphabet_font&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;alphabet_layout_alphabets&lt;/span&gt;
        &lt;span class="no"&gt;ALPHABET_LAYOUTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(:&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;word_guesser&lt;/span&gt;
        &lt;span class="vi"&gt;@canvasses&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="n"&gt;margin_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
        &lt;span class="n"&gt;margin_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
        &lt;span class="vi"&gt;@canvasses&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;canvas&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;layout_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;width_hint&lt;/span&gt; &lt;span class="mi"&gt;230&lt;/span&gt;
            &lt;span class="n"&gt;height_hint&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="ss"&gt;:white&lt;/span&gt;
          &lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

          &lt;span class="vi"&gt;@rectangles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
          &lt;span class="vi"&gt;@borders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
          &lt;span class="vi"&gt;@letters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
          &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="vi"&gt;@rectangles&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;margin_x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;margin_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;background&lt;/span&gt; &lt;span class="ss"&gt;:transparent&lt;/span&gt;

              &lt;span class="vi"&gt;@borders&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;rectangle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;foreground&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="ss"&gt;:title_background&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;
                &lt;span class="n"&gt;line_width&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;

              &lt;span class="vi"&gt;@letters&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linux?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="n"&gt;letter_font&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;guess_button&lt;/span&gt;
        &lt;span class="vi"&gt;@guess_button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;layout_data&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
          &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'Guess'&lt;/span&gt;

          &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="n"&gt;do_guess&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_backspace&lt;/span&gt;
        &lt;span class="vi"&gt;@letter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;highlighted_letter_index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@letter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
          &lt;span class="n"&gt;index_to_delete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highlighted_letter_index&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="n"&gt;index_to_delete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;highlighted_letter_index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="vi"&gt;@letter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index_to_delete&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="vi"&gt;@letter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
        &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# refactor this reusable code into a method that highlights the caret&lt;/span&gt;
        &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index_to_delete&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:title_background&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_guess&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;word_filled_up?&lt;/span&gt;
        &lt;span class="n"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;invalid_word?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;message_box&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'Invalid Word'&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="s2"&gt;"The word you entered is not an allowed guess!&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;Please try another word!"&lt;/span&gt;
          &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="n"&gt;guess_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@five_letter_word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;guess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;update_guess_word_background_colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;update_alphabet_background_colors&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@five_letter_word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="ss"&gt;:in_progress&lt;/span&gt;
          &lt;span class="vi"&gt;@guess_button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispose&lt;/span&gt;
          &lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;word_guesser&lt;/span&gt;
            &lt;span class="n"&gt;guess_button&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;
          &lt;span class="vi"&gt;@guess_button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispose&lt;/span&gt;
          &lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="vi"&gt;@restart_button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;button&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="n"&gt;layout_data&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
              &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'Restart'&lt;/span&gt;
              &lt;span class="n"&gt;focus&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;

              &lt;span class="n"&gt;on_widget_selected&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
                &lt;span class="n"&gt;do_restart&lt;/span&gt;
              &lt;span class="k"&gt;end&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="n"&gt;display_share_text_dialog&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;highlighted_letter_index&lt;/span&gt;
        &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;border&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:title_background&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;swt_color&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;highlighted_letter_index&lt;/span&gt;
        &lt;span class="vi"&gt;@letter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="vi"&gt;@letter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# refactor this reusable code into a method that highlights the caret&lt;/span&gt;
          &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:title_background&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_left&lt;/span&gt;
        &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;highlighted_letter_index&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;
        &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# refactor this reusable code into a method that highlights the caret&lt;/span&gt;
        &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:title_background&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_right&lt;/span&gt;
        &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;highlighted_letter_index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;
        &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;caret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;# refactor this reusable code into a method that highlights the caret&lt;/span&gt;
        &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:title_background&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;do_restart&lt;/span&gt;
        &lt;span class="vi"&gt;@share_text_dialog&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
        &lt;span class="n"&gt;alphabet_layout_alphabets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;alphabet_character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="vi"&gt;@alphabet_borders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;
          &lt;span class="vi"&gt;@alphabet_rectangles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:white&lt;/span&gt;
          &lt;span class="vi"&gt;@alphabet_letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:black&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="vi"&gt;@restart_button&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispose&lt;/span&gt;
        &lt;span class="vi"&gt;@canvasses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:dispose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@canvasses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;
        &lt;span class="vi"&gt;@guess_button&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispose&lt;/span&gt;
        &lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;word_guesser&lt;/span&gt;
          &lt;span class="n"&gt;guess_button&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@five_letter_word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;refresh&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_guess_word_background_colors&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;guess_result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;guess_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;result_color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;background_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;COLOR_TO_BACKGROUND_COLOR_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;result_color&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="vi"&gt;@borders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;background_color&lt;/span&gt;
          &lt;span class="vi"&gt;@rectangles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;background_color&lt;/span&gt;
          &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;COLOR_TO_TEXT_COLOR_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;result_color&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="n"&gt;async_exec&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vi"&gt;@canvasses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;redraw&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_alphabet_background_colors&lt;/span&gt;
        &lt;span class="n"&gt;alphabet_layout_alphabets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each_with_index&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;alphabet_character&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;result_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@five_letter_word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;colored_alphabets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;alphabet_character&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;result_color&lt;/span&gt;
            &lt;span class="n"&gt;background_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;COLOR_TO_BACKGROUND_COLOR_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;result_color&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
            &lt;span class="vi"&gt;@alphabet_borders&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;background_color&lt;/span&gt;
            &lt;span class="vi"&gt;@alphabet_rectangles&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;background&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;background_color&lt;/span&gt;
            &lt;span class="vi"&gt;@alphabet_letters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;foreground&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;COLOR_TO_TEXT_COLOR_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;result_color&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;word_filled_up?&lt;/span&gt;
        &lt;span class="vi"&gt;@letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;letter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;invalid_word?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;FiveLetterWord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;WORLD_ALLOWED_GUESSES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;valid_character?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;122&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_a&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;character&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;display_share_text_dialog&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@five_letter_word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upcase&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;emoji_result&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

        &lt;span class="no"&gt;Clipboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="vi"&gt;@share_text_dialog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body_root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;grid_layout&lt;/span&gt;
          &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'Share Result'&lt;/span&gt;

          &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;layout_data&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="s1"&gt;'Result is copied to clipboard!'&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="n"&gt;styled_text&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;layout_data&lt;/span&gt; &lt;span class="ss"&gt;:fill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:fill&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;
            &lt;span class="n"&gt;editable&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
            &lt;span class="n"&gt;caret&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
            &lt;span class="n"&gt;alignment&lt;/span&gt; &lt;span class="ss"&gt;:center&lt;/span&gt;
            &lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Segoe UI Emoji'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt;
            &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="vi"&gt;@share_text_dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;alphabet_font&lt;/span&gt;
        &lt;span class="n"&gt;the_font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;style: :bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;28&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;the_font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Helvetica'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linux?&lt;/span&gt;
        &lt;span class="n"&gt;the_font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Arial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt; 
        &lt;span class="n"&gt;the_font&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;letter_font&lt;/span&gt;
        &lt;span class="n"&gt;the_font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="ss"&gt;style: :bold&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;the_font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Helvetica'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;linux?&lt;/span&gt;
        &lt;span class="n"&gt;the_font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="s1"&gt;'Arial'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;height: &lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;OS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;windows?&lt;/span&gt; 
        &lt;span class="n"&gt;the_font&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;dispose_alphabet_container_children&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_rectangles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_borders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_letters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:dispose&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rebuild_alphabet_container&lt;/span&gt;
        &lt;span class="n"&gt;dispose_alphabet_container_children&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;content&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;alphabets&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;layout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vi"&gt;@alphabet_container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;update_alphabet_background_colors&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;alphabet_layout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
         &lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
         &lt;span class="n"&gt;save_config&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_config&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="ss"&gt;alphabet_layout: &lt;/span&gt;&lt;span class="vi"&gt;@alphabet_layout&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save_config&lt;/span&gt;
        &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CONFIG_FILE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;YAML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_config&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
        &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;full_message&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;load_config&lt;/span&gt;
        &lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exist?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CONFIG_FILE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="no"&gt;YAML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;File&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;CONFIG_FILE&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
        &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;full_message&lt;/span&gt;
        &lt;span class="p"&gt;{}&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;

      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;emoji_result&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
        &lt;span class="vi"&gt;@five_letter_word&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;guess_results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;result_color&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
            &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;result_color&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:green&lt;/span&gt;
              &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"🟩"&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:yellow&lt;/span&gt;
              &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"🟨"&lt;/span&gt;
            &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="ss"&gt;:gray&lt;/span&gt;
              &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"⬜"&lt;/span&gt;
            &lt;span class="k"&gt;end&lt;/span&gt;
          &lt;span class="k"&gt;end&lt;/span&gt;
          &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: &lt;a href="https://github.com/AndyObtiva/glimmer_wordle" rel="noopener noreferrer"&gt;https://github.com/AndyObtiva/glimmer_wordle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;RubyGem: &lt;a href="https://rubygems.org/gems/glimmer_wordle" rel="noopener noreferrer"&gt;https://rubygems.org/gems/glimmer_wordle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blog Post Announcement: &lt;a href="https://andymaleh.blogspot.com/2023/10/glimmer-wordle-115.html" rel="noopener noreferrer"&gt;https://andymaleh.blogspot.com/2023/10/glimmer-wordle-115.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>gamedev</category>
      <category>glimmer</category>
      <category>gui</category>
    </item>
    <item>
      <title>Intro to Ruby in the Browser (Talk Video)</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 08 Sep 2023 00:46:17 +0000</pubDate>
      <link>https://dev.to/andyobtiva/intro-to-ruby-in-the-browser-talk-video-205g</link>
      <guid>https://dev.to/andyobtiva/intro-to-ruby-in-the-browser-talk-video-205g</guid>
      <description>&lt;p&gt;Matz mentioned in his RubyConf 2022 keynote speech that in the future of Ruby, maybe we could start replacing JavaScript with Ruby in the browser... &lt;/p&gt;

&lt;p&gt;YouTube Video:&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
      &lt;div class="c-embed__cover"&gt;
        &lt;a href="https://www.youtube.com/watch?si=hkHElMC-5sPHZ2Lz&amp;amp;v=4AdcfbI6A4c&amp;amp;feature=youtu.be" class="c-link s:max-w-50 align-middle" rel="noopener noreferrer"&gt;
          &lt;img alt="" src="https://res.cloudinary.com/practicaldev/image/fetch/s--nmC5w7Xh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.ytimg.com/vi/4AdcfbI6A4c/maxresdefault.jpg%3Fsqp%3D-oaymwEmCIAKENAF8quKqQMa8AEB-AH-CYAC0AWKAgwIABABGGUgZShlMA8%3D%26rs%3DAOn4CLBzRftdliiaMTC17OghZJmHbFaB1Q" height="450" class="m-0" width="800"&gt;
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;div class="c-embed__body"&gt;
      &lt;h2 class="fs-xl lh-tight"&gt;
        &lt;a href="https://www.youtube.com/watch?si=hkHElMC-5sPHZ2Lz&amp;amp;v=4AdcfbI6A4c&amp;amp;feature=youtu.be" rel="noopener noreferrer" class="c-link"&gt;
          Intro to Ruby in the Browser - YouTube
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;p class="truncate-at-3"&gt;
          Montreal.rb September, 2023 Talk - Intro to Ruby in the Browser - Andy Maleh, Senior Software Engineer, LexopMatz mentioned in his RubyConf 2022 keynote spee...
        &lt;/p&gt;
      &lt;div class="color-secondary fs-s flex items-center"&gt;
          &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://res.cloudinary.com/practicaldev/image/fetch/s--Wd2tTYlJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.youtube.com/s/desktop/fc8159e8/img/favicon.ico" width="16" height="16"&gt;
        youtube.com
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Blog Post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://andymaleh.blogspot.com/2023/09/montrealrb-sep-2023-intro-to-ruby-in.html"&gt;https://andymaleh.blogspot.com/2023/09/montrealrb-sep-2023-intro-to-ruby-in.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>web</category>
      <category>webassembly</category>
      <category>opal</category>
    </item>
    <item>
      <title>Every True Rubyist Builds Their Own Code Editor in Ruby!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Tue, 15 Aug 2023 01:45:23 +0000</pubDate>
      <link>https://dev.to/andyobtiva/every-true-rubyist-builds-their-own-code-editor-in-ruby-4420</link>
      <guid>https://dev.to/andyobtiva/every-true-rubyist-builds-their-own-code-editor-in-ruby-4420</guid>
      <description>&lt;p&gt;(originally posted on the &lt;a href="https://andymaleh.blogspot.com/"&gt;Code Master Blog&lt;/a&gt; at &lt;a href="https://andymaleh.blogspot.com/2023/08/every-true-rubyist-builds-their-own.html"&gt;https://andymaleh.blogspot.com/2023/08/every-true-rubyist-builds-their-own.html&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer-cs-gladiator"&gt;Gladiator&lt;/a&gt; (Glimmer Editor) 0.11.0 has just been released! It is my personal day-to-day code editor that I have built with &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-swt"&gt;Glimmer DSL for SWT&lt;/a&gt; in Ruby (using JRuby). It has syntax highlighting support for 40+ programming languages, split pane support with drag and drop, file look up support, directory tree navigation support, and many smart editing keyboard shortcuts. I use it for professional Ruby on Rails software engineering too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4lG3MfNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/AndyObtiva/glimmer-cs-gladiator/raw/master/images/glimmer-gladiator.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4lG3MfNG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://github.com/AndyObtiva/glimmer-cs-gladiator/raw/master/images/glimmer-gladiator.png" alt="gladiator1" width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That said, I am no code editor building expert, so Gladiator looks ugly! But, I love it because I built it 100% myself. Every self respecting Senior Software Engineer out there should build their own code editor, even if just as a toy app to later be discarded in favor of another code editor (though they might grow to prefer their own). And, if they are Rubyists, they should build their code editor in Ruby (whether using MRI Ruby, JRuby or Opal Ruby). If you think of yourself as a Ruby Senior Software Engineer, but cannot build your own code editor in Ruby, there are serious holes in your skillset!! Explore &lt;a href="https://github.com/AndyObtiva/glimmer"&gt;Glimmer&lt;/a&gt; libraries for many Ruby options to help you start the code editor building challenge and journey, whether using the &lt;a href="https://andymaleh.blogspot.com/2022/02/glimmer-dsl-for-libui-wins-fukuoka-ruby.html"&gt;Fukuoka Ruby 2022 Award&lt;/a&gt; Winning &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui"&gt;Glimmer DSL for LibUI&lt;/a&gt;, the 100% feature-complete JRuby-based Glimmer DSL for SWT, the brand new Glimmer DSL for WX, the Linux-focused Glimmer DSL for GTK, Glimmer DSL for Tcl/Tk, Glimmer DSL for FXRuby, Glimmer DSL for Swing, Glimmer DSL for JavaFX, or Glimmer DSL for Opal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gvDN4Pjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-dsl-swt-demo-hello-world.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gvDN4Pjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-dsl-swt-demo-hello-world.gif" alt="gladiator2" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nowadays, I see many Software Engineers on the Internet and social media who claim to be "Rubyists", but use non-Ruby code editors and non-Ruby frontend technologies, and that comes across as part hypocrisy and part lost opportunity!! After all, if they truly believed in Ruby, they would be building more things in it. Computer processors are so fast nowadays that many of Ruby's performance trade-offs are negligible in practice, except in some niche programming specialties like numerical computing, realtime systems, low-level programming, and performance-intensive game development. But sadly, in the last decade, many fake "Rubyists" entered the Ruby community just to associate with the "cool" factor of Ruby or to obtain Ruby job salaries without truly believing in Ruby 100% or even fully understanding the Ruby way of doing things. &lt;/p&gt;

&lt;p&gt;Thankfully, there are many litmus tests out there that reveal true Rubyists from fake "Rubyists", and one of them is whether a Ruby Software Engineer has built their own code editor in Ruby or not, or if they at least use a Ruby-based code editor like Redcar, Arcadia, or Gladiator, among others. Personally, I do not just write Ruby code in a web backend using Rails. I also write all my desktop applications in Ruby using Glimmer, including my code editor Gladiator, and I try to even build web frontend in Ruby using Opal Ruby.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--epqqHsLN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer-cs-gladiator/raw/master/images/glimmer-gladiator.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--epqqHsLN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer-cs-gladiator/raw/master/images/glimmer-gladiator.gif" alt="gladiator3" width="640" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just think of how great it would be if the Ruby community had a feature-rich Ruby-scriptable code editor / IDE that makes it possible to build plug-ins with highly maintainable and productive Ruby code. It does not have to support every programming language out there. It can just be a Ruby community niche thing. With such a Ruby-based code editor, Rubyists would be practicing what they preach regarding the productivity/maintainability of Ruby programming by using Ruby to build the very tools they use in day-to-day Ruby software engineering.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>codeeditor</category>
      <category>programming</category>
      <category>desktop</category>
    </item>
    <item>
      <title>If You Liked Shoes, You'll Love Glimmer!</title>
      <dc:creator>Andy Maleh</dc:creator>
      <pubDate>Fri, 23 Jun 2023 02:43:39 +0000</pubDate>
      <link>https://dev.to/andyobtiva/if-you-liked-shoes-youll-love-glimmer-1642</link>
      <guid>https://dev.to/andyobtiva/if-you-liked-shoes-youll-love-glimmer-1642</guid>
      <description>&lt;p&gt;A new &lt;a href="https://github.com/AndyObtiva/glimmer#faq"&gt;Glimmer FAQ (Frequently Asked Questions) section&lt;/a&gt; has been added to the &lt;a href="https://github.com/AndyObtiva/glimmer"&gt;Glimmer project README on GitHub&lt;/a&gt; in order to answer questions like "How do Glimmer GUI DSLs compare to Shoes?" and "What is the difference between Glimmer and Glimmer DSL for SWT?", among others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gvDN4Pjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-dsl-swt-demo-hello-world.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gvDN4Pjg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-dsl-swt-demo-hello-world.gif" alt="glimmer demo" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am including the Glimmer FAQ below for your convenience. If you have other questions that are not answered in the Glimmer FAQ, please ask your questions in a comment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do Glimmer GUI DSLs compare to Shoes?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you liked Shoes, you'll love Glimmer!&lt;/p&gt;

&lt;p&gt;That is because [Glimmer]((&lt;a href="https://github.com/AndyObtiva/glimmer"&gt;https://github.com/AndyObtiva/glimmer&lt;/a&gt;) does everything that Shoes did, but with a lighter and better GUI DSL (Graphical User Interface Domain Specific Language) that addresses all the issues that Shoes suffered from, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shoes does not allow code in Shoes blocks to use variables defined outside of Shoes blocks in a straightforward manner as it changes &lt;code&gt;self&lt;/code&gt; inside Shoes blocks, breaking Ruby expectations and producing confusing behavior. On the other hand, Glimmer DSL blocks are 100% standard Ruby blocks that represent real closures, so they enable usage of variables defined outside the blocks in a 100% standard Ruby way.&lt;/li&gt;
&lt;li&gt;Shoes lacks support for high-quality business widget controls (View components) like table and tree. Glimmer GUI DSLs that are feature complete like [Glimmer DSL for SWT]((&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-swt"&gt;https://github.com/AndyObtiva/glimmer-dsl-swt&lt;/a&gt;) do support table and tree widgets. Some non-final Glimmer GUI DSLs like Glimmer DSL for LibUI support the table control too.&lt;/li&gt;
&lt;li&gt;Shoes does not encourage proper separation of concerns with a correct MVC architecture (Model-View-Controller), resulting in a lot of non-presentation logic mixed with View code. Glimmer GUI DSLs do support proper separation of concerns 100% following the MVC or MVP (Model-View-Presenter) architecture by default.&lt;/li&gt;
&lt;li&gt;Shoes does not provide a simple way for connecting View components to Model data. Glimmer GUI DSLs provide full bidirectional/unidirectional data-binding support out of the box that provides the terest code syntax for connecting Views to Models and keeping them in sync.&lt;/li&gt;
&lt;li&gt;Shoes does not support a native mechanism for building custom View components. Glimmer GUI DSLs do support the ability to build custom widgets (aka controls or View components), custom windows (aka shells), and custom shapes (canvas graphics), enabling software engineers to expand a Glimmer DSL’s vocabulary with new keywords representing brand new visual concepts. That results in much higher productivity by enabling the reuse of higher visual concepts as their own self-encapsulated components.&lt;/li&gt;
&lt;li&gt;Shoes does not expose native features of its wrapped GUI toolkit. Glimmer GUI DSLs do expose all native features of their wrapped GUI toolkits, thus enabling developers to use a GUI toolkit like SWT directly when needed on top of using &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-swt"&gt;Glimmer DSL for SWT&lt;/a&gt; (a widget initialized via SWT directly could be passed to Glimmer DSL for SWT to wrap as a Glimmer &lt;code&gt;WidgetProxy&lt;/code&gt; object and integrate with other Glimmer initialized &lt;code&gt;WidgetProxy&lt;/code&gt; objects). That facilitates the 80/20 rule of having Glimmer GUI DSLs automate 80% of the work while still enabling software engineers to reach down to the low-level GUI toolkit API in 20% of the cases when needed (though in practice, it's probably more like 1% of the cases).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is great that Shoes paved the way for creating desktop GUI DSLs in Ruby. Glimmer took that approach to its maximum and produced the ultimate evolution of Shoes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between Glimmer and Glimmer DSL for SWT?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-swt"&gt;Glimmer DSL for SWT&lt;/a&gt; was the first GUI DSL created as part of the &lt;a href="https://github.com/AndyObtiva/glimmer"&gt;Glimmer&lt;/a&gt; project to enable building desktop applications, and it was originally just called Glimmer. It relied on the Eclipse SWT library to render native GUI (Graphical User Interface) widget controls (View components) on every platform (Mac, Windows, and Linux). Eventually, the idea of a Glimmer DSL proved itself so successful and viable for building desktop apps with a fraction of the effort needed in other programming languages/technologies that it was expanded to support other GUI toolkits. So, Glimmer got renamed to Glimmer DSL for SWT, and the core Glimmer DSL engine got extracted to Glimmer (becoming a DSL framework), which then got reused to build other Glimmer GUI DSLs such as Glimmer DSL for LibUI and Glimmer DSL for GTK, among many others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between Glimmer DSL for SWT and Glimmer DSL for LibUI?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-swt"&gt;Glimmer DSL for SWT&lt;/a&gt; and &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui"&gt;Glimmer DSL for LibUI&lt;/a&gt; support rendering platform native widgets/controls, which enable building native desktop apps that look 100% native on every platform (Mac, Windows, and Linux). &lt;/p&gt;

&lt;p&gt;However, Glimmer DSL for SWT runs in JRuby (Ruby running in the JVM [Java Virtual Machine]) whereas Glimmer DSL for LibUI runs in standard Ruby (aka MRI Ruby or CRuby).&lt;/p&gt;

&lt;p&gt;Glimmer DSL for SWT is 100% feature-complete and has a final release. Glimmer DSL for LibUI is 100% complete as far as covering the LibUI features, but LibUI itself is still a mid-alpha library, so it is missing a few features that will get added eventually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between Glimmer DSL for LibUI, Glimmer DSL for GTK, Glimmer DSL for Tk, Glimmer DSL for FX, and Glimmer DSL for WX?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All of &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui"&gt;Glimmer DSL for LibUI&lt;/a&gt;, &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-gtk"&gt;Glimmer DSL for GTK&lt;/a&gt;, &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-tk"&gt;Glimmer DSL for Tk&lt;/a&gt;, &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-fx"&gt;Glimmer DSL for FX&lt;/a&gt;, and &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-wx"&gt;Glimmer DSL for WX&lt;/a&gt; run in standard Ruby (aka MRI Ruby or CRuby).&lt;/p&gt;

&lt;p&gt;However, only &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-libui"&gt;Glimmer DSL for LibUI&lt;/a&gt; and &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-wx"&gt;Glimmer DSL for WX&lt;/a&gt; render native controls on every platform. The other libraries do not render native controls on every platform, albeit Glimmer DSL for GTK renders native controls on Linux distributions utilizing Gnome.&lt;/p&gt;

&lt;p&gt;Also, Glimmer DSL for LibUI does not require any prerequisites beyond installing the Ruby gem, so you can install it and get instant GUI with very little effort, whereas Glimmer DSL for GTK, Glimmer DSL for Tk, Glimmer DSL for FX, and Glimmer DSL for WX do require extra dependencies in general, albeit Glimmer DSL for GTK has everything it needs in Linux Gnome flavors and both Glimmer DSL for FX and Glimmer DSL for WX have everything they need on Windows by including pre-built binaries.&lt;/p&gt;

&lt;p&gt;You may learn more about the differences between various Glimmer DSLs by checking out the &lt;a href="https://github.com/AndyObtiva/glimmer#glimmer-dsl-comparison-table"&gt;Glimmer DSL Comparison Table&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is the difference between Glimmer DSL for SWT, Glimmer DSL for Swing, and Glimmer DSL for JFX?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-swt"&gt;Glimmer DSL for SWT&lt;/a&gt; relies on the Eclipse SWT library, which renders native widgets on every platform (Mac, Windows, and Linux) to build desktop apps that look 100% native on every platform (Mac, Windows, and Linux). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer-dsl-swing"&gt;Glimmer DSL for Swing&lt;/a&gt; relies on Swing, which does not render native widgets on every platform. &lt;a href="https://github.com/AndyObtiva/glimmer-dsl-jfx"&gt;Glimmer DSL for JFX&lt;/a&gt; relies on JavaFX, which also does not render native widgets on every platform.&lt;/p&gt;

&lt;p&gt;Also, SWT ensures initializing native widgets in memory using non-Java code (e.g. C/C++), thus ensuring native OS high performance for rendering native widgets without being prone to Java garbage collection pauses. On the other hand, Swing and JavaFX initialize non-native widgets in memory using Java code, thus depend on the performance of the Java Virtual Machine while being prone to Java garbage collection pauses. As a result, SWT ensures a better user experience than Swing and JavaFX.&lt;/p&gt;

&lt;p&gt;You may learn more about the differences between various Glimmer DSLs by checking out the &lt;a href="https://github.com/AndyObtiva/glimmer#glimmer-dsl-comparison-table"&gt;Glimmer DSL Comparison Table&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not just use SWT, LibUI, GTK, Tk, FOX Toolkit, wxWidgets, Swing, or JavaFX from Ruby directly?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GUI Toolkits implement low-level GUI rendering concerns. And, while some of them do offer object-oriented APIs, their APIs are very verbose and imperative by design due to being low-level APIs. As such, they require software engineers to write a lot more low-level code that does not map intuitively to the structure of the GUI visually, slowing down productivity and making maintainability more expensive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/AndyObtiva/glimmer"&gt;Glimmer&lt;/a&gt; GUI DSLs on the other hand are fully declarative and follow Rails' Convention Over Configuration maxim by including smart defaults and automation of low-level details, so they enable software engineers to write the simplest most minimalistic code that maps to the actual visual GUI concepts, maximizing productivity and resulting in code that is very maintainable and intuitive to reason about.&lt;/p&gt;

&lt;p&gt;Furthermore, Glimmer GUI DSLs offer advanced Bidirectional/Unidirectional Data-Binding Support, which enables syncing View data with Model attributes with the tersest code syntax possible to greatly simplify reasoning about the code while supporting proper separation of concerns through correct adherence to MVC (Model-View-Controller) and MVP (Model-View-Presenter). &lt;/p&gt;

&lt;p&gt;That's in addition to scaffolding and native executable packaging in some Glimmer GUI DSLs. As a result, productivity increases even further and maintainability becomes even less expensive, thus enabling software engineers to deliver pieces of software in a matter of minutes or hours for desktop application MVPs (Minimal Viable Products). As such, Glimmer GUI DSLs significantly shorten the feedback cycle and enable incrementally releasing features at a very fast pace, not possible with GUI toolkit low-level APIs.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;Check out the up-to-date &lt;a href="https://github.com/AndyObtiva/glimmer#faq"&gt;Glimmer FAQ on the GitHub page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Originally posted on the Code Master Blog:&lt;br&gt;
&lt;a href="https://andymaleh.blogspot.com/2023/06/if-you-liked-shoes-youll-love-glimmer.html"&gt;https://andymaleh.blogspot.com/2023/06/if-you-liked-shoes-youll-love-glimmer.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>desktop</category>
      <category>gui</category>
      <category>dsl</category>
    </item>
  </channel>
</rss>
