ghoetker

ghoetker

Zenity as a simple GUI

There has been a lot of discussion about GUIs and it will be incredibly cool to have Boyd Multerer’s Scenic framwork when he releases it. In the interim (or perhaps for simpler tasks), I’ve discovered that Zenity is actually not half bad to use. Not pretty, but functional. Although originally for Linux, a Mac version available from MacPorts. Not having found any mention of it by searching for Forums, I wanted to share in case anyone else might find it useful.

By “discovered”, I mean that I found Andrei Clinciu’s great post at https://andreiclinciu.net/zenity-gui-for-elixir/ and the links therein. Just to give a flavor, here is an example that takes a list of keywords, ensures they are unique and in alphabetic order, presents the list to the user as a check list and then returns the checked words as a list.

My example is more brute force that Andrei’s because some of the arguments to be sent required quotes and I was having a terrible time getting that to work (I am very much a beginner at Elixir and not primarily a developer.)

The desired command to be sent is as follows:

/opt/local/bin/zenity --list --checklist --column "Delete?" --column "Keywords" --separator=":" "FALSE" "Cat" "FALSE" "Furry dog" "FALSE" "Horse" 2>/dev/null

which I built programmatically and then just passed to Port.open as a blob. Zenity sometimes emits an irritating GTK+ warning, which I’d chosen to sent to /dev/null for simplicity. Obviously, in real use, kw_input would come from some external source.

Even I can tell that the structure of this example is horrid, but I hope it illustrates the Zenity-specific aspects adequately. Sometimes it’s nice to just be able to kludge a shell command together for what you need.

Would love to hear of other alternatives, especially for low-complexity use cases like this.

Glenn

defmodule Zenity do
  @zenity "/opt/local/bin/zenity"

  def do_it do
    kw_input = ["Cat", "Furry Dog", "Cat", "Horse"]

    kw_for_cmd =
      kw_input
      |> MapSet.new()
      |> Enum.sort()
      |> Enum.flat_map(fn x -> [~s("FALSE"), ~s("#{x}")] end)
      |> Enum.join(" ")

    cmds =
      ~s(#{@zenity} --list --checklist --column "Delete?" --column "Keywords" --separator=":" #{kw_for_cmd} 2>/dev/null)

    exec(cmds)
  end

  defp exec(cmd) do
    port = Port.open({:spawn, cmd}, [:stream, :binary, :exit_status, :hide, :use_stdio])

    port
    |> handle_output
    |> listify
  end

  defp handle_output(port, data \\ "") do
    receive do
      {^port, {:data, data}} ->
        handle_output(port, data)

      {^port, {:exit_status, status}} ->
        {data, status}
    end
  end

  defp listify({_, 1}) do
    IO.puts("Operation cancelled")
  end

  defp listify({"", 0}) do
    IO.puts("Nothing selected")
  end

  defp listify({kw_list, 0}) do
    kw_list
    |> String.trim_trailing("\n")
    |> String.split(":")
  end

end

Zenity.do_it

Most Liked

Andrei

Andrei

Hi there.
I’m glad you’re using Zenity together with Elixir.
That blog post attracted a lot more visitors than I had anticipated which is great.

Zenity is cool for fast prototyping, the sad part is that it’s development has stopped.

I recommend newcomers to try yad out (https://sourceforge.net/projects/yad-dialog/), it’s a Zenity fork.

It provides more flexibility and way more options than Zenity ever did.

Good luck in developing!

Where Next?

Popular in Questions Top

pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
New
logicmason
Hi there, I'm working through my first release with elixir/phoenix. I've built a release with distillery and found that it crashes when I...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod -- where is this set? Thanks.
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
sacepums
Hey guys. I'm new to elixir and im really stocked about it. But I ran into a bit of problem - I need to convert a date sting, for examp...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

Other popular topics Top

Qqwy
Update: How to use the Blogs & Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
lk-geimfari
What is most correct way to open, read and parse JSON file with poison? For example if we have example.json file in root of some projec...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
belgoros
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

We're in Beta

About us Mission Statement