-
Remap your Caps Lock
The following three paragraphs are an angry
Caps Lock
rant. Feel free to skip past it or join me by commenting below.I’ve had it with
Caps Lock
! How many times did I accidentally press it while hitting theA
key! How many times did I meanTab
orShift
! There is an obvious problem with theCaps Lock
placement, and there being only a millimeter of space to designate it from an adjacent key, it is quite difficult to notice when you accidentally press it.Pushing
Caps Lock
is more tolerable when typing, but while using keyboard controlled software it’s a real pain;vim
turns into a beeping ravaging nightmare,vimperator
messes up all your bookmarks… Same thing with websites supporting keyboard shortcuts.When was the last time I ever used
Caps Lock
? Over ten years ago, when I was playing a video game that usedCaps Lock
to switch between running and walking. Em… Seriously? Time to put an end this nonsense.Linux and Mac
Drop this into your
~/bin/capslockremap
, and don’t forget tochmod +x ~/bin/capslockremap
. Now run the script with root privileges (that’ll last you until the next restart).#!/bin/sh # This temporarily remaps the Caps Lock key to a Control key. # The keyboard will return to the previous settings after a # reboot. The Linux console and the X Window system each # handles keypresses separately, so each must be remapped # separately. First remap the X keyboard since this does not # require root access. # Remap the Caps Lock key to a Control key for # the X Window system. if type setxkbmap >/dev/null 2>&1; then fi # You have to be root to remap the console keyboard. if [ "$(id -u)" != "0" ]; then echo "This script is not running as root so" echo "the console Caps Lock cannot be remapped." echo "Perhaps you forgot to run this under sudo." echo "Note that this problem does not effect X." echo "This only effects the consoles running on" echo "Alt-f1 through Alt-f6." exit 2 fi # Remap the CapsLock key to a Control key for the console. (dumpkeys | grep keymaps; echo "keycode 58 = Control") | loadkeys
Windows
Download Sysinternals Ctrl2Cap v2.0, run it as Administrator with
install
flag:ctrl2cap.exe /install
.Source CapsLock Remap Howto - Noah.org.
-
Python doctests and decorators bug
Now, this as well might be a feature, but doctest strings are not being executed for decorated functions (at least in version 2.7). However, there is a workaround.
You need to decorate your functions with
functools.wraps
within a decorator to import docstrings into a decorator scope.#!/usr/bin/env python from functools import wraps def decorator(func): @wraps(func) def wrapper(): return func() return wrapper @decorator def foo(): """ >>> foo() False """ return True import doctest doctest.testmod()
Now you can see this test failing, where otherwise it would have been ignored:
********************************************************************** File "decorator.py", line 12, in __main__.foo Failed example: foo() Expected: False Got: True ********************************************************************** 1 items had failures: 1 of 1 in __main__.foo ***Test Failed*** 1 failures.
-
Python tests with doctest and unittest
When it comes to tests,
doctest
is a great simple module to write tests for your application. However it is pretty basic and does not have any extended features like, for example, centralized unit tests. If you have multiple modules with doctests (and you probably do) you most likely want to be able to run all doctests recursively from one place. That’s whereunittest
comes in.Let’s assume we store modules in the
lib/
directory:$ ls lib/ __init__.py bar.py foo.py
Here are the contents of
foo.py
andbar.py
respectfully:def foo(): """ >>> foo() False """ return False def bar(): """ >>> bar() True """ return True def baz(): """ >>> baz() False """ return False
Now, to run all tests we need a wrapper script. Let’s call it:
runtests.py
:#!/usr/bin/env python import unittest import doctest import os files = [] root_dir = 'lib/' for root, _, filenames in os.walk(root_dir): for filename in filenames: if filename == '__init__.py' or filename[-3:] != '.py': continue f = os.path.join(root, filename) f = f.replace('/', '.') f = f[:-3] files.append(f) suite = unittest.TestSuite() for module in files: suite.addTest(doctest.DocTestSuite(module)) unittest.TextTestRunner(verbosity=1).run(suite)
This approach invokes the
doctest.DocTestSuite
method, which converts doctests strings into unittest suites. Time to run our tests:$ chmod +x runtests.py $ ./runtests.py ... ---------------------------------------------------------------------- Ran 3 tests in 0.008s OK
And just to be sure that approach actually works, let’s make one of the tests fail:
$ ./runtests.py .F. ====================================================================== FAIL: baz (lib.bar) Doctest: lib.bar.baz ---------------------------------------------------------------------- Traceback (most recent call last): File "/usr/lib/python2.7/doctest.py", line 2201, in runTest raise self.failureException(self.format_failure(new.getvalue())) AssertionError: Failed doctest test for lib.bar.baz File "/home/rosipov/unitdoc/lib/bar.py", line 8, in baz ---------------------------------------------------------------------- File "/home/rosipov/unitdoc/lib/bar.py", line 10, in lib.bar.baz Failed example: baz() Expected: True Got: False ---------------------------------------------------------------------- Ran 3 tests in 0.009s FAILED (failures=1)
-
pygame.font not found
I had an issue with pygame not being able to find a dependency for the font module. After quite a time-consuming search the missing package name was
libsdl-ttf2.0-dev
.Hope this helps someone.
-
Use vimdiff as git mergetool
Using vimdiff as a git mergetool can be pretty confusing - multiple windows and little explanation. This is a short tutorial which explains basic usage, and what the LOCAL, BASE, and REMOTE keywords mean. This implies that you have at least a little bit of basic vim knowledge (how to move, save, and switch between split windows). If you don’t, there’s a short article for you: Using vim for writing code. Some basic understanding of git and branching is required as well, obviously.
Git config
Prior to doing anything, you need to know how to set vimdiff as a git mergetool. That being said:
git config merge.tool vimdiff git config merge.conflictstyle diff3 git config mergetool.prompt false
This will set git as the default merge tool, will display a common ancestor while merging, and will disable the prompt to open the vimdiff.
Creating merge conflict
Let’s create a test situation. You are free to skip this part or you can work along with the tutorial.
mkdir zoo cd zoo git init vi animals.txt
Let’s add some animals:
cat dog octopus octocat
Save the file.
git add animals.txt git commit -m "Initial commit" git branch octodog git checkout octodog vi animals.txt # let's change octopus to octodog git add animals.txt git commit -m "Replace octopus with an octodog" git checkout master vi animals.txt # let's change octopus to octoman git add animals.txt git commit -m "Replace octopus with an octoman" git merge octodog # merge octodog into master
That’s where we get a merge error:
Auto-merging animals.txt CONFLICT (content): Merge conflict in animals.txt Automatic merge failed; fix conflicts and then commit the result.
Resolving merge conflict with vimdiff
Let’s resolve the conflict:
git mergetool
This looks terrifying at first, but let me explain what is going on.
From left to right, top to the bottom:
LOCAL
– this is file from the current branchBASE
– common ancestor, how file looked before both changesREMOTE
– file you are merging into your branchMERGED
– merge result, this is what gets saved in the repoLet’s assume that we want to keep the “octodog” change (from REMOTE). For that, move to the MERGED file (
Ctrl + w, j
), move your cursor to a merge conflict area and then::diffget RE
This gets the corresponding change from REMOTE and puts it in MERGED file. You can also:
:diffg RE " get from REMOTE :diffg BA " get from BASE :diffg LO " get from LOCAL
Save the file and quit (a fast way to write and quit multiple files is
:wqa
).Run
git commit
and you are all set!If you’d like to get even better about using Vim, I wrote a book about it: Mastering Vim. I’m pretty proud of how it turned out, and I hope you like it too.