Broken shortcuts on gnome with dvorak

Let’s say you’re one of the three people who uses the dvorak keyboard layout and Gnome on Linux. (I apparently have a weakness for, how shall I say it, esoteric choices. c.f., my Dylan-related posts.) You try to use the Keyboard Preferences control panel to setup your keyboard layout switcher and suddenly notice your terminal windows keep disappearing on you. WTF?

You do some fiddling and eventually discover that even though your keyboard is nominally in dvorak layout, the keyboard shortcuts are still using qwerty layout and Control-d was really sending Control-d instead of the expected Control-e. Although some people claim this makes sense, I can only assume this was a mistake and those people are on crack. (Okay, maybe not crack…maybe they just don’t touch type, but is it really that different?)

It turns out that there’s a relatively easy solution IF you have both the “USA” and “USA Dvorak” layouts listed in your “Selected layouts”. Make sure “USA Dvorak” is listed first and “USA” is listed second. You can do this by removing the “USA” layout and re-adding it.

Intuitive, right?

As an added bonus to this solution, the keyboard switcher widget in the task bar now calls the “USA” layout “USA2” and calls the “USA Dvorak” layout “USA”.

Happy dvoraking.

Serving Dynamic Content

This is the second in a series of articles about web programming in Dylan. This example will show how to dynamically generate the contents of a web page.

First, the ever-exciting library and module definitions. In addition to common-dylan and koala (the HTTP server) we need streams for writing data to the response and date so we can show something dynamic happening:

define library web60-dynamic-content
  use common-dylan;
  use io, import: { streams };
  use koala;
  use system, import: { date };
end;

define module web60-dynamic-content
  use common-dylan;
  use date, import: { as-iso8601-string, current-date };
  use koala;
  use streams, import: { write };
end;

A web page is a resource mapped to a URL inside the web server. To create a resource we subclass <resource>:

define class <clock-page> (<resource>) end;

To make our resource do something we define a method on respond. (If we only wanted to implement the GET request method we could define a method on respond-to-get instead.)

define method respond (page :: <clock-page>, #key)
  let stream = current-response();
  let date = as-iso8601-string(current-date());
  write(stream, concatenate("<html><body>", date, "</body></html>"));
end;

current-response() returns the active <response> object. To send data back to the client we write to the current response.

let server = make(<http-server>,
                  listeners: list("0.0.0.0:8888"));
add-resource(server, "/", make(<clock-page>));
start-server(server);

In the previous example we already saw how to create and start a server, so the new bit here is using add-resource to map a URL to a <resource>. The first argument to add-resource is the URL router. (In Routes terminology it would be a "mapper".) For convenience, an <http-server> is a kind of router so we can add resources directly to the server. In a future example, I will show how to do more complex URL routing, which will explain the reason for the mysterious #key in the respond definition above.

Here’s the complete code:

---- File: library.dylan ----
Module: dylan-user

define library web60-dynamic-content
  use common-dylan;
  use io, import: { streams };
  use koala;
  use system, import: { date };
end;

define module web60-dynamic-content
  use common-dylan;
  use date, import: { as-iso8601-string, current-date };
  use koala;
  use streams, import: { write };
end;

---- File: main.dylan ----
Module: web60-dynamic-content

define class <clock-page> (<resource>)
end;

define method respond (page :: <clock-page>, #key)
  let stream = current-response();
  let date = as-iso8601-string(current-date());
  write(stream, concatenate("<html><body>", date, "</body></html>"));
end;

let server = make(<http-server>,
                  listeners: list("0.0.0.0:8888"));
add-resource(server, "/", make(<clock-page>));
start-server(server);

Run this example and point your browser at http://127.0.0.1:8888/.

Previous: Serving Static Content

Back to top

Serving Static Content

This example will show you how to use the Dylan web server (koala) to
serve static content from the file-system. First I’ll go through the
process line by line and then will show the complete code.

First, we need an HTTP server. We’ll make it listen to all interfaces
on port 8888:

let server = make(<http-server>,
                  listeners: list("0.0.0.0:8888"));

Instances of <resource> are responsible for generating HTTP
responses. To serve static content we create a
<directory-resource> whose file-system directory is /tmp and which
allows directory listings:

let resource = make(<directory-resource>,
                    directory: "/tmp",    // c:\tmp on Windows
                    allow-directory-listing?: #t);

Next we connect the resource to a specific URL on the server:

add-resource(server, "/", resource);

Last, we start the server:

start-server(server);

If you wanted to start the server in a separate thread you could say
this instead:

start-server(server, background: #t);

The entire example, including the library and module definitions,
looks like this:

---- File: library.dylan ----
Module: dylan-user

define library web60-static-content
  use common-dylan;
  use koala;
end;

define module web60-static-content
  use common-dylan;
  use koala;
end;

---- File: main.dylan ----
Module: web60-static-content

define function main ()
  let server = make(<http-server>,
                    listeners: list("0.0.0.0:8888"));
  let resource = make(<directory-resource>,
                      directory: "c:/tmp",
                      allow-directory-listing?: #t);
  add-resource(server, "/", resource);
  start-server(server);
end;

main();

Run this example and point your browser at http://127.0.0.1:8888/.

Note that serving static content is one of the things built into koala itself, so if that’s all you need to do this will accomplish the same thing:

koala --listen 0.0.0.0:8888 --directory /tmp