How to slugify text in Vim (properly)

Recently I had to write a lot attributes —titles and matching slugs (in the URL)— for a bunch of links for a simple Hungarian web page I was building. There were a lot of links. Since I was editing the HTML template and associated URL configuration in Vim, I figured I’d quickly run some macro to generate me slugs from the page titles, so that I wouldn’t have to do them one-by-one. It turned out none of the existing solutions did quite what was necessary so I developed my own solution (shown below), but first: What is a slug?

Define: slug

Slugifying is a step up from ascii-fication. If we take the latter to mean “removing all non-ASCII characters from a string” then slugifying simplifies it even more. The point of slugifying is to generate (usually from a link or post title) a string good for use as a URL, without the characters getting garbled up into non-human-readable URL-encoded rubbish like this:

Slugify%20text%20in%20Vim%2C%20for%20example%20%E1rv%EDzt%171r%151t%FCk%F6rf%FAr%F3g%E9p%0A

when what you really want is something like this:

slugify-text-in-vim-for-example-arvizturotukorfurogep

Existing solutions and the problem of OSX

I based my solution on xolox’s slug function from his str collection, but even more hardcore. His doesn’t handle accented characters well.

Mine shells out to iconv, like the Diacritic plugin does.

This doesn’t work so well on OSX because apparently its transliteration is rubbish, my workaround is to do a second pass and remove OSX’s garbage. I later found out that it’s because OSX uses the BSD libiconv which is much leaner and simpler and lighter than the GNU libc (this can be a good thing) but also apparently puts in much effort into transliterating strings in locales other than English. For example, if I convert a German word like “grün” to a German locale, I expect to get “groen”, and if I convert it to ASCII, which has no accented characters, then I expect grun, with no accents.

The iconv command on OSX would give you gr”un. IMO this is not useful in any language and it also doesn’t get me any closer to removing the accents to form slugs. A Hungarian example with a typical test word:

  • Árvíztűrőtükörfúrógép input text
  • ‘Arv’izt”ur”ot”uk”orf’ur’og’ep libiconv (OSX)
  • Arvizturotukorfurogep glibc (this is what I want)

The solution

Since I can’t expect this to work consistently on Mac and Linux and I myself often switch between both I decided to brute force it, use iconv and strip any left over apostrophes and quotes from the result to handle the OSX case:

command! Slugify call setline('.', join(split(tolower(substitute(iconv(getline('.'), 'utf8', 'ascii//TRANSLIT'), "[\"']", '', 'g')), '\W\+'), '-'))

Probably not the most elegant solution, but at least it works for me…. consistently.

Edit from the future: I have now used this so much that I’ve committed it to my vimrc.

Rooting Samsung Galaxy Mini

Samsung Galaxy Mini

Samsung Galaxy Mini

My wife’s phone (Samsung Galaxy Mini GT-S5570I) doesn’t get system updates any more, so I need to manually move Google’s updates into ROM to make space for regular apps. You need root privileges to do this, so I was following these instructions on the XDA Forum which almost work fine. You need to download and apply a file update.zip but the problem is the update script inside doesn’t include S5570I in the list of phone models it checks for, so the script aborts.

All you need to do is edit /META-INF/com/google/android/updater-script inside update.zip and include this phone model in the assertion list, for example, I duplicated lines 15 and 16 and just added an I to the end:

getprop("ro.product.device") == "GT-S5570" ||
getprop("ro.build.product") == "GT-S5570"  ||
getprop("ro.product.device") == "GT-S5570I" ||
getprop("ro.build.product") == "GT-S5570I"  ||

Everything works completely fine after that. Obviously this is not a general solution when rooting, you can’t just blindly add your own phone model into any update.zip not knowing what’s in it, but since this was from a post for specifically this model and it already had several very similar models listed, I thought it was worth the risk and it turned out just fine. Woop! 😎

grml zsh inPlaceMkdirs

I keep forgetting this, but it’s really useful when working in the command line so I’m writing it down now. I use the grml zsh configuration in my shell and it has several very good features; a cool one I’d use more often if I could remember the shortcut is “in-place mkdir”. The key sequence is:

Ctrl-X, Shift-M

That’s Ctrl and x, followed by an uppercase M.

Here’s an example use case: Imagine you’re writing a command to do something with a very long path, like moving a file deep into a source tree

mv File.java src/something/very/long/

except half-way in your realise some of the directories in that path don’t exist. No problem! Usually you’d have to cancel that command, create the missing directories and then type it again. Now you can just type Ctrl-X, Shift-M, the directories are created and you can just press enter to use them. Much less annoying! This can even work for different directories in the same command; move the cursor to the directory you need and zsh will create that one!

For other useful shortcuts, see the reference card.

Secured my site with Let’s Encrypt

You might notice if you browse this blog now, that it’s served over HTTPS. I’ve even added an Apache configuration to redirect plain HTTP requests to secure HTTPS and I’ve spent the last few days checking the pages for URLs including non-secure content and rewriting them to use HTTPS where possible, or otherwise removing them. You’ll also notice in the left-hand corner of the browser’s address bar, there’s a (hopefully familiar) little green lock which indicates:

  • your communication with the site is encrypted well
  • the authenticity of the site is verified by a trusted authority

Of those, the latter usually involves paying a trusted certificate authority a lot of money to verify and sign your site’s certificate so that browsers will mark it trusted. Security is important but this high cost often creates a barrier for small companies wanting to use https. Continue reading

Mathematical Range Summing

Immediately after the last post about summing a range of numbers, a talented friend of mine, Gábor, offered an even shorter, cleverer solution:

What I especially like about it is that instead of relying on esoteric JavaScript functions to do the job, it’s done with reasoning and plain maths, which makes it clearer and easier to read too.

The Maths.abs() call is only needed because in the original problem, the arguments could be in either order; the logic is still the same though, you just need to make sure the range is positive. In short, it’s (a+b) × (a-b+1) ÷ 2.

Sum All Numbers in a Range

A solution to Free Code Camp’s “Sum All Numbers in a Range” JavaScript challenge, in a Functional Programming style.

A friend of mine hosts meetups for the Free Code Camp, which describes itself as:

We’re an open source community of people who learn to code and help nonprofits.

He organises casual meetings in coffee shops to allow participants to work on their assignments in a nice environment and help each other. If you’re looking to learn programming I recommend finding a Free Code Camp group in your area.

Today I visited such a meeting and one of the Code Campers was working on a solution for one of the JavaScript problems in the Intermediate Algorithm Scripting section. The task was to write a function that takes an array of 2 numbers as an argument and returns the sum of all the numbers between them, including the 2 numbers themselves. For example, an input of [3, 1] should result in 6, because 1 + 2 + 3 = 6. As a hint, it’s recommended you read the documentation for Math.min(), Math.max() and Array.prototype.reduce(). Continue reading

Lean Poker

I had a lot of fun attending a Lean Poker event last weekend!

Me at Lean Poker

Me at Lean Poker

It’s a type of event where programmers get together, form teams and spend the day writing code competitively, to see who can write the best automated online-poker player. We don’t play for money but for pride, and the main aim is to practise writing beautiful code and lean principles. That said, given the time constraint of a single day, the focus is usually on Deliver as fast as possible and by the end I’m flurrying around to keep errors out of the code. We try to get quick feedback during the day (more on that later) but I thought I’d do a write up about the event to give people who haven’t attended one of these before an idea of what it’s like!

Continue reading

Switch Colours in the GIMP

GIMP Colour SwitcherAfter my previous discovery I thought surely there should also be an easy keyboard shortcut for swapping the foreground and background colours in the GIMP, even though it doesn’t seem to be documented anywhere. There is. Just press X.

Actually I think it would be useful if this was shown in the tooltip text when you hover over the colour switching button, like it does with the other tools. If you’re curious, here is a list of 74 keyboard shortcuts for the GIMP (including this one) that you might not have known otherwise. I think keyboard shortcuts are great for editing pictures because you can change tools (and now also swap colours) without moving your cursor away from where you’re drawing!

Automatically Pop Up Steam Key

Now that I’ve got steam, I get to be constantly pestered by e-mails sending me keys with which to identify that I am myself. To save a few steps in this annoying, repetitive process I wrote a tiny bash script which finds the key in an e-mail from steam and uses zenity to pop it up on my screen, then added a filter in Evolution Mail to mark these “steam verification” messages as read and pipe them to the pop-up script. This allows me to copy the key with a double-click and paste it into steam with a middle-click, without having to poke around in my mail client for the e-mail and the place where the key is mentioned in it.

In the hope that it saves someone else from this irksomeness, here’s the code for the script:

#/bin/bash

# Displays a pop-up showing a Steam activation key piped to it by a MUA.
# In the e-mail the steam key is wrapped in <h2> tags
# Author: Sion Le Roux <sinisterstuf@gmail.com>

# read e-mail from pipe
while read -r line; do
    # find <h2>
    buffer=$(echo $line | grep 'h2')
    if [[ ! -z $buffer ]]; then
        #strip surrounding <h2> tags
        steamkey=$(echo $buffer | sed -e 's/<\/\?h2>//g')
    fi
done

# display the steam code in a pop-up
zenity --info --title="Steam Key" \
    --window-icon="/usr/share/pixmaps/steam.png" \
    --text="<tt><big><b>$steamkey</b></big></tt>"

Packaged Tomboy add-ins for Arch Linux

The wiki-like note taking application, Tomboy, maintains a list of user-written add-ins on its website, almost none of which were available in the Arch Linux repositories. Recently I learnt how packages are created for Arch Linux and read up on the standards, so I ‘adopted’ an ownerless add-in package from the Arch Linux User Repository and packaged 6 more.

Finally, I created a meta-package called tomboy-extras which contains nothing but depends on all the working Tomboy add-ins (tested on my laptop) in the AUR, to easily install all add-ins at once. I created a gist on GitHub for each package’s build script and made a repository containing the meta-package’s PKGBUILD file and each gist as a git sub-module named after the package name. The README file in tomboy-extras’ git repository contains links to the gists for the add-ins’ PKGBUILDs so that they can be found easily.

So, if you would like to contribute to one of them, feel free to fork the relevant gist, or leave a comment there, and if you would like to contribute to tomboy-extras itself or have an add-in included, just fork tomboy-extras and send a pull request; I’ll probably be adding more add-ins to it myself already. Also, if you do use any of these packages, please give them a vote on AUR so that we can see how many people use them. If they’re popular, they may be included in the official repositories, who knows!