Sunday, March 18, 2012

urxvt: looking better and with tabs

urxvt is a great terminal emulator, but I don't particularly care for it's default look and feel. It's not very difficult to make it look better though.

This page explains how you can make urxvt look like gnome-terminal by adding a few lines to your .Xdefaults file. This is how my .Xdefaults looks like:
URxvt*background: #000000
URxvt*foreground: #00ff00
! black
URxvt.color0  : #000000
URxvt.color8  : #555555
! red
URxvt.color1  : #AA0000
URxvt.color9  : #FF5555
! green
URxvt.color2  : #00AA00
URxvt.color10 : #55FF55
! yellow
URxvt.color3  : #AA5500
URxvt.color11 : #FFFF55
! blue
URxvt.color4  : #0000AA
URxvt.color12 : #5555FF
! magenta
URxvt.color5  : #AA00AA
URxvt.color13 : #FF55FF
! cyan
URxvt.color6  : #00AAAA
URxvt.color14 : #55FFFF
! white
URxvt.color7  : #AAAAAA
URxvt.color15 : #FFFFFF

URxvt*font: xft:Monospace:pixelsize=18

URxvt*letterSpace: -1

URxvt.perl-ext-common : default,matcher
URxvt.urlLauncher     : firefox
URxvt.matcher.button  : 1


! scrollbar style - rxvt (default), plain (most compact), next, or xterm
URxvt.scrollstyle: plain

URxvt.perl-ext-common:  default,tabbed
Also, if you like to have tabs, you can run urxvt like urxvt -pe tabbed, or you can add this line to your .Xdefaults.
URxvt.perl-ext-common:  default,tabbed
 In order to open a new tab, press C-M-Down (that is, control and alt and down arrow). To switch tabs use C-M-Left and C-M-Right. To move the current tab, use C-Left and C-Right. I wish I could change these key bindings since the arrow keys are two far away from my comfort zone, but I haven't find a way to do that, yet. Well, nothing is perfect!

For more urxvt customizations, see this page.

By the way, this is the commands I've put in my .stumpwmrc in order to have urxvt as my default terminal emulator. Notice that the class attribute is URxvt not Urxvt as one might expect.
(defcommand urxvt () ()
  "Start a urxvt instance or switch to it if already running"
  (run-or-raise "urxvt" '(:class "URxvt")))
(define-key *root-map* (kbd "c") "urxvt")
(define-key *root-map* (kbd "C-c") "urxvt")
 If you're ever in doubt about the class attribute of a certain window, just switch to it, press C-t : and then type in (stumpwm::window-class (stumpwm::current-window)).

Saturday, March 17, 2012

Making Firefox keyboard friendly

If you're using StumpWM, chances are you don't like to use "the rat" a lot. There is also a good chance that you're an avid emacs user and while typing in Firefox you frequently try pressing C-a to go the beginning of the line and instead have everything selected. No worries! Firefox extensions are, as always, to the rescue.

Mouseless Browsing is a Firefox extension that helps you keep your hands on the keyboard by adding small numeric tags to (almost) everything clickable. Instead of clicking those, you can simply type in the numbers. If you want to open a link in a new tab, just press Alt while typing. If you're in a text area and don't want the numbers ended up in there, hold Ctrl while typing. There are a few other shortcuts too, all configurable in the extension preferences. Another useful option is to have the have the tags hidden by default (they sometimes makes a mess of some pages) and instead have them shown when you press a certain shortcut key.

Firemacs is another helpful extension; one that emacs users will love. It simply changes many of the Firefox's key bindings to things emacs users are more accustomed to (C-a instead of Home, C-f instead of right arrow and so on). You might want to disable making ESC work as Meta (that is, Alt) key. While the trusty C-g works most of the time, there are certain situations (like in menus) that you have to use ESC.

Again, Firefox's extensions are keeping me tightly where I am, stopping me from switching to other browsers. Damn you Firefox, you're locking me in!

Controlling VLC

After fixing the issue of volume control, now I wanted to be able to use my multimedia keys to play/pause VLC. To do that, I used VLC telnet interface and telnetlib which is a very useful library almost equivalent to the Python library of the same name. Of course, I finally learned that I can use VLC's global hotkeys to achieve this, without the problems I encountered, but I'm gonna post what I came up with just for future reference.

Using telnetlib is very straightforward. The code is pretty self-explanatory.
;; vlc control. vlc telnet interface should be enabled.
(defcommand vlc-play () ()
  "start/resume vlc playback"
  (telnetlib:with-telnet-session (tn "localhost" 4212)
    (telnetlib:read-until tn "Password: ")
    (telnetlib:write-ln tn "admin")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "play")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "quit")))

(defcommand vlc-pause () ()
  "pause vlc playback"
  (telnetlib:with-telnet-session (tn "localhost" 4212)
    (telnetlib:read-until tn "Password: ")
    (telnetlib:write-ln tn "admin")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "pause")
    (telnetlib:read-until tn "> ")
    (telnetlib:write-ln tn "quit")))
Obviously, VLC's telnet interface should be active. I found no way to find out if playback is paused in VLC or not. There are two commands that looked like they should help, but they don't. Telnet command is_playing only returns 0 if playback is stopped, not paused. status command for some reason always says "( state paused )". Anyway, I'm glad that VLC itself can create global key-bindings, so I'm happy with my current situation.

Mail Notification

I want to have a visual indicator for when I have unread mail in my inbox. I'm gonna use the SCROLL LOCK LED for this. For controlling the LED I'll use the ledcontrol package which consists of a daemon (ledd) and a few utilities like the ledcontrol command. These enable you to use your LEDs very effectively. There is also a ledcontrol-gtk package which is a graphical frontend for this program. It is useful for learning ledcontrol commands.

This is the code I'm currently using:
;; mail notification
(defvar *unread-mail-count* 0)
(defcommand check-mail () ()
  "Checks an email account and if there is unread mail in the inbox
makes the scroll lock led to slowly blink. Returns the number of
unread messages. Needs the ledcontrol command available and the ledd
daemon pipe file (/var/run/ledd-pipe by default) should be accessible
by normal users."
  (let ((sock (clonsigna:make-imap :host "imap.gmail.com" :port 993 :ssl-p t)))
    (unwind-protect
         (progn
           (clonsigna:cmd-connect sock)
           (clonsigna:cmd-login sock "username" "password")
           (clonsigna:cmd-select sock "inbox")

           ;; cmd-search will return something like (("* SEARCH 2461
           ;; 2465 2471")) The numbers are message ids, that's why we
           ;; split the string by spaces, count the parts and then
           ;; subtract two for the "* SEARCH" part
           (setf *unread-mail-count*
                 ( - (length
                      (cl-utilities:split-sequence
                       #\Space
                       (first
                        (clonsigna:cmd-search sock :criteria "UnSeen"))))
                     2))

           ;; if there is unread mail, have the scroll lock led blink
           ;; for one second every five seconds
           (if (zerop *unread-mail-count*)
               (run-shell-command "ledcontrol set s9 off")
               (run-shell-command "ledcontrol set s9 dutycycle 5000 1 100 20"))

           *unread-mail-count*)
      (clonsigna:cmd-close sock))))

(defvar *mail-notification-timer* (run-with-timer 1 120 'check-mail))
The check-mail function uses the clonsigna package (for IMAP).  When there is unread mail, it sets the SCROLL LOCK LED to blink for one second every five seconds. It also sets the global variable *unread-mail-count* to the number of unread messages.

StumpWM's run-with-timer function is used to have the function called every two minutes.

This simplistic approach is far from perfect. One major problem for me is that if I go to my mail program and read all the unread messages, it will take a while for the LED to stop blinking.

Another problem is that this is not how email clients show the unread mail notifications. They show the number of new unread messages. That is, if there are five unread messages, and you switch to your mail client but don't read them, the notification disappears. Next time when say, two new messages arrive, you are only notified of two new messages, not seven.

The obvious way to do this is to write a plugin for my mail client (currently Thunderbird), but I'm afraid I don't have the time (and interest) to read up on how I can do that, so I'll stick with this for now.

Friday, March 16, 2012

Volume Control

So, I've finally started using StumpWM on my desktop (still on Ubuntu though) and I need to address some more practical matters. One of these is changing sound volume.

There's a handy tool called amixer that ships with Ubuntu and Debian (and probably other distros). It can be used to change many parameters of the mixer. Here we simply use it like amixer sset Master 5%+ which simply raises the master volume by 5 percent. That line also prints out the current volume (among other things) which we will use in order to show the user the current volume. I've added this snippet to my .stumpwmrc file:
;; setup volume control key bindings
(defcommand volume-up () ()
  "Increases master volume by 5 percent."
  (let ((result (run-shell-command "amixer sset Master 5%+" t)))
    (cl-ppcre:register-groups-bind (pct) ("\\[(\\d+)%\\]" result)
      (message "~a%" pct))))
(define-key *top-map* (kbd "XF86AudioRaiseVolume") "volume-up")

(defcommand volume-down () ()
  "Increases master volume by 5 percent."
  (let ((result (run-shell-command "amixer sset Master 5%-" t)))
    (cl-ppcre:register-groups-bind (pct) ("\\[(\\d+)%\\]" result)
      (message "~a%" pct))))
(define-key *top-map* (kbd "XF86AudioLowerVolume") "volume-down")

(defcommand volume-mute-toggle () ()
  "Mutes/Unmutes the master volume."
  (let ((result (run-shell-command "amixer sset Master toggle" t)))
    (cl-ppcre:register-groups-bind (state) ("\\[(on|off)\\]" result)
      (if (equalp state "off")
          (message "muted.")
          (message "unmuted.")))))
(define-key *top-map* (kbd "XF86AudioMute") "volume-mute-toggle")
This defines three commands (volume-up, volume-down and volume-mute-toggle) and binds them to the multimedia volume control keys. This works fine on my computer. If the multimedia keys are not available for you, this page suggests adding these lines:
(define-keysym #x1008ff11 "XF86AudioLowerVolume")
(define-keysym #x1008ff12 "XF86AudioMute")
(define-keysym #x1008ff13 "XF86AudioRaiseVolume")
UPDATE: I just noticed that the code for mute does not work on my Desktop (with Ubuntu Precise) though it's perfectly fine on my laptop (which runs Debian Squeeze). After some poking around, I found out that apparently when pulseaudio is present, amixer cannot unmute sound. I looked around for a pulseaudio equivalent and found pactl. But unlike amixer, pactl does not print out the current state of things after running a command and it also (as far as I know) does not provide a toggle command. What I did was to run pactl list first. This command prints out a lot of information from which we can find out if sound is muted or not. In the following snippet, I'm using a very simplistic regular expression to extract this information. It might not work correctly on a different setup
(defcommand volume-mute-toggle () ()
  "Mutes/Unmutes the master volume."
  (cl-ppcre:register-groups-bind (state)
      ("Mute: (yes|no)" (run-shell-command "pactl list" t))
    (cond ((equalp state "yes")
           (run-shell-command "pactl set-sink-mute 0 0")
           (message "unmuted."))
          (t
           (run-shell-command "pactl set-sink-mute 0 1")
           (message "muted.")))))

Thursday, March 15, 2012

Find keyboard shortcuts

If you're wondering what the key-binding of a certain command is, just press C-t h w. You'll be prompted for the command you're looking for and if it's bound to a key, you'll know about it. To know more about help options (which all start with the key-binding C-t h) press C-t h ?.

Wednesday, March 14, 2012

Keyboard Layouts

Today I decided to tackle the problem of keyboard. I normally have two keyboard layouts, one for US English (the default) and one for Persian. I had heard that setxkbmap can help me do this. With some digging I found running this command can help me do that:
$ setxkbmap "pc+us+ir:2+inet(evdev)+group(shifts_toggle)"
I got that line by running setxkbmap -print on my Ubuntu machine. The output had something that seemed to be what I want. And I was right! Running that, I noticed that the changes I've made with xmodmap was reset. Well, all I had to do was to put the line that runs xmodmap after setxkbmap. Like this:
(run-shell-command "setxkbmap \"pc+us+ir:2+inet(evdev)+group(shifts_toggle)\"")

;; load keyboard map
(run-shell-command "xmodmap ~/.xmodmap")
Except that didn't work. I logged out and logged back in, and I saw my alt and ctrl keys are not where they should be. A couple of times running those commands by C-x C-e from within Emacs gave me an idea what might be wrong. You see, by default, run-shell-command runs the command given to it asynchronously. I needed to make sure setxkbmap is done before I move onto xmodmap. Thankfully, run-shell-command has one last optional argument collect-output-p. It's function is to collect the program output, but in doing so it makes the execution synchronous. So adding that argument fixed the problem:
(run-shell-command "setxkbmap \"pc+us+ir:2+inet(evdev)+group(shifts_toggle)\"" t)
Voila! Now I can switch layouts like before. Of course, I have no visual indication of the current layout anymore. I'm not 100% sure I want that. I might choose to work out a way for caps lock or scroll lock LED to do that for me later.

UPDATE: If you want a visual indicator for the current keyboard layout, you can change the setxkbmap invokation to something like this:
(run-shell-command
 "setxkbmap \"pc+us+ir:2+inet(evdev)+group(shifts_toggle)\" -option grp_led:caps"
 t)
This makes the CAPS LOCK led to turn on when an alternate keyboard layout is active.

Better Console Font (in Arch)

In order to use Terminus as my console (tty) font, I simply installed the package terminus-font with pacman (includes both console and X11 ...