Sunday, 13 May 2012

Automatically undecorate maximised windows in GNOME Shell

One feature I really liked about the Ubuntu Netbook Remix (while it lasted) was how whenever you maximised a window, it removed the title bar. The program that did this was called Maximus.

This was really handy for saving a bit of vertical screen real estate, especially when you had a small 10" screen. Yes, it became harder to unmaximise a window/drag it around/resize it, but on a 10" screen you don't do that often anyway as it's really not big enough to bother with having multiple windows visible at once.

Anyhow, I wanted this ability in GNOME shell (undecorate maximised windows), so I wrote an extension to do this.

Maximus GNOME shell extension undecorates maximised windows Without Maximus: title bar consumes vertical space.

Before I give the link, I'll mention that you don't actually need an extension to get this behaviour; this blog post gives two ways to do it:

  1. Install Maximus: if you're lucky or have Ubuntu, you can just sudo apt-get install maximus. This will install the original Maximus program for you and then you're done. However if you have Fedora, Maximus is not in the package repositories. In that case you could try to download the source and build/install it yourself. This isn't as easy as simply installing a program or extension though.
  2. Edit your window theme: you can edit the theme GNOME-shell uses to decorate your windows to artificially remove the title bar from maximised windows. See Method 2 in this blog post for how. This is nice and easy, but you have to do it every time you change your window theme.

I'd recommend installing Maximus from your package manager if you have it (i.e. Ubuntu). Otherwise, edit your window theme (knowing that it could get written over every time you change your theme), or try my Maximus GNOME shell extension (from extensions.gnome.org).

The Maximus GNOME shell extension is just an extension that emulates the behaviour of the original Maximus program. All it does is undecorate windows that are maximised.

The homepage/repository/instructions are here. For a one-click install just visit extensions.gnome.org (or you can also download the zip file and use gnome-tweak-tool to install it ('Shell Extensions' > 'Install Extension' > select .zip file). Make sure you additionally enable it.)

Enjoy & let me know of any bugs :)


For developers: How it's done

For those who are interested, this is how I managed to get the windows undecorated.

Recall that in GNOME-shell, window objects are Meta.Windows (using the Mutter = Metacity + Clutter bindings). There are four ways I tried to undecorate/redecorate a window:

  • use the Mutter interface: try modifying the window.decorated property of a Meta.Window.
  • use the Gtk interface: try using window.set_hide_titlebar_when_maximised() or window.set_decorated(). on a Gtk.Window.
  • use the Gdk interface: try using window.set_decorations() on a Gdk.Window.
  • make an external call to xprop to set the window manager hints saying to undecorate the window.

Mutter: window.decorated = false

It would be ideal to undecorate using the Mutter bindings as GNOME-shell treats all windows as Meta.Windows anyway.

There is a window.decorated property for Meta.Windows but it's treated as read-only (as of GNOME 3.4.1); setting it to true or false has no effect. There is no way to set the window's decorations from the current (GNOME 3.4.1) Mutter gobject introspection. Not surprising; the Mutter API can't do much at the moment.

Gtk: window.set_hide_titlebar_when_maximised

Now assume that we could convert a Meta.Window into a Gtk.Window. Then we'd be able to use the function gtk_window_set_hide_titlebar_when_maximised() to get the behaviour we wanted, or if that didn't work, gtk_window_set_decorated().

However I couldn't find a way to make a GTK window from a Meta.Window, and in fact I'm not sure if it's possible/GTK works like that.

Gdk: window.set_decorations

Well, why not assume we could convert a Meta.Window into a Gdk.Window. Then we could use the function gdk_window_set_decorations(0) to remove decorations from a window.

How to create a Gdk.Window from a Meta.Window from the gobject introspection bindings? The best I could find was a function gdk_x11_window_foreign_new_for_display, which will create a Gdk.Window given the window's X ID. In the GNOME javascript bindings:

const Gdk = imports.gi.Gdk;
const GdkX11 = imports.gi.GdkX11;

let window = GdkX11.X11Window.foreign_new_for_display( Gdk.Display.get_default(), WINDOW_XID );
// remove decorations
window.set_decorations(0);
// add back decorations
window.set_decorations(Gdk.WMDecoration.ALL);

Assuming you can find the window's X ID (for example with xwininfo), this works!

However, this is another unfortunate caveat; when you call this code from within the GNOME-shell process (i.e. from a GNOME shell extension), the window gets killed! If you run the exact same code using the gjs binary, or you write the exact same code in Python with the Python bindings, it works!.

After a bit of asking around, it turns out that using the above code simply won't work as long as it's run directly from a gnome shell extension; I have to make sure that the code that undecorates the window happens from an external process. This means making an external call (for example, gjs undecorate_window.js) from my code.

Then I'll need to somehow pass the window's X ID into the script from the extension to make sure it undecorates the right window.

So yes, this option is viable, but given that I have to make an external call anyway I'd rather not have to load up the various libraries in the external script each time a window is maximised.

xprop

xprop is a command-line utility for examining/setting the X properties of a window.

Looking through the set_decorations code in GDK and the C source for Maximus, to undecorate a window one sets the _MOTIF_WM_HINTS property on the window. In the hints one specifies that the window should be undecorated. When the window manager looks at these hints it then attempts to undecorate the window according to the hints.

Translating this into using xprop to set the hints, one uses the following command (credit to this post that got me started):

xprop -id [window_XID] -f _MOTIF_WM_HINTS 32c -set _MOTIF_WM_HINTS "0x2, 0x0, 0x0, 0x0, 0x0"

To explain:

  • -id [window_XID]: this tells xprop which window we wish to modify the hints of.
  • -f _MOTIF_WM_HINTS 32c: this specifies the format of the _MOTIF_WM_HINTS property, each field being a 32bit unsigned integer.
  • -set _MOTIF_WM_HINTS 0x2, 0x0, 0x0, 0x0, 0x0: says we wish to set the value of _MOTIF_WM_HINTS to 0x2, 0x0, 0x0, 0x0, 0x0.

A quick explanation of what all the numbers in _MOTIF_WM_HINTS mean (see MwmUtil.h from the OpenMotif source for the documentation, or there is some rudimentary online documentation here).

The hints structure has 5 fields, and (in order) they are:

  • what fields we're specifying with the hints: the window functions, decorations, input mode and/or status.
  • the hints for the window functions. That is, which buttons to display on the window's title bar: maximise, minimise, close, ...
  • the decorations to be drawn on the window: title bar, border, all decorations, no decorations, ...
  • the input mode of the window: modeless (can't click on it), application modal, sytem modal, ...
  • the status of the window: whether it's a tearoff window or not.

So in the above, 0x2, 0x0, 0x0, 0x0, 0x0 says that:

  • we want to specify the decorations of the window (0x2); ignore all the other fields
  • we want there to be no decorations on the window (the third number is 0x0).

If we wanted to decorate the window we'd set the window hints to 0x2, 0x0, 0x1, 0x0, 0x0.

Summary

Out of all of the above, only xprop and the GDK version were viable. Since I have to make an external call to undecorate the window anyway, I'd rather have my external call be xprop -id ... than gjs undecorate_window.js because in the latter gjs has to load all the relevant modules to execute the code, whereas the former is a simple command-line call that does the undecorating directly.

So the only question left is how to get the X ID of a window in order to pass it in to xprop (we'd have the same problem with Gdk too).

Getting the X ID of a window

There is currently (GNOME 3.4.1) no official way to get the X ID from a Meta.Window. If I listen to maximise events, I get a Meta.Window specifying the window that was maximised. There is no method in the API to extract this window's X ID. (aaargh!)

So how can I find the Meta.Window's X ID? I could try convert it into a Wnck window which has a get_xid method, but there's no way to do this directly other than looping through a list of Wnck windows and (say) comparing titles to determine whether the Wnck window is the same as the Meta.Window. This is prone to error - what happens when you have multiple windows with the same title? How will you work out which Wnck window is your window?

After a bit of digging around in the source of Mutter, I found two (somewhat hacky) ways to grab a Meta.Window's X ID.

Method 1: Using the window's description

It turns out that the window.get_description() of a Meta.Window consists of its X ID followed by its name (truncated to 10 characters) in brackets. For example, 0x26005b (Google Chr).

So, method 1 is to extract the X ID from the description of the window. However, it isn't guaranteed that the window's description will have the X ID in it in future releases of GNOME/Mutter; it's just lucky that in 3.2 to 3.4 this is what the description is set to.

Method 2: Using the window frame's X ID

If one has the actor for a Meta.Window, then the property actor['x-window'] is the X ID of the window's frame.

By the frame of the window, I mean that every window has a frame created for it by the window manager, actor['x-window'] is the X ID for that frame.

However, to perform undecoration/decoration of windows, one must use the X ID for the client window, being the window that the frame contains.

The client window is actually the child of the frame window. By using xwininfo -children -id [frame_XID] we can get a list of all the X IDs for the frame window's children, namely the one client window.

So method 2 is to make an external call to xwininfo and parse the output the extract the child's X ID. Again, it is not guaranteed that actor['x-window'] will still be there in future releases of GNOME.

Failing that

If the above two methods fail to locate a window's X ID we can use its title as a last resort. This is because xprop -id [window's XID] can be replaced with xprop -name [window's title] to identify the window in question. However if you have multiple windows of the same title, you aren't guaranteed that xprop will identify the particular window you're after.

Putting it all together.

Putting it all together, this is what happens:

  1. Create a function onMaximise that fires whenever a window is maximised. One of its arguments is the window (that was maximised)'s actor.
  2. Get the window's X ID, first by trying to parse the window's description and failing that by calling xwininfo on actor['x-window'] to get the child's X ID.
  3. If we found the X ID, then call xprop -id [XI D] -f _MOTIF_WM_HINTS 32c -set _MOTIF_WM_HINTS "0x2, 0x0, 0x0, 0x0, 0x0". If we didn't, then call xprop -name [window.get_title()] ....

If you find a less cludgy way to do this (i.e. doing the external system call) please let me know!

Wednesday, 2 May 2012

Adding window options to title bar in GNOME 3.2, 3.4

In GNOME you can usually right-click on the title bar of an application's window to select Minimize, Maximize, Always on Top, Always on Visible Workspace, etc.

If you use Google Chrome and are not using the system title bar and borders (the default), you'll notice it's not possible to access this menu.

Window Options GNOME Shell Extension in action

I've written a small GNOME Shell Extension that adds this drop-down list to the GNOME Shell title bar that gets drawn for the current window. See it in action in the picture.

It's called Window Options and is available for installation from extensions.gnome.org.

To install it, visit extensions.gnome.org - one-click install.

Otherwise, download the .zip file on the Downloads page. Open gnome-tweak-tool, go to "Shell Extensions", "Install Extension" and select the .zip file.

This extension also works with the Status Title Bar extension (which shows the full window title in the top instead of just the current application's name). However, you have to make sure that Window Options is loaded after Status Title Bar, or else Status Title Bar will write over the menu.(UPDATE: It now works with Status Title Bar regardless of install order.)

To do this, just make sure that if you're using Status Title Bar, you install it before Window Options. If it's too late and you installed Window Options first, you can either uninstall and reinstall Window Options, OR just toggle Window Options on and off a couple of times (from gnome-tweak-tool) when you log in. This will cause Window Options to put its menu items in Status Title Bar's menu instead of the default panel one (that Status Title Bar removes).

You can configure which items are shown in the menu; to see how, see the Readme on Window Options' homepage (just scroll down a bit).

Thursday, 12 April 2012

Reduce horizontal spacing between icons in GNOME 3.2

One thing that annoys me about the default GNOME shell is the amount of horizontal space it wastes in between icons/indicators in the status area (top right on the panel).

Urgh look how much space is between all the icons!

I wrote a very simple GNOME shell extension to fix this. (My first ever! More an exercise in how to do it than anything else).

It's available for one-click install from extensions.gnome.org. The repository (for anyone interested in the code) is here.

If for some reason you don't want to/can't install from extensions.gnome.org, you can go to the 'Downloads' page and download the .zip file. Then start gnome-tweak-tool, select "Shell Extensions", "Install Shell Extensions", and choose the .zip file. Restart the gnome-shell, enable the extension, and you're all done!

The result?

Nice and slim

Voila! Enjoy :)

What it Does

It basically just modifies these lines from the file /usr/share/gnome-shell/theme/gnome-shell.css:

.panel-button {
    -natural-hpadding: 12px;
    -minimum-hpadding: 6px;
    /* ... and so on */
}

The attribute -natural-hpadding is set by default to 12 pixels wide. My extension sets this to 6 pixels wide (you can modify this if you want; just change the relevant lines in stylesheet.css that comes with the extensions).

If you set -naturial-hpadding below 6 pixels you will have to adjust -minimum-hpadding to match it too.

Shell Extensions in Gnome 3.2/Fedora 16

I just upgraded my work computer from Fedora 15 to Fedora 16, which uses Gnome 3.2. This is my first real experience with the GNOME shell in Fedora, because I got rid of it straight away (fallback mode) in F15 since I couldn't stand it so haven't used it since.

Anyhow, I thought I'd give it a shot this time as the GNOME team have apparently been doing good things with the newer versions of GNOME shell.

My first impression - danger Will Robinson! Switch back to fallback mode!

  • poor support for dual monitor which I use at work: top panel is only on one screen
  • to get to the Overview to switch/view windows I have to hover over the top left corner of the left-most screen, rather than just clicking a window from the top panel
  • the clock is in the middle of my top panel, meaning I wouldn't be able to see my current window title, except that
  • the window title of the current window I'm in doesn't show in the top panel. Just the application name.

I was just about to switch to fallback mode again, when I discovered GNOME shell extensions. These are little plugins (think of them like browser plugins) that add functionality to the GNOME shell interface.

Below I'll summarise some of the shell extensions that I found at the GNOME shell extensions website that rectified my problems. You generally install them from that website, and then use gnome-tweak-tool (or "Advanced Settings" in Fedora) to toggle them on and off.

You'll need to log out and in again or restart the shell (Alt+F2, type 'r' for restart, press Enter) to have them take effect.

Top Panel

Frippery Move Clock moves the clock to the left

Frippery Move Clock This moves the clock from the centre of the panel to the left of the status menu button (over the right of the screen). This frees up space for extensions that show icons for open windows, etc. Essential.

Extend Left Box This allows extensions using the top panel (e.g. window list extensions) to use the whole of the top panel instead of just the left half. Essential.

Status Title Bar This shows the entire title (e.g. "Blogger: Mathematical Coffee - Edit post - Google chrome") of your current window in the top panel, rather than just the application name ("Chrome"). Whether to use this or not depends on your top panel real-estate.< /p>

Status Title Bar with Extend Left Box show the full window title

Notification Icons

The following extensions affect the notification icons up the top-right of the screen (accessibility, volume, ...) and the messaging tray at the bottom of the screen.

Evil Status Icon Forever There are many extensions that hide icons (e.g. accessibility) or move icons from the messaging tray to the notification bar (dropbox, ...), but this one seems to cover the functionality of all of them. This allows you to set which notification icons to move from the messaging tray to the top panel (I added dropbox and guake up there) and which to hide (the accessibility icon). For instructions see here.

Evil Status Icon Forever lets me put dropbox & other icons up the top;
notice also the workspace indicator.
Places menu

Places Status Indicator adds a folder to the notification tray that, when clicked, shows a list of folders to open in nautilus.

If you want to remove an individual icon (accessibility, bluetooth, volume, ..) from the notification bar, use Evil Status Icon Forever. If for some reason you don't want to do that, you can install the volume icon remover, bluetooth icon remover, or gnome-shell-extension-remove-accessibility-icon from the fedora repositories.

Workspace indicator adds a little drop-down menu from the notification area letting you switch between workspaces (The '1' in the box in the above picture). Since I added this functionality on my docklet (later in this post), I didn't need this any more).

Status Icon

The "Status Icon" is the menu at the top-right of your panel with a speech bubble next to your user name. The speech bubble is your chat availability - you can control it from there. The menu also contains the "System Settings", "Log out", etc options.
Chat, Hibernate, Power Off options;
No name on the button

Alternative Status Menu By default the status menu only gives a "Suspend" option for closing your computer, and you have to hold down Alt to see "Hibernate" or "Power Off". This extension adds the "Hibernate" and "Power Off" buttons permanently to the menu. Very useful (for me anyway), because I want to power off my computer much more often than suspend it.

Status Only icon removes your username from next to the speech bubble, leaving just the speech bubble. I know my name already so there's no use having it there taking up space!

Empathy Menu You can set your availability for chat with the status menu, but you can't actually start a chat from it. What a pain! This extension adds an option "Chat" to the menu that launches empathy (there are similar ones for Pidgin and Gwibber). I still think I'd like to be able to click on a contact's name from that menu though, like Unity.

Notifications Alert this paints the speech bubble on the status menu red when you have a new notification (e.g. IM messages).

Window list

My biggest gripe is not having a one-click window list. I just want something like the good old gnome-panel. There are a number of extensions providing this functionality. These all work best with Frippery Move Clock extension and the Extend Left extension.

Dock this puts a permanent dock on the left or right side of the screen, the same dock that appears in the overview. You can configure it to autohide or not, and which side of the screen to put it on (not top and bottom though, and doesn't support one per monitor). Quite slick, although not very customisable.

Window List does what it says on the can. Adds window buttons (icon and text) to the top panel. Like the Windows XP task bar.

Window list

Window Icon List Adds icons for open windows to the top panel, like Windows 7.

Panel Docklet S I've saved the best til last! This is the extension I ended up going with - sleek, infinitely customisable. It lets me create either a panel or docklet (my chose) on any side of the screen I like. I can show one icon per group of icons (text too if I want), or one icon per application, and best of all, I can put one docklet per monitor, and I'll only get icons for applications on that monitor! I can also add a workspace switcher (depreciating the need for a separate workspace switcher app), add a button to go to the desktop, add my 'favourites' (on the side dock) as icon shortcuts, and much, much more. I strongly recommend this. The only downfall is that I find that the panel on the second monitor sometimes shows icons of applications even though they've already been closed, and if I right click on them gnome-shell crashes :(.

Panel Docklet S in 'docklet' mode
Panel Docklet S in 'panel-docklet' mode over my top panel

Other

User Themes: this allows you to install custom skins for the GNOME shell and switch between them from gnome-tweak-tool.

Lame Extensions Manager while you're playing around with all the shiny extensions on extensions.gnome.org, this provides a button in the status bar allowing you to toggle them on and off quickly.\

Summary

In the end, I managed to fix most my gripes - removed notification icons I don't use, moved the clock to the left, removed the name from the status bar, and these freed up a lot of space in the top panel.

With that free space I dumped a Panel Docklet S there (in the 'docklet panel' mode) which allows me to quickly see what windows I have open on a particular monitor and go to them (as well as letting me switch between workspaces), and changed the title bar to show the full name of the current window rather than the application name.

All in all, that covers most the gripes I started with! The fact that I can make one docklet per monitor soothes the gnome-shell dual-monitor pain, and the docklet really lets me do most things I wanted (workspace and window switching, shortcuts).

Thursday, 29 March 2012

Getting straight single quotes for code/verbatim in Sweave/knitr

Update 16 April 2012: Yihiu has fixed this from knitr 0.5! Thanks!

I've recently started using knitr to write reports, mainly about code I've written in R.

One thing that I insist upon in documentation on code is that code snippets within the document be able to be copy-and-pasted easily so the user can follow along.

This is why I don't like having the following in my documents:

> words <- c('Hello','world!')
> paste(words)
[1] "Hello"  "world!"

If the user wants to perform the code I've just written, they can't simply select everything and copy-paste; the > symbols are going to get in the way.

I much prefer something like this:

words <- c('Hello','world!')
paste(words)
## "Hello"  "world!"

This is why I like knitr as opposed to Sweave on which it is based; knitr seems to be more flexible in suppressing the leading > in input commands, and putting comments (##) in front of the outputs.

However, knitr has an annoying drawback that Sweave doesn't when it comes to typesetting code: a single quote mark/apostrophe ' in Sweave will stay as such in the output; in knitr, it will be converted to a left or right single quote.

By default, LaTeX will change "straight" single quotes ' into left and right single quotes that are curled depending on whether the quote is open or closed.

If you try and copy-paste these into a terminal you will run into trouble, and R will complain about "unexpected input in "??"", where the "??" may be a funny looking symbol (depending on your terminal) that basically means "I don't understand this fancy symbol you gave me!"

Now, Sweave has some way of dealing with this. It converts all of these funky quotes into normal straight quotes that can be safely copy-pasted into R. Knitr doesn't.

weird curly quotes in knitr

How to fix this? Well, there is a LaTeX package upquote that converts all single quotes that occur in a verbatim environment (or \verb commands) from left/right single quotes into straight single quotes.

It uses the textcomp package to access the command \textquotesingle which is the straight single quote (it also does backticks via \textasciigrave). The upquote package basically says "if you encounter a quote in a verb-like environment, make sure it's \textquotesingle!".

So how does this tie into getting straight quotes in Sweave/knitr? Easy: add \usepackage{upquote} and a fairly arcane command to your preamble:

\documentclass{article}
\usepackage{upquote} % to convert funny quotes to straight quotes
\setbox\hlnormalsizeboxsinglequote=\hbox{\normalsize\verb.'.}%
\begin{document}
<<eval=TRUE,echo=TRUE,tidy=FALSE>>=
    words <- c('Hello','world!')
@
\end{document}

Now you can just run knitr on this and then pdflatex, and voila! Straight quotes.

straight quotes in knitr!

How does this work?

For the more TeX-inclined among you, this is why it works.

First of all, when knitr process a Rnw file (and makes a tex file as an output), it defines a whole bunch of individual characters and uses them in the output. Have a look at the preamble of a knitted document and you will see a whole bunch of:


\newsavebox{\hlnormalsizeboxclosebrace}%
\newsavebox{\hlnormalsizeboxopenbrace}%
....
\setbox\hlnormalsizeboxopenbrace=\hbox{\begin{normalsize}\verb.{.\end{normalsize}}%
\setbox\hlnormalsizeboxclosebrace=\hbox{\begin{normalsize}\verb.}.\end{normalsize}}%

There are lots and lots of these definitions. There appears to be one for each punctuation character and text size.

In particular there is one for the single quote mark, called \hlnormalsizeboxsinglequote. Every single time you have a single quote in a code chunk, knitr replaces this single quote with \usebox{\hlnormalsizeboxsinglequote}. Every single time you use any punctuation character at all within a code chunk, knitr will replace it with the relevant \hlnormalsize[charactername]. It's bizarre, and leads to very ugly code!

For example, the simple chunk in the example above gets rendered (in the tex document) like so:


\begin{knitrout}
\definecolor{shadecolor}{rgb}{0.969, 0.969, 0.969}\color{fgcolor}\begin{kframe}
\begin{flushleft}
\ttfamily\noindent
{\ }{\ }{\ }{\ }\hlsymbol{words}{\ }\hlassignement{\usebox{\hlnormalsizeboxlessthan}-}{\ }\hlfunctioncall{c}\hlkeyword{(}\hlstring{\usebox{\hlnormalsizeboxsinglequote}Hello\usebox{\hlnormalsizeboxsinglequote}}\hlkeyword{,}\hlstring{\usebox{\hlnormalsizeboxsinglequote}world!\usebox{\hlnormalsizeboxsinglequote}}\hlkeyword{)}\mbox{}
\normalfont
\end{flushleft}
\end{kframe}
\end{knitrout}
How gross!

Anyhow, remember that knitr inserts all the savebox commands before the preamble you put in your Rnw document. Well, \setbox operates such that it calculates the contents of the box straight away and saves it to the box register, and then forgets the definition of the box (i.e. the \normalsize\verb.'.).

What this means is that \hlnormalsizeboxsinglequote gets defined before the upquote package is even loaded, and hence the effect of upquote (redefining ' to \textquotesingle within verbatim commands) happens too late to affect the \verb.'. that occurs in \hlnormalsizeboxsinglequote.

To fix this, we would like to retrieve the definition of the \hlnormalsizeboxsinglequote command after we load the upquote package so that its definition gets re-parsed. Then we'd just have to type something like \edef\hlnormalsizeboxsinglequote\hlnormalsizeboxsinglequote to say "set \hlnormalsizeboxsinglequote to what it used to be, but re-read the definition first".

Unfortunately there appears to be no way to do this. Hence the only fix is to look up how knitr defines \hlnormalsizeboxsinglequote by grabbing it out of the preamble of a knitted document, and copy its definition into the preamble of the source document.

This works for now, but it just means that if the knitr package changes how it defines \hlnormalsizeboxsinglequote (maybe in one revision they decide to make all quotes blue in colour), it is up to you to make sure that your redefinition of \hlnormalsizeboxsinglequote in your Rnw file matches that used by Sweave.

Wednesday, 7 March 2012

Be a NethackR!

Net Hack is one of the most amazing games of all times.

It's a rogue-like game, where the quest is to retrieve the Amulet of Yendor from the bottom of the dungeon and bring back it up to the top in order to sacrifice it to your deity and achieve immortal fame & glory, etc. Along the way, one must avoid the many (and I mean many) ways to die, including from the evil Wizard of Yendor, also known as Rodney.

Adventuring through the dungeon (aww, I died)

There are many, many, many ways to die in Net Hack. Also, there's no saving except to resume your game later - once you die, you die. You have to restart the game from scratch. Finally, the game comes with a small hints book to get you started, but no real instructions (like "don't look at Medusa or you'll die! Don't touch a cockatrice or you'll turn to stone! Don't eat to much or you'll die of overeating (not kidding!)").

These factors all make Net Hack a very, very, hard game. And yet addictive! I have yet to win the game after a couple of years of on and off playing, but I still love it.

Anyhow, I decided to write an R package that would let me play Net Hack in R (terminal version, of course! I wouldn't play the graphics version unless I didn't have a keyboard!).

Why would I want to play Net Hack from R? Well ... why not? :D

You can download it from here - either go to the 'Downloads' page and grab the .zip file and install within R (Packages -> Install package(s) from local zip files... OR install.packages('nethackR_1.0.1.zip',repos=NULL)), or if you feel hackerish and are running Cygwin or Linux (or Mac? haven't tested it there), you can grab the source, unzip, and type:

make
make install

After that, go into R, read the help file, and start a game!

library(nethackR)
?nethackR  # read some help files
?nethack   # read some help files
nethack()  # start a game!

You can even feed in nethack options:

nethack(dogname='Indy',catname='lolcatz',hilite_pet=TRUE,time=TRUE)

Enjoy! (and let me know of bugs, I'm sure there are some).

As a note - the package comes bundled with the Net Hack executable already. You may not feel secure running an exe that the package author (me) guarantees you is the actual NetHack.exe and not one filled with viruses. If so, download NetHack yourself and place it within the bin/your_OS-type folder in the nethackR folder of your R library. your_OS-type is either 'unix' (for Linux and Mac) or 'windows' (for Windows). That way you can be sure the executable is safe.

Onward NethackRs!

RIP yet another character!

Extra rambling (mainly for R people):

This was mostly an exercise in writing R packages - it was the first one I ever wrote and wanted something fun to motivate me.

It turned out to be much easier than I thought - you can just call system('nethack'), and R takes care of the rest, even the interactive part - it's as if I'd just run nethack from the terminal instead.

However, I then took this to Windows to test, and if I used the GUI console for R (Rgui.exe as opposed to Rterm.exe), NetHack would start but hang my system until I forcibly closed the NetHack.exe process using the System Manager.

I figured out the solution today by looking at the help file for system in R in Windows (turns out the help file is different in Linux and didn't include this all-important information) - turns out I can't run interactive (text) programs in Rgui, it just doesn't work.

So instead, if the user uses Rgui, the package will launch a command prompt from which the user can play.

Wednesday, 15 February 2012

11.10 Oneiric: "Bad password" and rtlwifi

Today my wireless decided to stop working (under Linux; it of course worked in Windows).

Whenever I tried to connect to a network, it (wicd, that is) would spend ages on the "authenticate" stage before eventually saying "Bad password". Of course, the password was correct. "Bad password" seems to be a generic error wicd gives you that covers all manner of actual errors.

Looking at dmesg | tail, I'd get a whole bunch of:

[  134.347782] rtl8192c: Loading firmware file rtlwifi/rtl8192cfw.bin
[  134.686790] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[  135.037001] rtl8192c: Loading firmware file rtlwifi/rtl8192cfw.bin
[  135.376045] ADDRCONF(NETDEV_UP): wlan0: link is not ready
[  135.548216] rtl8192c: Loading firmware file rtlwifi/rtl8192cfw.bin
[  135.887744] ADDRCONF(NETDEV_UP): wlan0: link is not ready

...and so on.

lsmod | grep rtl yields:

rtl8192ce              84775  0 
rtl8192c_common        75767  1 rtl8192ce
rtlwifi               110972  1 rtl8192ce
mac80211              462046  3 rtl8192ce,rtl8192c_common,rtlwifi
cfg80211              199630  2 rtlwifi,mac80211

And lspci | grep -i network gave

04:00.0 Network controller: Realtek Semiconductor Co., Ltd. RTL8188CE 802.11b/g/n WiFi Adapter (rev 01)

After ages of googling, I found this bug, actually a Fedora bug, that sounds a lot like mine.

Looking through the various attempts at fixes, etc, the only one that worked for me was:

ifconfig wlan0 down
iwconfig wlan0 mode monitor
ifconfig wlan0 up

I know the first line switches off my wireless for a bit, the second sets the mode to 'monitor' (whatever that means??!!), and the third switches it on again, but I have no idea what this all actually means.

It'd love to have an understanding of what was wrong and why that fixed it, but I'll definitely settle for having it fixed :).