Monday, May 14, 2012

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 versions). Then I edited the CONSOLEFONT variable in rc.conf to have the value ter-216b.

I haven't been able to enable 256 colors in console and use my monitor's native 1920x1080 resolution (the best mode hwinfo reports is 1280x720 and for some reason it doesn't seem to work either).

Saturday, May 5, 2012

Switching from GNU Screen to tmux

GNU Screen is a fantastic program. It is, however, more or less abandoned. tmux promises to be a more full-featured alternative, with cleaner source code and easier configuration. This is the .tmux.conf file I'm currently using.

# change tmux key-bindings to screen key-bindings (with ^O as prefix)

# Set the prefix to ^O
unbind C-b
set -g prefix ^O
bind a send-prefix

# Bind appropriate commands similar to screen.
# lockscreen ^X x 
unbind ^X
bind ^X lock-server
unbind x
bind x lock-server

# screen ^C c 
unbind ^C
bind ^C new-window
unbind c
bind c new-window

# detach ^D d
unbind ^D
bind ^D detach

# displays * 
unbind *
bind * list-clients

# next ^@ ^N sp n 
unbind ^@
bind ^@ next-window
unbind ^N
bind ^N next-window
unbind " "
bind " " next-window
unbind n
bind n next-window

# title A
unbind A
bind A command-prompt "rename-window %%"

# other ^O
unbind ^A
bind ^O last-window

# prev ^H ^P p ^? 
unbind ^H
bind ^H previous-window
unbind ^P
bind ^P previous-window
unbind p
bind p previous-window
unbind BSpace
bind BSpace previous-window

# windows ^W w 
unbind ^W
bind ^W list-windows
unbind w
bind w list-windows

# quit \ 
#unbind \
#bind \ confirm-before "kill-server"

# kill K k 
unbind K
bind K confirm-before "kill-window"
unbind k
bind k confirm-before "kill-window"

# redisplay ^L l 
unbind ^L
bind ^L refresh-client
unbind l
bind l refresh-client

# split -v |
unbind |
bind | split-window

# :kB: focus up
unbind Tab
bind Tab select-pane -t:.+
unbind BTab
bind BTab select-pane -t:.-

# " windowlist -b
unbind '"'
bind '"' choose-window

# Q break-pane (close all other panes)
unbind !
bind Q break-pane

#####################################################################

# enable 256 color support
set -g default-terminal "screen-256color"

# make prefix+S toggle status line visibility
bind S set -g status

# more or less screen style split
# prefix+H: split horizontally by grabbing the previous window into the new pane
# prefix+V: split vertically by grabbing the previous window into the new pane
bind H join-pane -ht :-1
bind V join-pane -vt :-1

The bulk of the code is for making tmux key-bindings like those of GNU Screen (up until the seprator line). Most of that code is copied from the sample config file that came with the Arch package (in /usr/share/tmux/screen-keys.conf). The rest adds these functionalities:
  • Enable 256 color support.
  • Add a key-binding for toggling status line visibility.
  • Add a pair of key-bindings for screen style splitting. In screen, when you split a window, two windows are created and each can be rotated so that it contains one of the previously created windows. In tmux, splitting results in creating two "panes". A window can contain several panes. This is usually desirable (with this config, accessible through the use of prefix+| and prefix+% shortcuts). However, sometimes you might want to split the window so that the new pane contains one of the previously created windows. The last two lines add the prefix+H and prefix+V key-bindings that make this possible (one for splitting vertically, the other horizontally). The new pane will contain the window before the current one.
I also added this to my .stumpwmrc to make switchig to the emacs inside tmux easier (again, this is not exactly correct, but it works most of the time for me).

(defcommand emacs-in-tmux () ()                                                                                                                                                                
  "attempts to switch to an emacs instance run in a tmux window                                                                                                                          
called 'emacs', itself inside a urxvt instance."                                                                                                                                               
  (let ((ret                                                                                                                                                                                   
         (run-shell-command "tmux select-window -t emacs ; echo $?" t)))                                                                                                                       
    (if (eql (elt ret 0) #\0)                                                                                                                                                                  
        (run-or-raise "urxvt" '(:class "URxvt"))                                                                                                                                               
        (message "no screen session found."))))                                                                                                                                                
(define-key *root-map* (kbd "C-e") "emacs-in-tmux")

My latest urxvt configuration

The latest changes include turning off the scrollbar (who needs a scrollbar anyway), turning off the tabs (screen and tmux do the job better) and also stopping urxvt from jumping forward when a program is producing output and I'm looking previously generated output (the last three lines).
! to match gnome-terminal "Linux console" scheme                                                                                                                                               
! foreground/background                                                                                                                                                                        
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.scrollBar: false     ! turn off the scroll bar                                                                                                                                           
                                                                                                                                                                                               
URxvt*secondaryWheel  : true                                                                                                                                                                   
URxvt*secondaryScreen : true                                                                                                                                                                   
                                                                                                                                                                                               
URxvt*scrollTtyOutput   : false                                                                                                                                                                
URxvt*scrollWithBuffer  : true                                                                                                                                                                 
URxvt*scrollTtyKeypress : true

My GNU Screen Configuration

First an update on my latest setup. I switched to Arch Linux a while back and I'm rather happy with it so I'm not thinking of going back to Ubuntu at the moment despite the fact that I'm hearing it's in a good condition.

Second I've started using screen a lot more than before. Specifically, I began running my emacs session inside screen a while back, so that I can connect to my home computer from other places and attach to my screen session and use the running emacs instance. More recently, I've switched to using tmux instead of screen but for the sake of keeping history, I'm posting the code and configuration I used to use here. tmux will be the subject of another post.

This is the .screenrc I used:

escape ^Oo                                                                                                                                                                                     
vbell off                                                                                                                                                                                      
                                                                                                                                                                                               
# Scrollback buffer size in lines                                                                                                                                                              
defscrollback 5000                                                                                                                                                                             
                                                                                                                                                                                               
startup_message off                                                                                                                                                                            
                                                                                                                                                                                               
hardstatus alwayslastline                                                                                                                                                                      
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'                                                       
                                                                                                                                                                                               
# enable support for 256 colors                                                                                                                                                                
term screen-256color                                                                                                                                                                           
terminfo rxvt-unicode 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'                                                                                                                                   
                                                                                                                                                                                               
# fix for residual editor text. sometimes when you run an editor and                                                                                                                           
# close it, some of its text may stay visible. this fixes that                                                                                                                                 
# problem.                                                                                                                                                                                     
altscreen on                                                                                                                                                                                   
                                                                                                                                                                                               
screen -t  emacs       0        emacs -nw                                                                                                                                                      
screen -t  shell0
It changes the screen prefix to ^O so that it doesn't clash with the emacs shortcut. It turns off the visual bell, enlarges to scrollback buffer, turns off the welcome screen, adds a status line, enables 256 color support inside screen, enables alternate screen (so that residual text from some editors will not stay visible after closing them), and finally starts a shell and an emacs instance.

I also added this code to my .stumpwmrc so that I can switch to emacs in the usual way (by pressing C-t C-e):
(defcommand emacs-in-screen () ()                                                                                                                                                              
  "attempts to switch to an emacs instance run in a gnu screen window                                                                                                                          
called 'emacs', itself inside a urxvt instance."                                                                                                                                               
  (let ((ret                                                                                                                                                                                   
         (run-shell-command "screen -X select emacs > /dev/null ; echo $?" t)))                                                                                                                
    (if (eql (elt ret 0) #\0)                                                                                                                                                                  
        (run-or-raise "urxvt" '(:class "URxvt"))                                                                                                                                               
        (message "no screen session found."))))                                                                                                                                                
(define-key *root-map* (kbd "C-e") "emacs-in-screen")
For some reason this sometimes fails to switch to emacs properly, but it usually does!

And one last thing. The GNU Screen version shipped with Arch lacks vertical split support. This AUR package contains the patch for vertical splitting. Unfortunately, it lacks another patch that stops screen from complaining about long $TERM values, so I made a new AUR package that applies this other patch, too. I found that the process of creating Arch packages is surprisingly easy. In this case, I just downloaded the other package, updated its PKGFILE, and made the source tarball using makepkg --source.

Friday, May 4, 2012

Stop urxvt scrolling

Say some program is continueously spitting output and your want to scroll back in the history and check something. By default, you can't. urxvt will jump down when something is added to the output. You can do one of these things:
  • Press Ctrl-s. This will pause the program. When you're done, press Ctrl-q to continue.
  • Add these lines to your .Xdefaults (or wherever you put your X resources):

    URxvt*scrollTtyOutput:      false                                                                                                                                                             
    URxvt*scrollWithBuffer:     true                                                                                                                                                              
    URxvt*scrollTtyKeypress:    true
    

Sunday, March 25, 2012

LightDM: Switch user from the command line

Say you're on Ubuntu 11.10 or later, or any other distribution that uses LightDM. What would you do to go back to the greeter window where you can choose another user without logging out? In most other shells, there is a graphical option for it. In StumpWM you can use the dm-tool utility:
dm-tool switch-to-greeter

Friday, March 23, 2012

PPTP from Command Line

Although this blog is supposed to be about StumpWM, there are things unrelated to the window manager that one needs to do in order to make the transition easier. Since the network manager applet is not available in StumpWM (unless you use a systray program like trayer), you need to know how to do certain tasks without it.

I'm comfortable configuring my network from command line. There was one thing though that I had always done using Network Manager applet; setting up pptp. I googled for it and quickly found this which explains how I can use pptp from the command line.

First you create a file in /etc/ppp/peers. Name the file whatever you want, like myvpn. Put this inside that file:

remotename myvpn
linkname myvpn
ipparam myvpn
pty "pptp <host> --nolaunchpppd "
name <username>
usepeerdns
require-mppe
refuse-eap
noauth

# adopt defaults from the pptp-linux package
file /etc/ppp/options.pptp
Fix the host name and the user name accordingly. Then add a line like this to /etc/ppp/chap-secrets:

<username> myvpn <password> *

Again obviously you need to put your own username and password plus the correct connection name.

I have also created two scripts in /etc/ppp/ip-up.d/ and /etc/ppp/ip-down.d/ to set up the default gateway properly. These scripts are tailored for my own system and you might need to adapt them. the one in ip-up.d/ removes the current default gateway and adds a new one. The other one reverses this.

/etc/ppp/ip-up.d/myvpn:
#!/bin/bash

if [[ $PPP_LOCAL = 192.168.2.* ]]; then
    route del default gw 192.168.1.1
    route add default gw 192.168.2.100
fi
/etc/ppp/ip-down.d/myvpn:
#!/bin/bash

if [[ $PPP_LOCAL = 192.168.2.* ]]; then
    route add default gw 192.168.1.1
    route del default gw 192.168.2.100
fi
Don't forget to make the scripts executable. Also notice that ip-up.d/ and ip-down.d/ are only available in Debian and its derivatives (to learn more about the arguments passed to them and the available environment variables, see the Debian /etc/ppp/ip-up and /etc/ppp/ip-down scripts). Other distros use slightly different paths.

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.

Monday, March 12, 2012

Change the X mouse pointer to an arrow

In my Debian installation, the mouse pointer is an arrow. In the second X server I use on Ubuntu however, the mouse pointer is the default x shape which I don't like. Fortunately, adding this one line to .stumpwmrc can fix this.
(run-shell-command "xsetroot -cursor_name left_ptr")

Sudo, the stumpish way

This has been nagging me for a few days. It was a small thing, but it still bothered me. Whenever I want to run a command, I use the C-t ! shortcut. If I want to run it as root, I had to use gksu, but gksu does not exactly fit in the simple look and feel of StumpWM. What I wanted was a way to ask for password in the small box that appears in the top right when StumpWM wants some input.

A look at sudo man page pointed me to the right direction. sudo has an option that let's you specify another program to ask for password. Perfect. The command line option is -A. The program can be specified either in sudo config file or using the environment variable SUDO_ASKPASS. This script would do the trick:
#!/bin/bash
env SUDO_ASK_PASS=~/bin/ask.sh sudo -A $@
Now we only need the ask.sh script. But how can we get a script to call a StumpWM function? At first, I wanted to write a small server that opens a port and listens for commands. Fortunately, I accidentally learned about stumpish which is a script in StumWM's contrib directory that can send commands to StumpWM and return the results. Here's how ask.sh uses stumpish:
#!/bin/bash
stumpish stumpwm-password password:
The first argument is the name of a StumpWM command, while the rest are it's parameters. Since, as far as I know, there is no StumpWM command to ask for input, I wrote these two in my .stumpwmrc:
;; these commands are mainly intended to be called by external
;; commands through the use of stumpish
(defcommand stumpwm-input (prompt) ((:string "prompt: "))
  "prompts the user for one line of input."
  (read-one-line (current-screen) prompt))

(defcommand stumpwm-password (prompt) ((:string "prompt: "))
  "prompts the user for a password."
  (read-one-line (current-screen) prompt :password t))
I called the first script stu and put it with ask.sh in my bin directory. Now whenever I want to run synaptic, I press C-t ! and type in stu synaptic.

Sunday, March 11, 2012

Multiple X servers and Firefox problems

As I've said before, running StumpWM on Ubuntu using a new .desktop file in /usr/share/xsessions/ did not turn out a very pleasant experience. This article however gave me another idea. How about running a separate X server? I decided to give it a shot.

I simply created a .xinitrc file in my home directory and in it I put this: exec stumpwm. After that, I switched to a tty by pressing Ctrl-Alt-F1 and ran startx -- :1. Then I pressed Ctrl-Alt-F8 to switch to the new X screen. It actually worked! I quickly copied my configuration from my laptop and restarted StumpWM. Everything seemed to be working, until I tried to start Firefox.

Firefox simply gave me an error message saying that another instance of Firfox was already running. I searched about this on the Internet and learned that I can run Firefox in a new profile and with the -no-remote option to stop it from connecting to the already running instance. In order to create a new profile, you can run firefox --ProfileManager. Then to start Firefox with the new profile and as a new instance you can run firefox -no-remote -P profilename.

Long story short, it didn't work as I thought it should. The first time I ran it, Firefox started correctly. But whenever I ran one of the other commands to open a new tab or anything, it just gave me an error saying another instance is running but is not responding. I finally found out that if I drop the -no-remote option (while retaining -P) it will work as expected.

The question for me now is, should I stick with my plan of building on Debian, or should I stick with Ubuntu? I still get doses of unstability on Ubuntu while Debian remains rock solid. Also, keeping Ubuntu around might tempt me to go to Unity whenever I ran into difficulties instead of trying to find a workaround and learn something in the process. I'm gonna need to think about this.

Saturday, March 10, 2012

A quick note on wireless firmware in Debian

Installing Debian on my laptop, I realized that I need a non-free firmware for my wireless card. Apparently Ubuntu bundles this with its installation media, but not Debian. So after installing Debian, I downloaded this tarball from here and installed the .deb package with iwlwifi in its name (that's for my Intel wireless card).

Beginning StumpWM configuration

StumWM stores its configuration in a .stumpwmrc file in the home directory. The number one thing I need in this file is Swank. Here's the code I used.
(load "/home/mostafa/slime/swank-loader.lisp")
(swank-loader:init)
(defcommand swank () ()
  (setf stumpwm:*top-level-error-action* :break)
  (swank:create-server :port 4005
                       :style swank:*communication-style*
                       :dont-close t)
  (echo-string
   (current-screen)
   "Starting swank. M-x slime-connect RET RET, then (in-package stumpwm)."))
(swank)
For some reason, this does not always start swank though. When that happens, I just hit C-t ; and run "swank." I can then connect to the Lisp image by invoking slime-connect in emacs.

I've been using this sample as the base for my own .stumpwmrc. What I've learned? First, I learned how I can declare a command that can be run interactively run through StumpWM's semi-colon prompt. The macro is defcommand. It's similar to defun, only with an additional set of "interactive" parameters which will be prompted for at run time.

I also learned that I can define my own key-bindings using define-key. Here's an example:
(define-key *root-map* (kbd "x") "firefox")
This tells StumpWM to run the command "firefox" previously declared by defcommand when I hit C-t x. C-t is StumpWM's prefix key (can be changed of course). Any key-binding added to *root-map* is should be used after pressing this prefix. If wan't to make a key-binding without the prefix key, I can add it to *top-map*. This is how the "firefox" command is defined:
;; launch web browser
(defcommand firefox () ()
  "start firefox or switch to it if already running."
  (run-or-raise "firefox" '(:class "Firefox")))
Remember that the value after :class should be Firefox with a capital F. If it's not written like that, rerunning the command will not raise the current window, but will open a new one. On Debian, :class should be Iceweasel instead of Firefox. (For a short explanation of class and other window attributes in X see here. In short, class name is, by convention, the instance name with the first letter capitalized.)

One of the most frequent things I do throughout my day is jumping to Wikipedia to look up something, or to search for it in Google. These two commands help me do that easier:
;; ask the user for a search string and search for it in Wikipedia
(defcommand wikipedia (search)
  ((:string "Search in Wikipedia for: "))
  "prompt the user for a search term and look it up in the English Wikipedia"
  (check-type search string)
  (let ((uri (format nil "http://en.wikipedia.org/wiki/Special:Search?search=~a" search)))
    (run-shell-command
     (cat "firefox \"" uri "\""))))

;; ask the user for a search string and search for it in Google
(defcommand google (search)
  ((:string "Search in Google for: "))
  "prompt the user for a search term and look it up in Google "
  (check-type search string)
  (let ((uri (format nil "http://www.google.com/search?q=~a" search)))
    (run-shell-command
     (cat "firefox \"" uri "\""))))
Finally, I need to more things. First, Network Manager seems essential. I'm going to use it's Tray icon at the moment, so since StumpWM doesn't have a tray, I'll use trayer which launches a tray in a floating window. In Debian, trayer can be installed by running apt-get install trayer. This launches trayer properly and then runs the Network Manager applet.
;; system tray
(run-shell-command
 "/usr/bin/trayer --SetDockType false --transparent true --expand false")

;; start network manager applet
(run-shell-command "nm-applet --sm-disable")
And then I need to load my own customized keymap (I swap the ctrl and alt keys and make Caps Lock an additional alt).
;; load keyboard map
(run-shell-command "xmodmap ~/.xmodmap")
That's it for now.

The Host System

I tried using StumpWM on the same Ubuntu (Precise Beta) installation I'm using right now. I created a new xsession for it and tried logging in. I wasn't impressed. The graphics is for some reason garbled and I encountered several crashes.

I decided using Debian stable instead. I installed Squeeze on my laptop, then installed SBCL and the libraries I needed (cl-clx and cl-ppcre) and then I finally downloaded and built StumpWM, created the session file and logged into it. Now this is much better!

Debian stable is a bit outdated, so I added the backports repositories and upgraded Firefox (well, Iceweasel actually). I also installed Mouseless Browsing plug-in for Firefox. I quite like it. It does, every now and then, make a website less pretty than it usually is, but otherwise it makes the web experience a lot better for the folks who don't like taking their hands off the damn keyboard!

Another thing I really need is Emacs. I've been using Emacs 24 for quite some time. I use the packages from Emacs Snapshot. I then transferred a copy of Emacs Prelude from my desktop together with my own customizations. I'm ready to set off now.

Start...

This is going to be a blog about my experience with StumpWM, a tiling window manager written in Common Lisp. If you want to know how I got here, you can read on.

I've been a happy user of Ubuntu for a few years now. When they switched to Unity, I was in the pro-Unity camp. I like especially how it saves precious screen space. Trouble began when I upgraded to Oneiric. There were a few problems which gave me hours of headache. Some of those have been fixed as of Precise Beta, but one nasty one still remains. The graphics gets ever slower as I continue using the system. Dragging windows and icons especially becomes almost impossible.

A week or two ago I decided enough was enough. I tried Linux Mint with it's shiny new GNOME Shell desktop, but I soon found out that I can't stand the amount of screen space wasted by local menus, title bars and two panels. What I could do about it? I could do switch to a window manager that is even more minimalistic than Unity. I immediately remembered StumpWM.

Common Lisp is my favorite programming language. I've also been a GNU Screen and Emacs user for years, both sources of inspiration for StumpWM. I also like using keyboard instead of mouse as much as I can, so a keyboard-driven window manager wouldn't put me off.

I found out that there is a lot to learn and I need a place to document what I learn somewhere. And that's why I started this blog. It will primarily serve as a repository of knowledge for me. I've also learned that writing somehow etches things into my memory so that I'm less likely to forget them. And if, by a happy coincidence, what I write here is of use to someone else, even better!

A quick note about the name of this blog. I usually obsess about names, but this time I thought I'd go with whatever came to my mind first. I was looking for a name that's both Lispy and Stumpy, and I came up with Thtump, which is both but might be rather lame. I've already chosen the sub-domain, so it's too late to change it!

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 ...