11 November 2009

Happy Hacking Keyboard Lite 2 Xmodmap settings for Ubuntu Linux

During the upgrade to Ubuntu 9.10 I managed to clobber my hard-won Xmodmap settings to make my Happy Hacking Keyboard Lite 2 (the USB version, with the arrow keys) work properly.

Here is the commented xmodmap file I use to modify the default key mappings, which is slightly British oriented. To use the file, run xmodmap path_to_file.

Some features:
  • £ and € symbols are mapped to right-diamond-3 and right-diamond-e, respectively.
  • Arrow keys work.
  • PageUp/PageDown on Fn-Arrows work.
  • Left Diamond is another Alt.
  • Tilde, pipe, backslash and backtick behave themselves.
I just hope I don't ever have to work all this out again.


------------------- SNIP FILE -------------------

! This is an xmodmap input file for the Happy Hacking Keyboard, model HHKB Lite 2. It assumes that the
! keymap is already set up for a gb-105 keyboard, then applies fixes for arrow keys and British conventions
!
! This file makes the following changes:
!
! Fix the arrow keys
!
keycode 111 = Up
keycode 116 = Down
keycode 113 = Left
keycode 114 = Right
!
! Fix the Fn-Arrows to give PgUp, PgDown, Home and End
!
keycode 112 = Prior
keycode 117 = Next
keycode 110 = Home
keycode 115 = End
!
! Fix the Alt and Diamond keys
!
keycode 133 = Super_L
keycode 134 = Mode_switch
keycode 64 = Alt_L
keycode 108 = Alt_R
!
! Put the @ on shift-' as British keyboards do
!
keycode 48 = apostrophe at
!
! Put the " on shift-2 as British keyboards do
!
keycode 11 = 2 quotedbl
!
! Put the Pound symbol on right-diamond-3
!
keycode 12 = 3 numbersign sterling sterling
!
! Put the Euro symbol on right-diamond-e
!
keycode 26 = e E EuroSign
!
! Fix tilde
!
keycode 49 = grave asciitilde
!
! Fix backslash
!
keycode 51 = backslash bar
!
!
! Remove all the existing modifier key mappings
!
clear Shift
clear Lock
clear Control
clear Mod1
clear Mod2
clear Mod3
clear Mod4
clear Mod5
!
! Put the modifier key mappings back
!
add Shift = Shift_L Shift_R
add Lock = Caps_Lock
add Control = Control_L Control_R
!
! including this line which makes both Alt keys and the left diamond key act as Alt keys
!
add Mod1 = Alt_L Alt_R Super_L
!
! makes the right diamond acts as the Mode_switch modifier (mapped to right diamond above)
!
add Mod3 = Mode_switch
add Mod5 = Scroll_Lock

------------------------- END OF FILE -----------------------

20 August 2009

Share a git repository with unix groups

If you have a shared Linux/Unix box that all your developers use to share code with git, there are various ways of setting up the shared repository. If you just use git over ssh, you don't need to maintain any more servers.

The simplest possible solutions assume that there is a single user account and different developers are authenticated on the server with their ssh public keys. I needed to restrict which developers get access to different repositories, and to be able to switch these permissions on and off. Unix has already solved this problem of course, with users and groups. Here is how to use real users and groups on your unix server to control git access.

  1. Set up unix accounts for your users. "adduser jim"
  2. Set up groups for each project, "addgroup wonderproject-developers"
  3. Add the appropriate developers to the group "adduser jim wonderproject-developers"
  4. In a private directory on your server, logged in as yourself, make a directory for the git repository "mkdir wonderproject.git"
  5. Make the new group the group owner of the git repository "chgrp wonderproject-developers wonderproject.git/"
  6. Fix the perms so only the group and the owner can read and write the repository "chmod 770 wonderproject.git/"
  7. Make the repository setgid, so that any new files created inside it have group ownership the same as the directory "chmod g+s wonderproject.git"
  8. cd wonderproject.git
  9. create the git repository "git --bare init --shared=group" the --shared option ensures that git keeps the correct permissions when the various developers push commits into the repository.
  10. Now, if your project is empty, clone this new repository onto your desktop and start committing "git clone ssh://jim@git.example.com:port/path/to/repos/wonderproject.git
  11. If you have an existing repository on your desktop and you want to push it into the empty shared repository, edit your .git/config remote url to point at the new server url and then do a "git push --all"

30 June 2009

Switching off Expect: 100-Continue header with Apache HttpClient

Apache HTTP client version 4.0 (at least, the version bundled with the Android SDK) adds the header "Expect: 100-Continue" by default, which confuses many web servers. The following snippet switches this header off:

HttpClient client = new DefaultHttpClient();
client.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false);

I was seeing an error response like the following before I switched this header off:

HTTP/1.1 417 Expectation Failed.
Date: Tue, 30 Jun 2009 10:03:59 GMT.
Server: hi.
Vary: Accept-Encoding.
Content-Length: 364.
Connection: close.
Content-Type: text/html; charset=iso-8859-1.

417 Expectation Failed
Expectation Failed
The expectation given in the Expect request-header field could not be met by this server.
The client sent Expect: 100-Continue but we only allow the 100-continue expectation.

Copying package selections with debian/ubuntu

This is documented in lots of places but it seems to always take me a while to find it. Here is how to install the set of packages from one machine to another.
  1. On the source machine: sudo dpkg --get-selections > output_file
  2. Transfer the output file to the target machine
  3. On the target machine: sudo dpkg --set-selections <>
  4. On the target machine: sudo apt-get -u dselect-upgrade

3 May 2009

Screen Tweaks on Ubuntu Jaunty

Screen is a must-have tool for anyone that spends time at the command line. I move my .screenrc file around with me whenever I move machine, and hadn't thought about it much for a while, but when I started screen on a Ubuntu Jaunty box with no .screenrc, I noticed that the system-wide screen config in /etc/screenrc is now quite useful.

The screenshot below shows the status line from the default config.


Using two whole lines for status messages seems a bit much but I'm a little old school when it comes to preserving display space. So you get load, CPU, free memory, a clock and named screens without any effort now.

I copied the /etc/screenrc to ~/.screenrc and added a few options

bind x
bind ^x
ignorecase on


The bind options stop C-ax, which normally detaches the terminal from screen, from working. I tend to type that keystroke by accident fairly frequently. The last option ignores case during history searches.

If you use lots of gnome-terminal windows or even tabs to manage your terminal sessions you should try screen, it will speed you up a lot once the keystrokes get wired into your muscle memory.

16 February 2009

MyFaces NoSuchMethodError

java.lang.NoSuchMethodError - org.apache.myfaces.component.html.ext.HtmlDataTable.refresh(Ljavax/faces/context/FacesContext;)V

This exception can be thrown by MyFaces when the page backing bean doesn't return a String that is mapped in the navigation-rules in faces-config.xml (or wherever you have your mapping file).

Check for typos or a missing entry in the navigation rules.

Hibernate gotcha: in clause with positional and named query parameters

Here's a gotcha that can break JPA QL queries with an IN clause when using Hibernate as the persistence provider. The problem happens when you use positional parameters rather than named parameters.

Code such as the following will break with positional parameters:
List states = widgetService.findSomeWidgetStates();
Query q = entityManager.createQuery("select count(w) from Widget w where w.state in (?)");
q.setParameter(1, states);
with the error message:
Caused by: java.lang.IllegalArgumentException: Can not set java.lang.Integer field example.Widget.id to....
But if you change to named parameters, as in:
Query q = entityManager.createQuery("select count(w) from Widget w where w.state in (:widgetStates)");
q.setParameter("widgetStates", states);
Everything just works. So it seems named parameters are worth a little extra typing.