Elm resizeable SVG canvas filling the screen

I am toying with writing an SVG-based game in (exciting-looking JavaScript-replacement) Elm, and I wanted an SVG that filled the whole screen and resized when the screen resized. I found it harder than I expected, so here is what I came up with for your information and comment.

Try the demo.

Because I was using Html.App.programWithFlags I was not able to shortcut the process and use just elm-reactor – I needed to create an HTML file and compile my code with elm-make.

index.html sets up a full-screen app and passes in the window size:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="UTF-8"/>
    <title>Sootl</title>
    <script src="sootl.js"></script>
    <style>
        html, body, svg
        {
            margin: 0px;
            padding: 0px;
            border: 0px;
            overflow: hidden;
        }
    </style>
</head>
<body>
</body>
<script>
var app = Elm.Main.fullscreen(
    {
        width:  window.innerWidth,
        height: window.innerHeight
    }
);
</script>
</html>

elm-package.json requires the Html, Svg and Window packages:

{
    "version": "1.0.0",
    "summary": "Stay out of the light!",
    "repository": "https://github.com/andybalaam/sootl.git",
    "license": "GPL2",
    "source-directories": [
        "."
    ],
    "exposed-modules": [],
    "dependencies": {
        "elm-lang/core": "4.0.5 <= v < 5.0.0",
        "elm-lang/html": "1.1.0 <= v < 2.0.0",
        "elm-lang/svg": "1.1.1 <= v < 2.0.0",
        "elm-lang/window": "1.0.0 <= v < 2.0.0"
    },
    "elm-version": "0.17.1 <= v < 0.18.0"
}

Main.elm contains the Elm code, which starts off with the window size from JavaScript, and then listens to resize events using the Window module.

import Html exposing (Html)
import Html.App exposing (programWithFlags)
import Svg exposing (..)
import Svg.Attributes exposing (..)
import Window


type alias Flags =
    { width : Int
    , height : Int
    }


type Msg = Resize Int Int


type alias Model =
    { screen :
        { width : Int
        , height : Int
        }
    }


init : Flags -> (Model, Cmd Msg)
init flags =
    (
        { screen =
            { width = flags.width
            , height = flags.height
            }
        }
    , Cmd.none
    )



view : Model -> Html Msg
view model =
    let
        sw = model.screen.width  - 0
        sh = model.screen.height - 0
    in
        svg
        [ width  <| toString sw
        , height <| toString sh
        ]
        [ rect
            [ x "0"
            , y "0"
            , width (toString model.screen.width)
            , height (toString model.screen.height)
            , fill "#eeffee"
            ]
            []
        , text'
            [ x <| toString <| sw / 2
            , y <| toString <| sh / 2
            , fontSize <| toString <| sh / 10
            , textAnchor "middle"
            ]
            [ text
                ((toString model.screen.width)
                ++ ", "
                ++ (toString model.screen.height))
            ]
        ]


update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
    let m =
        case msg of
            Resize w h -> {model | screen = {width = w, height = h}}
    in
        (m, Cmd.none)


subscriptions : Model -> Sub Msg
subscriptions model =
    Window.resizes (\size -> Resize size.width size.height)


main =
   programWithFlags
     { init = init
     , view = view
     , update = update
     , subscriptions = subscriptions
     }

I installed all the packages with:

elm-package install

Then I compiled the code with:

elm-make --output=sootl.js Main.elm

Now I launched elm-reactor:

elm-reactor

And navigated my browser to http://localhost:8000/index.html to see it working.

Ambiguous names in Java due to non-normalised unicode – but all OK in Python

In Java and several other languages, identifiers (e.g. method names) are allowed to contain unicode characters.

Unfortunately, some combinations of unicode characters are logically identical. For example, á (one character: Latin Small Letter a with Acute U+00E1) is the same as á (two characters: Latin Small Letter A U+0061, and Non-spacing Acute Accent U+0301). These combinations are not just similar – they are identical by definition.

Java does not do any normalisation on your code before compiling it, so two identifiers containing equivalent but different unicode combinations are considered different (ref: JLS 7 section 3.8).

$ cat U.java 
public class U {
    static String \u00e1() { return "A WITH ACUTE"; }
    static String a\u0301() { return "A + NON-SPACING ACUTE"; }
    public static void main(String[] a) {
        System.out.println(á());
        System.out.println(á());
    }
}
$ javac U.java && java U
A WITH ACUTE
A + NON-SPACING ACUTE

We can define and use two functions called á and á and they are totally independent entities.

But don’t do this.

Python 3 also allows unicode characters in identifiers, but it avoids the above problem by normalising them (ref: Python 3 Reference, section 2.3):

$ cat U.py 
#!/usr/bin/env python3

def á():
    print("A WITH ACUTE")

def á():
    print("A + NON-SPACING ACUTE")

á()
á()

$ hexdump -C U.py 
23 21 2f 75 73 72 2f 62  69 6e 2f 65 6e 76 20 70  |#!/usr/bin/env p|
79 74 68 6f 6e 33 0a 0a  64 65 66 20 c3 a1 28 29  |ython3..def ..()|
3a 0a 20 20 20 20 70 72  69 6e 74 28 22 41 20 57  |:.    print("A W|
49 54 48 20 41 43 55 54  45 22 29 0a 0a 64 65 66  |ITH ACUTE")..def|
20 61 cc 81 28 29 3a 0a  20 20 20 20 70 72 69 6e  | a..():.    prin|
74 28 22 41 20 2b 20 4e  4f 4e 2d 53 50 41 43 49  |t("A + NON-SPACI|
4e 47 20 41 43 55 54 45  22 29 0a 0a c3 a1 28 29  |NG ACUTE")....()|
0a 61 cc 81 28 29 0a 0a                           |.a..()..|
$ ./U.py 
A + NON-SPACING ACUTE
A + NON-SPACING ACUTE

(Legend: A WITH ACUTE, A + NON-SPACING ACUTE)

The second definition overwrites the first because they are considered identical. You can call it via either way of saying its name.

Both ways of working are scary, but I’d definitely choose the Python 3 way if I had to.

Gracefully shutting down Firefox, to avoid the crash/session dialog

I normally have several Firefox profiles open, and when I log out without closing the Firefox windows I get the “session restore” dialog on my next login.

This is because of Bug 336193 which says that Firefox should shut down gracefully when it receives a SIGTERM signal, which is what happens when I log out (in Ubuntu MATE anyway). At the moment, it shuts down ungracefully, meaning it is treated as if Firefox crashed when it restarts.

So, instead of my normal shutdown button, I have one that launches a script that closes all my Firefoxes first, like this:

#!/bin/bash

# Prerequisites:
# sudo apt-get install sysvinit-utils xdotool

set -x
set -u

function close_firefoxes()
{
    local PID
    local WID

    PID=$(pidof -s firefox)
    FOUND=$?

    while [ $FOUND ]; do
    {
        WID=$(xdotool search --pid "$PID" | tail -1)
        xdotool windowactivate --sync "$WID"
        xdotool key --clearmodifiers 'ctrl+q'
        sleep 1
        PID=$(pidof firefox)
        FOUND=$?
    }; done
}

close_firefoxes

mate-session-save --shutdown-dialog

Snake in Python 3 + Qt 5

Series: Groovy, Ruby, BASIC, Dart, Elm, Python3+Qt5

I’m writing the game Snake in lots of programming languages, for fun, and to try out new languages.

Python 3 broke compatibility to fix some mistakes – was it worth it? Qt 5 continues to offer more and more features – can it win me over?

Slides: Snake in Python 3 + Qt 5

If you want to, you can Support me on Patreon.