Chinese Translation by oschina.net
Uzbek Translation by vectorified.com
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)
- Fast.
- 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.
There have been lots of “modern desktop applications” being built with Electron. This allows programmers to build desktop applications with HTML, CSS and JavaScript. Sounds awesome right? Well…
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
“Red is a next-generation programming language strongly inspired by Rebol.”
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.
GUI
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 hello_world_gui.red
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" ]
and run:
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 rand_img
and 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 random_btn
and 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 file
, string
, binary
or url
datatype.
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…
[A-Z]{3,}\s\d\S{3,}
…is similar to the following PARSE rule:
[some letter space 4 digit opt letter]
Given the following rules of letter
and digit
:
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 true
and false
otherwise.
>> 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.™
Lines Clone
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.
Closing Thoughts
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:
Helpin’Red — (Recommended)
Rebol Documentation — (Recommended)
The Red Language Notebook — (Recommended)
Red Official Documentation — (Slightly incomplete)
Red guides and community material
-
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. ↩