After trying (and failing) to wrap “executable” ducktape around a Python script using PyInstaller on Windows, The class of programming languages which now usually pique my interest have the following attributes:
- Static binary compilation. (producing a binary, not running bytecode i.e Java, Python)
- Cross Platform. (Windows, Mac, Linux, *BSD and/or Haiku (Bonus) )
Having picked up Go three years ago for this purpose, (started developing an app with it) I can guarantee that Go binaries work across multiple platforms through cross compilation. Other languages such as Crystal and Rust also tick the boxes above, but both were not stable at the time. Today, I’m exploring options for native cross platform GUIs1.
While Electron is easier, faster to market and cost effective for programmers, Electron is notorious for the sheer amount of bloat it carries in binary size and in RAM usage2. You may have come across posts lamenting the use of it, to the point that bashing Electron is almost guaranteed in an online tech forum if any application dares to use it.
To your disappointment, this is not one of these posts. Qt and GTK+ are interesting alternatives, I even plan to use them myself. However, both are not as quick to develop in as Electron is. Can we have both? A native cross platform GUI that is also faster to develop in? Enter Red.
Red was made largely because Rebol was proprietary, closed source software (That is until in 2012, Rebol 3 was made open source). Both languages have a great GUI system (which we will get into), the difference Red makes is that it can be used for systems programmming with a DSL called Red/System and the compiler is amazingly less than 2MB. You can find out more about Red here and you can download it here.
Here is a “Hello World” using Red’s GUI system.
Red comes with an interpreter, so you can go ahead and run the code below by typing
Red  view [ text "Hello World" ]
Red will interpret this code and run it without compiling it to a binary. If you want to produce a binary, amend the code to the following:
Red [ needs: 'View ] view [ text "Hello World" ]
red -r -c hello_world_gui.red
The result of this compilation is a single binary that shows the words “Hello World” in a GUI. GUI support is not currently available on Linux yet (it’s experimental), but compiling this works on Windows and Mac. Red supports cross compilation so that you can compile binaries for a different platform, We can get a list of the available cross compilation targets that Red can compile to.
hako ~ red -h ... Cross-compilation targets: MSDOS : Windows, x86, console (+ GUI) applications Windows : Windows, x86, GUI applications WindowsXP : Windows, x86, GUI applications, no touch API Linux : GNU/Linux, x86 Linux-ARM : GNU/Linux, ARMv5, armel (soft-float) RPi : GNU/Linux, ARMv5, armhf (hard-float) Darwin : macOS Intel, console or GUI applications macOS : macOS Intel, GUI-only, applications bundles Syllable : Syllable OS, x86 FreeBSD : FreeBSD, x86 Android : Android, ARMv5 Android-x86 : Android, x86
A “Hello World” isn’t that useful though, let’s go further with a simple image viewer where we get a random image, here is the code:
Red [ title: "Simple Image Viewer" author: "Wesley Hill" version: 0.1 needs: 'View ] rand_img: https://source.unsplash.com/random/310x200 message: "Press Random for a random image!" view/options [title "Simple Image Viewer" below center pictures: image 310x200 message across random_btn: button "Random" [ new_image: load rand_img pictures/image: new_image pictures/text: "" ] text "A Simple Image Viewer in Red" ]
The two variables
message are created above, and we use the
view function to invoke Red’s VID dialect and View Engine, we set our title and layout to being in the center of the window. Our images will be of size
310x200 using the
pair datatype and we set our button
text to be across from one another. Finally, once we click the “Random” button, we use the
load function to retrieve data from a source. The source needs to be a path, which can be a
In this case we are using the
url datatype from
rand_img and we set our image with
pictures/image: to our new image held in
new_image. We only want our image to be displayed, so we set the text in the image to be empty.
We can inspect the datatype with the
type? built-in function. Note that Red has over 50+ types.
>> print type? rand_img url >> print type? message string >>
Once we run the code above we get our simple image viewer!
…and it also works on Windows
Red can be used for more advanced applications, here are a few:
Automated Photo Copier
For a more advanced application using Red, I wrote a program for my Dad to deal with moving hundreds of photos. Below is the GUI of the program in action, I’m using a collection of random photos to demonstrate the program.
These demo photos are tiny (~5KB on average), and the photos my Dad works with are usually around ~14MB per photo in a sea of thousands of photos.
Parsing the data
The input data is actually an email containing a list of photos that the client has selected.
Selected the following images: BIRTHDAY PARTY > ABC 7453 TIF_FILE_ID: 0123456789 BIRTHDAY PARTY > ABC 7454 TIF_FILE_ID: 0123456790 ... BIRTHDAY PARTY > ABC 8217 TIF_FILE_ID: 0123456899
The filename of the selected photos takes the form of
ABC_1234.jpg. So it would make sense to use Regular Expressions for this problem. Instead, Red has it’s own pattern matching parser originally invented by Rebol called PARSE.
The following regular expression below…
…is similar to the following PARSE rule:
[some letter space 4 digit opt letter]
Given the following rules of
letter: charset [#"A" - #"Z"] digit: charset "0123456789"
The reason why
opt letter is included in the parse rule, is to catch the
ABC 1234A optional edgecase which sometimes appears in the email. Below is how the parser sees this rule:
Using the Red interpreter, we can test that the parse rule is working. For successful matches PARSE returns
>> parse "ABC 1234" [some letter space 4 digit] == true >> parse "ABC 1234A" [some letter space 4 digit opt letter] == true >> parse "ABC 1234AB" [some letter space 4 digit opt letter] == false
PARSE is a Rebol/Red specific alternative to the now universal regular expression syntax which most if not all experienced programmers are familiar with. It took me a while to learn the syntax and I appreciate the fact that the rules are in plain readable english unlike regex.
Writing this app took me a weekend after prototyping and testing it in Python, it is < 220 lines of code. My Dad uses a Mac, so generating a binary is as easy as compiling the source in release mode for macOS.
red -r -o "APC" -t macOS apc.red --red-only -v 4
and it’s not even 2MB and it. just. works.™
To demonstrate Red’s networking and serialisation capabilities, I re-created an app I had on my phone called Lines, which is a simple London tube status app. Unfortunately it’s not available on the App Store anymore, but I still have it on my old iPhone. The image on the right shows what it looks like.
Below is the same app implemented in Red. Clicking on the “Lines” will pop open information about a particular tube line.
Currently Red has no built-in JSON parser. I found a JSON parser floating around that was good enough for this demonstration. Building this app took around 3 days of free time to make and is around 897KB in size.
Apart from the GUI system which could do with a Linux implementation (A GTK3 backend is in the works for Red), be aware that Red currently compiles binaries in 32bit. With the Automated Photo Copier app I had problems when I was copying large photos using Red and often the program just crashed all of a sudden. I switched to using
cp to copy the photos (Since I knew that my Dad was only using a Mac) by calling
call/console to the
cp command. At that point it copies the images flawlessly. This would be a different story had he used Windows instead.
Is Red a good alternative to Electron? If you’re building a small internal tool that needs a quick GUI or need a cross platform GUI with less development headaches, then yes. It isn’t production ready yet, but Red has a lot of huge potential in the future looking at their roadmap. I have to admit the learning curve is slightly moderate if you are not familiar with Rebol (resources and links below). An alternative I have yet to try out is Lazarus (maybe in a future blogpost!), but the speed of developing GUI’s in Red is very promising.
The Lines clone code is open source on GitHub.
If you’re interested in learning more about Red, check out these links:
Rebol Documentation — (Recommended)
The Red Language Notebook — (Recommended)
RedProgramming.com — (Recommended)
Red Official Documentation — (Slightly incomplete)
I used the tried and tested ones, you know: Python, Ruby, Java, C/++/# and JS, but wanted to try something new. In terms of GUI’s for Go, shiny is experimental, there is therecipe/qt and my personal favorite, andlabs/ui. ↩
There exists some performant Electron apps (Visual Studio Code), but this is the exception and not the rule. ↩