Wednesday, October 12, 2011

ido-mode and virtual buffers

Every now and again you come across something in Emacs and slap your forehead and say "why didn't I notice that before". ido-mode is one, but the setting ido-use-virtual-buffers really makes it. The concept is simple : ido-mode remembers all your past buffers so all you need to do is "C-x b" (ido-switch-buffer) and start to type the filename and ido will complete to it having remembered it from previous sessions. No need to use C-x C-f and possibly the ido find facility any more - just type the mainpart of the filename or part of it. Incredible cool time saver and very very useful.

From the Manual

ido-use-virtual-buffers is a variable defined in `ido.el'.
Its value is t
Original value was nil

If non-nil, refer to past buffers as well as existing ones.
Essentially it works as follows: Say you are visiting a file and
the buffer gets cleaned up by mignight.el. Later, you want to
switch to that buffer, but find it's no longer open. With
virtual buffers enabled, the buffer name stays in the buffer
list (using the `ido-virtual' face, and always at the end), and if
you select it, it opens the file back up again. This allows you
to think less about whether recently opened files are still open
or not. Most of the time you can quit Emacs, restart, and then
switch to a file buffer that was previously open as if it still
This feature relies upon the `recentf' package, which will be
enabled if this variable is configured to a non-nil value.

my ido settings are currently:-

 '(ido-create-new-buffer (quote never))
'(ido-enable-flex-matching t)
'(ido-enable-last-directory-history nil)
'(ido-enable-regexp nil)
'(ido-max-directory-size 300000)
'(ido-max-file-prompt-width 0.1)
'(ido-use-filename-at-point (quote guess))
'(ido-use-url-at-point t)
'(ido-use-virtual-buffers t)

Wednesday, October 5, 2011

Javascript utilities

Playing with javascript lately I came across a super utility called jshint : and Dale Harvey has produced a super jshint-mode! For a javascript nOOb like me it's invaluable when combined with jslint (jshint can replace it, but you might like to turn it off at times then manually invoke jslint instead).

See : jshint and Javascript Lint

My javascript set up:-

(require 'js-beautify)

(add-to-list 'load-path "~/.emacs.d/jquery-doc")
(require 'jquery-doc)
(add-hook 'js2-mode-hook 'jquery-doc-setup)
(require 'flymake-jshint)
(add-hook 'js2-mode-hook
(lambda () (flymake-mode t)))

(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

;; (add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))
(add-hook 'js2-mode-hook '(lambda () (js-beautify)(define-key js2-mode-map (kbd "M-t") (lambda()(interactive)(js-beautify)))(define-key js2-mode-map [(shift f10)] (lambda()(interactive)(jslint-thisfile)))))

;; javascript lint
(defun jslint-thisfile ()
(compile (format "jsl -process %s" (buffer-file-name))))
(defun jslint-thisfile-test ()
(compile (format "jsl -process %s" (buffer-file-name))))

(provide 'rgr-javascript)

Wednesday, September 21, 2011

Booting Debian without X/GDM

Simply remove the startup links for the display manager. e.g I used gdm3 :

sudo update-rc.d -f gdm3 remove

Reboot and voila, my little Thinkpad is running as an exim4 MTA, mysql rdbms, apache virtual hosting server and general lan gateway but with an extra few hundred megs of RAM as we haven't loaded the extremely heavy X........

Wednesday, August 24, 2011

bash script to symbolically link using find results


find /var/www/webs -name 'vhost' -exec bash -c 'IFS=/ read -a names <<< "$1"; ln -sf "$1" "${names[4]}"' -- {} \;

Sunday, August 14, 2011

Backup all mysql databases for project infrastructure

Frequently I need to back up all the databases on the server and restore locally on the development machine for testing/backup. These scripts (on the bash $PATH) do just that. Sorry about the indentation but I dont have the inclination to fight with bloggers defaults today....

(1) backup-web-databases

for dir in "${1:-$HOME/webs}"/*/
if [[ $(basename "$dir") != "template" ]]
cd ${dir}
if [ -e "db" ]
echo "Backing up database in ${dir}"
cd ~/webs

(2) backup-database : this parses an authinfo file in the format "user password dbinstance host"

[ -a db/backups ] || mkdir db/backups
read -r uid pwd dbname rest < <(head -1 db/authinfo)
mysqldump --skip-lock-tables -u${uid} -p${pwd} --database ${dbname} > db/backups/db-backup.sql

(3) restore-web-databases

cd ~/webs
for dir in "${1:-$HOME/webs}"/*/
if [ "$(basename "$dir")" != "template" ]
cd ${dir}
if [ -e "db" ]

(4) restore-database

[ -a db/backups ] || mkdir db/backups
read -r uid pwd dbname rest < <(head -1 db/authinfo)
if [ -e "db/backups/db-backup.sql" ]
echo "Restoring DB for `pwd`"
mysql -u ${uid} -p${pwd} < db/backups/db-backup.sql
echo "No DB back found in `pwd`"

Thursday, July 7, 2011

modifications to up scripts for vpn
In the scripts in etc/ppp/ip-up.d you can use

When the ppp link comes up, this script is called with the following
$1 the interface name used by pppd (e.g. ppp3)
$2 the tty device name
$3 the tty device speed
$4 the local IP address for the interface
$5 the remote IP address
$6 the parameter specified by the 'ipparam' option to pppd

Silly I missed that.

My Emacs Files At GitHub

Wednesday, July 6, 2011

Bash script to sync a number of machines from the current one

pass "all" to do the lot from one major node. edit as appropriate.
set SYNCHOSTS if you like or set the defaults as appropriate.



if [ -z ${hosts} ]; then
hosts=(asus x30 dev t60)

for myhost in "${hosts[@]}";
ping -c 1 "$myhost" > /dev/null
if [ "$?" -eq 0 ] ; then
echo "${myhost} up"
if [ "${COMMAND}" = "all" ]; then
rsync -avz --force --exclude ".emacs.d/agent" --exclude ".emacs.d/url" --delete --exclude "auto-save-list" --exclude ".gnuskillfiled" --exclude "*~" --ignore-errors ~/common-files $USER@$myhost:
rsync -avz ~/Mail $USER@$myhost:
rsync -avz ~/.org-files $USER@$myhost:
rsync -avz ~/bin $USER@$myhost:
echo "$myhost down"

My Emacs Files At GitHub

script to return ip address of an interface

sudo ifconfig ${1-eth1} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'

My Emacs Files At GitHub

Going Anonymous - the Linux way : iPlayer, VPNs and PPTP

Somewhat naughtily I have a hankering to watch UK TV on my PC at times. There's only so much Dieter Bohlen and the Bavarian Brass Quartet one can take. Alas, in a fit of stupiditiy and bureaucracy English online TV is not allowed - they filter youby your country's IP address. The IP address is the "unique" address of yourinternet connection - its how hackers and "groomers" are caught! So the "easy"way is to use whats called a "proxy". A proxy routes some or all of yourinternet traffic through a "proxy" and the site you are visiting sees the IP address of the proxy and not your own country/location specific IP. As a resultof this the BBC and ITV or any site that limits its viewers gladly give uptheir goodies in this victim-less crime.

There is a problem however. Good proxies are hard to find. And when you do find them many wont stream video -only static web content. Where there is a need there is a supplier however! Andsure enough you can purchase a "proxy" from companies in the UK. This led me to consider a VPN after a friend mentioned them. A VPN, or Virtual Private Network,allows you to route traffic to a remote end point. And that remote end point hasits own localised IP address. So how to do this in Linux?The first option is the simply atrocious Network-Manager. It provides a GUI foryou to set up a VPN. When it doesnt crash. It also, and bizarrely, ignores and/or clashes with the standard Linux network stack configuration files. All that AND it only allows one VPN to be enabled.The second option was to read up on and manage manually the horrifically complexLinux network config files. My loathing for Network-Manager made me role up my sleeves and take this approach.So, this small blog doesnt wax lrical on the hurdles but merely explains the results! Hopefully it can be used to help you get a vpn working.So, off we go.

First step is the /etc/network/interfaces file

auto lo
iface lo inet loopback

auto eth1
iface eth1 inet dhcp

iface uk1 inet ppp
provider uk1

Here we have defined a device, uk1, for the vpn. Note the "ppp". This tells th enetworking infrastructure that its a peer to peer connect. We need more info to establish the connection : the "provider" clause points to /etc/ppp/peer/uk1which is as follows:-

pty "pptp VPN_SERVER-ADDRESS --nolaunchpppd"
remotename PPTP
file /etc/ppp/options.pptp
ipparam uk1

The personalised parts are obvious enough. But what about authentication? The "name" clause in the previous file is mapped to to an auth file : in this case/etc/ppp/chap-secrets where the contents are simply

# Secrets for authentication using CHAP
# client server secret IP addresses PPTP PASSWORD-FOR-VPN-SERVER *

How do we fire this up? Two ways

sudo pon uk1


sudo ifup uk1

If success you will see a new route in your routing table! But this route is currently not used since we havent yet told the system WHAT data must travel onthis new route.Before we bring "up" the interface :

[5107]shamrock@development:/etc/ppp$ sudo route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface UGH 0 0 0 eth1 U 0 0 0 eth1 UG 0 0 0 eth1


[5109]shamrock@development:/etc/ppp$ sudo ifup uk1
[5110]shamrock@development:/etc/ppp$ sudo route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface UH 0 0 0 ppp0 UGH 0 0 0 eth1 U 0 0 0 eth1 UG 0 0 0 eth1

In this example the ip address "" is that of us that will appear to the sites we visit, the new interface ppp0 is there too. A quick look in our/var/log/syslog shows what happened in more detail:-

Jul  6 20:49:12 dev pppd[1]: pppd 2.4.5 started by root, uid 0
Jul 6 20:49:12 dev pppd[1]: Using interface ppp0
Jul 6 20:49:12 dev pppd[1]: Connect: ppp0 <--> /dev/pts/3
Jul 6 20:49:12 dev pptp[2]: anon log[main:pptp.c:314]: The synchronous pptp option is NOT activated
Jul 6 20:49:12 dev pptp[3]: anon log[ctrlp_rep:pptp_ctrl.c:251]: Sent control packet type is 1 'Start-Control-Connection-Request'
Jul 6 20:49:13 dev pptp[3]: anon log[ctrlp_disp:pptp_ctrl.c:739]: Received Start Control Connection Reply
Jul 6 20:49:13 dev pptp[3]: anon log[ctrlp_disp:pptp_ctrl.c:773]: Client connection established.
Jul 6 20:49:13 dev pptp[3]: anon log[ctrlp_rep:pptp_ctrl.c:251]: Sent control packet type is 7 'Outgoing-Call-Request'
Jul 6 20:49:14 dev pptp[3]: anon log[ctrlp_disp:pptp_ctrl.c:858]: Received Outgoing Call Reply.
Jul 6 20:49:14 dev pptp[3]: anon log[ctrlp_disp:pptp_ctrl.c:897]: Outgoing call established (call ID 0, peer's call ID 33920).
Jul 6 20:49:14 dev pptp[2]: anon log[decaps_gre:pptp_gre.c:414]: buffering packet 5 (expecting 4, lost or reordered)
Jul 6 20:49:14 dev pppd[1]: CHAP authentication succeeded
Jul 6 20:49:14 dev pppd[1]: MPPE 128-bit stateless compression enabled
Jul 6 20:49:14 dev pppd[1]: local IP address
Jul 6 20:49:14 dev pppd[1]: remote IP address

So we have this vpn enabled now but how do we use it?One way to make us totally anonymous would be to simply set our local gateway default to ppp0 as opposed to eth1 e.g

sudo route add default gw GATEWAY-IP

But how can we dynamically get the GATEWAY IP assigned by our pptp connection? A little bit of awk and sed:-

sudo route add default gw `sudo ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'`

At this point ALL traffic from this PC would be routed via our VPN and ALL sitesand servers visitied would see the ip as your address andtherefore consider you "located" at the place where the IP was issued. The UK for the BBC, US for Fox News etc - depending on what VPN package you purchased.Up to this point you would be totally anaonymous. Well, anonymous enough! Dont think for a minute you can then go breaking laws and not get caught. The VPN companies WILL keep logs no matter what they claim. They will be able toassociate your real IP address with your "anonymous" one and therefore YOU ifpressed by the authorities!So how would we go about only routine certain traffic? e.g ONLY the traffic for the BBC web site iPlayer? Here comes the wonderful "route" command. e.g consider this "uktv" script:-

sudo ifup ${3-uk1} >/dev/null 2>&1
sudo route ${1-add} -host gw `sudo ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` ${IFACE}>/dev/null 2>&1
sudo route ${1-add} -host gw `sudo ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` ${IFACE}>/dev/null 2>&1

This adds our new VPN as the gateway for all traffic for the two sites and Be aware of the laws of your country!It can be used to add and remove the gateway for these sites simply enough:


turns them on. Our routing table now looks like this:-

[5114]shamrock@development:/etc/ppp$ uktv
[5115]shamrock@development:/etc/ppp$ sudo route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface UGH 0 0 0 ppp0 UH 0 0 0 ppp0 UGH 0 0 0 eth1 UGH 0 0 0 ppp0 U 0 0 0 eth1 UG 0 0 0 eth1

I wont go into the details but its pretty obvious if you made it this far. "manroute". Or google is your friend!Notice the parameter substituion in bash to provide a default for argumen 1($1). We can close off the TV routes by simply typing "uktv del". So

%uktv del

removes the our new routes! Easy! But what about automatically turning them onwhen the interface ppp0 is turned on? Here we have the ip-up directories onDebian at least. Simply create the scripts you want running in/etc/ppp/ip-up.d. Here are some of mine:-

[5112]shamrock@development:/etc/ppp$ ls -l ip-up.d/
total 20
-rwxr-xr-x 1 shamrock shamrock 902 Jul 5 05:09 0000usepeerdns
-rwxr-xr-x 1 shamrock shamrock 293 Jul 5 05:09 00-exim4
-rwxr-xr-x 1 shamrock shamrock 53 Jul 6 19:05 01-vpnsetup
-rwxr-xr-x 1 shamrock shamrock 284 Jul 6 19:04 02-news
-rwxr-xr-x 1 shamrock shamrock 259 Jul 6 19:15 03-uktv

where 02-news, for another example, is :-

route add -host gw `ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` ${IFACE}
route add -host gw `ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` ${IFACE}

The 03-uktv script would be a symbolic link to my ~/bin/uktv script outlinedabove!And that pretty much wraps that up. Oh! No it doesnt … one thing that took me AGES to sort out was the MTU. You can google what that is. The MTU is veryfinicky for pptp it seems. I had to dial mine back to 1400 in order for the vpn connection to my vpn supplier worked. How did I do that? Easy : modify the MTUwhen you bring the interface up. Thats the 01-vpn-setup script above:-

ifconfig ${IFACE} mtu 1400

tada! Happy hiding!

My Emacs Files At GitHub

Go anonymous and back again ...

sudo ifup ${3-uk1} >/dev/null 2>&1
sudo route ${1-add} default gw `sudo ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` 2>&1

My Emacs Files At GitHub

Script to add remove uk proxy routes

sudo ifup ${3-uk1} >/dev/null 2>&1
sudo route ${1-add} -host gw `sudo ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` ${IFACE}>/dev/null 2>&1
sudo route ${1-add} -host gw `sudo ifconfig ${IFACE} | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'` ${IFACE}>/dev/null 2>&1

My Emacs Files At GitHub

peer provider for vpn

pty "pptp –nolaunchpppd"
remotename PPTP
file /etc/ppp/options.pptp
ipparam uk1

My Emacs Files At GitHub

Sunday, June 26, 2011

Freenode and the Trends for LitteMan Power Abuse.

IRC is a wonderful technical resource available, for free, to anyone who has the
competence to set up an IRC client. One can be awed by the knowledge, freely
given, by people who have accumulated this knowledge through years of hard graft
despite sub standard documentation and lack of "google". Its hard to think to
back to the olden days ( a few years ago) when the only help you had were your
office colleagues and the dog eared tech manual. But sometimes, even now, Google
isnt enough. You want to communicate with living Gurus. And thats where IRC
channels come in. Once a haven but more often than not now a lair for small
minded, power hungry big heads with an agenda of self promotion. I also have a
theory that the closer you get to web technologies then the bigger the idiots
and the lower the real world competence of the self proclaimed experts that
haunt these channels and bully any nOOb unlucky enough to wander their way
looking for help and encouragement is. Frankly I have had enough of them, and I
know from private /msg-s so have many others.

Lets look at a typical example. The other day I was googling around for cheap
Linux/PHP/Mysql/Apache hosting options. Its hard to sort the wheat from the
chaff. Often the php installed is out of date or only supports a subset of core
modules you might need. Maybe their uptime isnt good. Or their admin UI
sucks. There are many things to consider. Now, I want to find recommendations
from competent PHP programmers who deal with this stuff all the time. real
people.. So I ask in the freenode #PHP irc channel. The resident troll and OP
who wields the "naughty stick" goes under the nym "TML". I had heard of him
before from someone who was complaining in another channel about some
intransigent show off who was getting too big for his boots. My Q went like
this : "Could any of you with experiences of reliable PHP hosting packages
please MSG me privately". One line. Polite. To the point. A request for
help. Our resident uber-Op pipes up "This is off topic go elsewhere". I reply
"oh sorry, I didnt know that but I asked people to privately msg me so it wont
be too much of a burden on the channel". Or words to that affect. In the
meantime I got about 7 recommendations (privately) with most of them telling me
how pompous and self important TML is. Firstly lets look at why it should be off
topic : Because it might be deemed commercial offering? Nah. Because its not
PHP related? Nah - after all hosting is directly linked to the language versions
and modules supported. Is it because some jobsworth decided it? Probably. The
channel was quiet too. Also ALL channels have an element of camaraderie and off
topic meandering - the maturer channels and OPs who dont have their head up
their own arses acceptthat. But that aside, lets not lose sight of the issue
here. One line. Polite. Asking for private replies so as not to flood the main
language reply stream. The channel is full of experienced PHP programmers the
kind that can, and did, quickly help and provide someone with their
experience. It takes a real low IQ to suggest that you should go to something
like #php-hosting where there is one person who is probably insane.. The huge
majority of PHP is linked with web hosted apps/sites. I needed help and people
are supposedly there to help. So I asked why this was so terribly "off
topic". Our self important operator promptly reminded it was off topic again, no
reason, and that "we" (dont you love people who claim to represent everyone else
whether they like it or not) cant help. I suggested that if he was there to help
he could do so, otherwise why would he flood the channel with so many topic
unrelated edicts and orders? He banned me. Banned from a PHP channel for asking
a simple PHP related question. TML if you're reading this : keep some
perspective and apply SOME common sense. If someone KEEPS coming back and asking
the same OT things then consider a temporary ban. You do not ban someone for
suggesting you're a jumped up little jobsworth who's a bit too fond of the red
card - you should take a deep breath and wonder if maybe, just maybe, that
person is correct.

I am working on a PHP project. I needed some help/pointers. I decided (before
posting this btw) to contact TML, make peace and request the ban was lifted. I
pointed out to him that I am not going to beg but if the rules were so strict
then I wont go off topic again asking about hosting. He refused to lift the ban
because he felt my apology was not "sincere enough" and that I might reoffend!
What a sanctimonious, self righteous little man some might think!. Unfortunately
he has the "F" flag, as founder, and I have no more redress. Fine. Maybe #php
will be better off without someone like myself. In all truthfulness, I doubt
it. Still, I am sure he is more than happy in own little world where his word
makes nOObs shudder and perps shake.. Fear the Op! For 'tis all they have….

My Emacs Files At GitHub

Saturday, June 11, 2011

enabling gtags auto tag completion in Global compatible modes

(require 'gtags)
(defun gtags-root-dir ()
"Returns GTAGS root directory or nil if doesn't exist."
(if (zerop (call-process "global" nil t nil "-pr"))
(buffer-substring (point-min) (1- (point-max)))
(defun gtags-update ()
"Make GTAGS incremental update"
(message "updating GLOBAL tags using gtags -i ..")
(call-process "gtags" nil nil nil "-i -f gtags.files")

(defun gtags-update-global ()
"Make GTAGS incremental update"
(message "updating GLOBAL tags!!")
(call-process "global" nil nil nil "-u")

(defun gtags-update-hook ()
(when (gtags-root-dir)
(when (memq major-mode (list 'php-mode 'c-mode 'org-mode 'javascript-mode 'js-mode 'emacs-lisp-mode))
(progn (message "global root : %s" (gtags-root-dir))(gtags-update-global)))))
(add-hook 'after-save-hook 'gtags-update-hook)

(defadvice gtags-find-tag (before gtags-make-complete-list activate)
"Make Global completion tags" (unless gtags-complete-list (gtags-make-complete-list)))

(add-hook 'php-mode-hook '(lambda () (gtags-mode t)))
(add-hook 'c-mode-hook '(lambda () (gtags-mode t)))

(provide 'rgr-gtags)

My Emacs Files At GitHub

Saturday, April 16, 2011

Google Translate on an xmonad toggle

NS "translate" "chromium-browser --app=" (name =? "Google Translate") nonFloating,

,((modMask myConfig .|. shiftMask, xK_t),  namedScratchpadAction scratchpads 

This is great, now I hit Mod-shift t and a chromium "app" containing google
translate appears/disappears.

My Emacs Files At GitHub

Friday, April 15, 2011

Exim4 handling redirecting mails from your apache vhost an external email

The Problem

Consider the Apache vhost Someone sends an email to We want exim4 to spot that and use sendmail to send the mail to
the approved user. frequently that person might be sat behind gmail or something

The components

  • Everything is done via exim4 config with the addition of a new router and
    vhost specific alias files which contain the email mappings.

  • The text here assumes you have NOT split your configuration

  • All exim configuration is done using the exim4.conf.template file.

The solution

  • Edit /etc/exim4/exim4.conf.template.

  • Modify the local domains definition

    # List of domains considered local for exim. Domains not listed here
    # need to be deliverable remotely.
    domainlist local_domains = @:localhost:dsearch;/etc/exim4/virtualhosts

This tells exim which domain names are considered for for further processing.

  • Insert the following additional router code before systemalias handling (400):-

    ### router/350_exim4-config_vdom_aliases
    driver = redirect
    domains = dsearch;/etc/exim4/virtualhosts
    data = ${expand:${lookup{$local_part}lsearch*@{/etc/exim4/virtualhosts/$domain}}}
    pipe_transport = address_pipe
    file_transport = address_file
    ### end router/350_exim4-config_vdom_aliases

  • A cursory glance at the code suggests that /etc/exim4/virtualhosts will play a
    part. It does!

  • Create a file for each vhost you wish to redirect email for. From our example
    we create /etc/exim4/virtualhosts/ In it we place our email
    mappings. Here is an example:-


My Emacs Files At GitHub

Sunday, April 10, 2011

Emacs at work developing facebook friendly meta data in php....

Copy named files to remote host and recreate directories

A script to copy only certain file name from tree to remote host and recreate
the directory structure. Had thought scp -r or something would do it. or rsync
directly but well, the rsync manual leaves me cold for things like what to
include and what to exclude… It's probably a lot simpler than this of course ;(


if [ "${host}" = "" ]; then
echo "No destination host specified"
echo "Usage : copy-files HOSTNAME FILENAME DESTDIR"

if [ "${filename}" = "" ]; then
echo "No FILENAME specified"
echo "Usage : copy-files HOSTNAME FILENAME DESTDIR"

if [ "${destdir}" = "" ]; then
echo "No DESTDIR specified"
echo "Usage : copy-files HOSTNAME FILENAME DESTDIR"

find . -type f -iname "${filename}" 2> /dev/null | while read -r FILE
REMDESTDIR="~/${destdir}/`dirname ${FILE#./}`"
echo "Found : ${FILE} .. Attempting : rsync -avz ${FILE} ${host}:${REMDESTDIR}"
rsync -avz "${FILE}" "${host}:${REMDESTDIR}/"

My Emacs Files At GitHub

Wednesday, March 9, 2011

org-googlecl - blogging to through org-mode

Installing a new Asus 1015PEM netbook with Debian Squeeze recently I had to
reinstall the google command line utility, googlecl. My utility org-googlecl to
allow me to blog directly from org-mode entries was broken however.

Google command line utility

Reason? googlecl , somewhat surprisingly, does not automatically create its
~/.local/share/googlecl/ directory. Simply create it yourself and then
org-googlecl works as documented.

Blog directly to from Emacs (org-mode support)

As a side note, using the Liquorix kernel, the Asus works perfectly with
Debian : all the "usual suspects" work - suspend/resume, wireless and audio all
work. Initially post-resume I had to manually remove and re-modprobe the
brcm80211 driver but that now seems to be resolved. On the downside, battery
life is rubbish compared to running Win 7 Start Edition which it came with (dual
boot) but its still acceptable - but when you think I have this litle beauty
running apache2 and mysql it's still a great little portable machine.

My Emacs Files At GitHub

Tuesday, March 8, 2011

Emacs to edit a Chromium textarea

A nice Chromium alternatives to the FF extension "Its all text" is here :-

Why it needs edit-server.el I'm not 100% - I guess it uses something other than
the emacs daemon emacsclient call. But, it works nicely. I added the following
ot my and all seems well. I like the double click in a textarea
method to launch an emacs client windows to edit.

(if (and (daemonp) (locate-library "edit-server"))
(require 'edit-server)

(add-hook 'edit-server-text-mode-hook
(lambda ()(progn()

My Emacs Files At GitHub

Wednesday, February 9, 2011

xmonad.hs : Haskell XMonad config file.

The smartBorders layout manipulator is extra important for netbook screens!

~/.xmonad/xmonad.hs::{-# LANGUAGE ScopedTypeVariables #-}

{-# LANGUAGE ScopedTypeVariables #-}

-- xmonad.hs
-- Richard G. Riley <>
-- Thanks to the #xmonad chaps
-- on freednode IRC for help and advice.

import XMonad
import XMonad.Core

import Data.List

import qualified XMonad.StackSet as W

import Control.OldException
import Control.Monad
import DBus
import DBus.Connection
import DBus.Message

import XMonad.Actions.GridSelect
import XMonad.Actions.MouseResize
import XMonad.Actions.CycleWS
import XMonad.Actions.CycleWindows (rotFocusedUp, rotFocusedDown)
import XMonad.Actions.RotSlaves

import XMonad.Actions.PerWorkspaceKeys
import qualified XMonad.Actions.Submap as SM
import qualified XMonad.Actions.Search as S
import XMonad.Actions.WindowBringer
import XMonad.Actions.WindowGo
import qualified Data.Map as M
import XMonad.Config.Gnome
import XMonad.Hooks.DynamicLog
import XMonad.Hooks.FadeInactive
import XMonad.Hooks.ManageDocks
import XMonad.Hooks.ManageHelpers
import XMonad.Hooks.SetWMName
import XMonad.Layout.Circle
import XMonad.Layout.DragPane
import XMonad.Layout.IM
import XMonad.Layout.Grid
import XMonad.Layout.NoBorders
-- import XMonad.Layout.Magnifier
import XMonad.Layout.PerWorkspace
import XMonad.Layout.Monitor
import XMonad.Layout.MultiToggle
import XMonad.Layout.MultiToggle.Instances
import XMonad.Layout.Reflect
import XMonad.Layout.SimpleFloat
import XMonad.Layout.WindowArranger
import XMonad.Prompt
import XMonad.Prompt.AppLauncher as AL
import XMonad.Prompt.Shell
import XMonad.Prompt.Ssh
import XMonad.Util.Run
import qualified XMonad.StackSet as Window
import XMonad.Util.EZConfig(additionalKeys)
import XMonad.Util.Scratchpad
import XMonad.Util.NamedScratchpad

import System.Posix.Unistd (getSystemID, nodeName)
import System.Environment (getEnvironment)

-- import Graphics.X11.Xlib

myWorkSpaces = ["1", "2:TV" ,"3","4","5","6","7:Eclipse","8:Gimp"]
myManageHook = composeAll . concat $
[fmap(i `isPrefixOf`) resource --> doIgnore | i <- myIgnores]
,[fmap(f `isPrefixOf`) resource --> doCenterFloat | f <- myFloats]
className =? "Gimp" --> doShift "8:Gimp"
, className =? "SDL_App" --> doShift "6:Android"
, className =? "screenkey" --> doShift "6:Android"
, className =? "MPlayer" --> doShift "2:TV"
,isDialog --> doCenterFloat
,isFullscreen --> doFullFloat

myFloats = ["gimmix","Gnome-system-monitor","Vncviewer", "Steam", "xvidcap", "Xvidcap", "recordMyDesktop","screensaver","gnome-panel","ktorrent","Ddd","GPicker","gpicker", "barrybackup","pinentry-gtk-2","recordMyDesktop","xsane"]
myIgnores = ["gworldclock","ddd", "bsh-Interpreter","Do","gnubiff"]
role = stringProperty "WM_WINDOW_ROLE"

myLayout = smartBorders(
onWorkspace "8:Gimp" (withIM 0.11 (Role "gimp-toolbox") $ reflectHoriz $ withIM 0.15 (Role "gimp-dock") Full) $
onWorkspace "2:TV" (smartBorders $ avoidStruts Full ) $
avoidStruts $ mouseResize $ windowArrange $ smartBorders $ mkToggle (single REFLECTY) $ mkToggle (single REFLECTX) $ mkToggle (single MIRROR) $ mkToggle(FULL??EOT) (Tall 1 (3/100) (1/2) ||| dragPane Horizontal 0.1 0.5||| Grid ||| Circle ))

myFocusFollowsMouse :: Bool
myFocusFollowsMouse = False

myTerminal = "~/bin/myterm"
myToggleTerminal = "~/bin/mytoggleterm"

myFadeLogHook :: X ()
myFadeLogHook = fadeInactiveLogHook fadeAmount
where fadeAmount = 0xaaaaaaaa

scratchpads = [

-- run htop in xterm, find it by title, use default floating window placement

-- NS "google-chrome" "google-chrome" (className =? "Google-chrome") nonFloating ,
-- NS "browser" "conkeror" (className =? "Conkeror") nonFloating ,
NS "chrome" "chromium-browser --new-window" (className =? "Chromium-browser") nonFloating ,
NS "iceweasel" "iceweasel" (className =? "Iceweasel") nonFloating ,
NS "facebook" "google-chrome --app=\"\" --new-window --class=\"facebook\"" (className =? "facebook") nonFloating ,
NS "evince" "evince" (className =? "evince") nonFloating ,
-- NS "yoono" "yoono" (name =? "Yoono") defaultFloating ,
NS "surf" "surf" (className =? "surf") nonFloating ,
NS "emacs" "edit -c" (className =? "Emacs") nonFloating,
NS "unison" "unison-gtk" (className =? "unison-gtk") nonFloating ,
NS "htop" "xterm -name htop -e htop" (title =? "htop")
(customFloating $ W.RationalRect (1/3) (1/8) (2/3) (1/2)) ,
NS "newsbeuter" "xterm -e myrss" (title =? "myrss")
(customFloating $ W.RationalRect (1/2) 0 (1/2) (1/4))

] where name = stringProperty "WM_NAME"

isLightHost :: String -> Bool
isLightHost = (`elem` ["X30","PUB","Hermes"])

-- This retry is really awkward, but sometimes DBus won't let us get our
-- name unless we retry a couple times.
getWellKnownName :: Connection -> IO ()
getWellKnownName dbus = tryGetName `catchDyn` (\ (DBus.Error _ _) ->
getWellKnownName dbus)
tryGetName = do
namereq <- newMethodCall serviceDBus pathDBus interfaceDBus "RequestName"
addArgs namereq [String "org.xmonad.Log", Word32 5]
sendWithReplyAndBlock dbus namereq 0
return ()

main = withConnection Session $ \ dbus -> do

putStrLn "Getting well-known name."
getWellKnownName dbus
putStrLn "Got name, starting XMonad."

host <- fmap nodeName getSystemID

xmonad myConfig
{ logHook = dynamicLogWithPP defaultPP {
ppOutput = \ str -> do
let str' = "<span font=\"Terminus 9 Bold\">" ++ str ++
str'' = sanitize str'
msg <- newSignal "/org/xmonad/Log" "org.xmonad.Log"
addArgs msg [String str'']
-- If the send fails, ignore it.
send dbus msg 0 `catchDyn`
(\ (DBus.Error _name _msg) ->
return 0)
return ()
, ppTitle = pangoColor "#003366" . shorten 50
, ppCurrent = pangoColor "#006666" . wrap "[" "]"
, ppVisible = pangoColor "#663366" . wrap "(" ")"
, ppHidden = wrap " " " "
, ppUrgent = pangoColor "red"
} >> myFadeLogHook


myConfig = gnomeConfig {
manageHook = namedScratchpadManageHook scratchpads <+> manageDocks <+> myManageHook
,layoutHook = myLayout
, startupHook = startupHook gnomeConfig >> setWMName "LG3D"
, workspaces= myWorkSpaces
, modMask = mod4Mask
, focusFollowsMouse = False
, terminal = myTerminal
} `additionalKeys` [
-- scrot is a nicely configurable screen shot utility
((0, xK_Print), spawn "scrot -s -d 5 -q50 'shot-%Y%m%d-%H.%M.%S.png' -e 'mv $f ~/tmp/' && nautilus ~/tmp")
,((modMask myConfig .|. controlMask, xK_p ), spawn "sleep 0.2;scrot -d5 -q50 -s 'shot-%Y%m%d-%H.%M.%S.png' -e 'eog $f'")
,((modMask myConfig, xK_b), bringMenu)
,((modMask myConfig.|. shiftMask, xK_g), goToSelected defaultGSConfig)

,((modMask myConfig, xK_s), SM.submap $ searchEngineMap $ S.promptSearchBrowser defaultXPConfig "chromium-browser")
,((modMask myConfig, xK_g), S.promptSearch greenXPConfig

,((modMask myConfig, xK_p), shellPrompt defaultXPConfig)

, ((modMask myConfig , xK_F1), AL.launchApp defaultXPConfig "gnome-terminal -x info " )
-- ,((modMask myConfig , xK_F1), manPrompt defaultXPConfig)

,((modMask myConfig .|. shiftMask, xK_o), spawn "ooffice -calc")
,((mod3Mask, xK_space), spawn "gnome-do")
,((modMask myConfig .|. shiftMask, xK_n), spawn "nautilus /home/shamrock")
,((modMask myConfig , xK_v), spawn "conkeror -f unfocus")
,((modMask myConfig .|. shiftMask, xK_c), namedScratchpadAction scratchpads "chrome")
,((modMask myConfig .|. shiftMask, xK_f), namedScratchpadAction scratchpads "facebook")
,((modMask myConfig .|. shiftMask, xK_i), namedScratchpadAction scratchpads "iceweasel")
,((modMask myConfig .|. shiftMask, xK_p), namedScratchpadAction scratchpads "htop")
,((modMask myConfig .|. shiftMask, xK_m), spawn "ssh hermes xterm -e htop")
,((modMask myConfig .|. shiftMask, xK_e), namedScratchpadAction scratchpads "emacs")
,((modMask myConfig .|. shiftMask, xK_d), namedScratchpadAction scratchpads "evince")
-- ,((modMask myConfig .|. shiftMask, xK_y), namedScratchpadAction scratchpads "yoono")

,((modMask myConfig .|. controlMask, xK_x), spawn "gxmessage -wrap -bg black -fg green `xprop | grep WM_`") -- query X resources

,((modMask myConfig .|. shiftMask, xK_t), scratchpadSpawnActionCustom myToggleTerminal)

-- ,((modMask myConfig .|. shiftMask, xK_t), scratchpadSpawnActionCustom "gnome-terminal --disable-factory --name scratchpad")

,((modMask myConfig .|. shiftMask, xK_h), sshPrompt defaultXPConfig)

-- workspace management

,((modMask myConfig, xK_Down), nextWS)
,((modMask myConfig, xK_j), rotSlavesDown)
,((modMask myConfig, xK_k), rotSlavesUp)
,((modMask myConfig, xK_u), rotFocusedDown)
,((modMask myConfig, xK_i), rotFocusedUp)
,((modMask myConfig, xK_Up), prevWS)
,((modMask myConfig .|. controlMask, xK_Up), shiftToNext)
,((modMask myConfig .|. controlMask, xK_Down), shiftToPrev)
,((modMask myConfig, xK_Right), nextScreen)
,((modMask myConfig, xK_Left), prevScreen)
,((modMask myConfig .|. controlMask, xK_Right), shiftNextScreen)
,((modMask myConfig .|. controlMask, xK_Left), shiftPrevScreen)
,((modMask myConfig .|. controlMask, xK_z), toggleWS)
,((modMask myConfig ,xK_x), sendMessage $ Toggle MIRROR)
,((modMask myConfig ,xK_f), sendMessage $ Toggle FULL)
,((modMask myConfig ,xK_y), sendMessage $ Toggle REFLECTX)
,((modMask myConfig ,xK_b), sendMessage(ToggleStruts))
-- ,((modMask myConfig, xK_x), sendMessage (Toggle "Circle"))

-- session management
,((modMask myConfig .|. controlMask, xK_f), withFocused float)
,((modMask myConfig .|. controlMask, xK_Delete), spawn "xkill")
,((modMask myConfig .|. shiftMask, xK_Delete), kill)
,((modMask myConfig .|. controlMask, xK_t), spawn "~/bin/myrootterm") -- root terminal
,((modMask myConfig .|. controlMask, xK_s), spawn "gksu poweroff")
,((modMask myConfig .|. controlMask, xK_r), spawn "gksu reboot")
,((modMask myConfig .|. controlMask, xK_l ), spawn "gnome-screensaver-command --lock")
,((modMask myConfig .|. controlMask, xK_v), spawn "gnome-volume-control")
,((modMask myConfig .|. controlMask, xK_o), spawn "sleep 0.5; xset dpms force off")

-- , ((modMask myConfig .|. shiftMask, xK_space), layoutScreens 2 (TwoPane 0.5 0.5))
-- , ((modMask myConfig .|. controlMask .|. shiftMask, xK_space), rescreen)

-- multi monitor stuff
,((modMask myConfig .|. controlMask, xK_1), spawn "xrandr -s 0")
,((modMask myConfig .|. controlMask, xK_2), spawn "xrandr -s 1")
,((modMask myConfig .|. controlMask, xK_3), spawn "xrandr -s 2")


searchEngineMap method = M.fromList
[((0, xK_g), method
,((0, xK_H), method S.hoogle)
,((0, xK_w), method S.wikipedia)
,((0, xK_i), method
,((0, xK_a), method
,((0, xK_m), method S.maps)
,((0, xK_y), method
,((0, xK_h), method hayoo)
hayoo = S.searchEngine "Hayoo" ""

pangoColor :: String -> String -> String
pangoColor fg = wrap left right
left = "<span foreground=\"" ++ fg ++ "\">"
right = "</span>"

sanitize :: String -> String
sanitize [] = []
sanitize (x:rest) | fromEnum x > 127 = "&#" ++ show (fromEnum x) ++ "; " ++
sanitize rest
| otherwise = x : sanitize rest

My Emacs Files At GitHub

Sunday, February 6, 2011

rsync and retain root/other_user attributes


# add the following line to /etc/sudoers in the remote system
# username ALL = NOPASSWD: /usr/bin/rsync
for myhost in asus dev x30 t60
ping -c 1 "$myhost" > /dev/null
if [ "$?" -eq 0 ] ; then
echo "$myhost up"
sudo rsync -Pha --delete --rsync-path="sudo rsync" --ignore-errors ~/common-files $USER@$myhost:
echo "$myhost down"

My Emacs Files At GitHub

Wednesday, February 2, 2011

Securing your private email credentials using Gnus and EPA/EPG

(first draft)

Securing Your Gnus Information. rgr Feb 1st, 2010.

Possibly you wish your gnus email/nntp access configuration to remain
"secretive". This can be a problem when its more and more popular to use
online repos for inter machine sync (e.g using github to hold your emacs
config files). It can be easy to accidentally open the repo or make a
mistake with the file permissions. Or you might even lose your laptop!
Emacs integration with Epa/gnupgp make securing this a doddle. The more
traditional .authinfo file used to mean storing your password in
plaintext : something many people dont like to do. One option is to
merely resave the .authinfo as .authinfo.gpg. emacs/Gnupg will prompt
you for a signing key and away you go. epa/epg usage is covered
elsewhere in the emacs manual. Dont forget to remove the original
.authinfo.. Configure your auth-sources and Emacs will detect the .gpg
as a default if it exists. The usage and format of authinfo is discussed
in the emacs/gnus manuals. My setting is

(setq auth-sources (quote ((:source "/home/me/.emacs.d/.authinfo.gpg"
:host t :protocol t))))

We can extend this to storing the more secretive part of your Gnus
online life (and any other emacs subset) in a .gpg file.

Lets create a file "my-config.gpg". Line 1 tells emacs which key to use
and that it contains elisp :-

;; -*- mode:emacs-lisp -*- epa-file-encrypt-to: ("86E37324********") -*-

In it you can store private information such as a your erc password and gnus posting styles maybe:-

(setq erc-password "123456")

(add-to-list `gnus-posting-styles `( ,(rx(or "INBOX.trolling" ""))
(from "Tommy <>")
(name "Tommy Troll"))t)

(add-to-list `gnus-posting-styles `(,(rx(or "serious"))
(name "Serious")(address "")
(from "Simon Serious<>")
(eval (setq mml2015-signers '("12349876")))
(organization "")

(signature-file "~/.emacs.d/.sigs/serious.sig")) t)
(provide 'my-config)

The loading of this file would cause emacs or the system to prompt you
for a password to decrypt the file if the agent (gpg-agent) or emacs
hasnt already cached the password for that key. This prompt can be an
issue if you're using the emacs daemon especially if starting the
process at system login. When to prompt? One nice way is to only load
the gpg file when you create an emacs frame. e.g

(defun load-secure-config(frame)
(require 'my-config "my-config.gpg"))

(add-hook 'after-make-frame-functions 'load-secure-config)

Here we see that the private configuration information is only loaded and
decrypted when you actually bring up an emacs frame - generally that
would be sufficient in the case of gnus.

My Emacs Files At GitHub

Monday, January 31, 2011

Using rsync to synchronise different machines over ssh

# January 2011 : rsync to various machines.
# author :
# The LOCALHOST machine should have itself in the
# /etc/hosts files as something lile 1.1.1 so that
# the ping fails : basically a check to see if the
# destination host is available.
for myhost in asus dev x30 t60
ping -c 1 "$myhost" > /dev/null
if [ "$?" -eq 0 ] ; then
echo "$myhost up"
rsync -avz --delete ~/common-files $myhost:
echo "$myhost down"

My Emacs Files At GitHub

Tuesday, January 25, 2011

Installed the Liquorix kernel on my Asus 1015 PEM

What a kerfuffle…

Opted for the power saving, more responsive Liquorix Debian kernel. The install
went pretty painlessly courtesy of the smxi installers. But it wont work with
the network-manager on wireless since killing X kills the networking connection
too. Daft. So be prepared with an ethernet cable. So, great. I reboot and:-

> uname -a
Linux 2.6.32-5-686 #1 SMP Wed Aug 25 14:28:12 UTC 2010 i686 GNU/Linux

WOOt! But wait! Whats this? No wireless. Oh yes, thats right : the weird and
wacky world of Debian politics means I need to run the module assistant to
install the sources and build the driver for the bcm43q13 wireless device. God
forbid they should forget all that and just have something that works out of the
box and actually attract new users. Oh no. So m-a is used once more. Except it
crashes out. What do do? A quick google revealed the wonderul linux wireless
website which maintains up to date repos of all wireless SW. Well, most. Should
be simple!

Have a read and decide that the brcm80211 driver should suffice. great! So
install the debian firmware-brcm80211 using aptitude.

sudo aptitude install firmware-brcm802011

Now follow the linux wireless instructions. Cant be too hard… and it wasn't!

Download the latest code. Unarchive to my usual build tree. Now its time for the
money shot.

./scripts/driver-select brcm80211
make && sudo make install

Crikey! It compiled. Now remove any existing driver and install the new one:-

sudo modprobe -r brcm80211
sudo modprobe -r wl
sudo modprobe brcm80211

All this was done over an ssh link from my main development machine to my Asus
netbook via ethernet cable btw. So lets try this driver .. oh no. Lets not. The
famous Linux BSOD….. Black Screen Of Death…

!(sdu->cloned) failed : file wlc_mac80211.c line 5140

Quickly subscribing to the mail list for linux-wireless
( I had the solution .. remove the offending
line and remake!

Bingo! It works.

And that ladies and gentleman was my day….

My Emacs Files At GitHub