Bloerg
       

Vim’s builtin tag integration is an incredibly easy way to jump from one source location to the definition of a function or class using Ctrl+]1 and Ctrl+t. To generate the tags file, I used to map the following command to <Leader>gt

:!ctags -R -f .tags --sort=yes --exclude=build --exclude=_build

As you probably can imagine, such command line will never cover all corner cases of files that need to be ex- or included. However, Git already knows about which files I’d like to ignore, so I now just feed the list of files already versioned to ctags which I map like this:

:!git ls-tree -r --name-only $(git rev-parse --abbrev-ref HEAD)  ctags -f .tags --sort=yes -L -

To open and close the whole folds of target destinations prior and after the jumps, I use the following functions and maps:

function TagJumpForward()
    execute "tag " . expand("<cword>")
    try | foldopen! | catch | | endtry
endfunction

function TagJumpBack()
    try | foldclose! | catch | | endtry
    pop
endfunction

nnoremap <silent> <C-i> :call TagJumpForward()<CR>
nnoremap <silent> <C-t> :call TagJumpBack()<CR>

Finally, if you use CtrlP for buffer and file navigation, you should enable the tag support and map the launcher, for example to Ctrl+B

let g:ctrlp_extensions = ['tag']
nnoremap <C-b> :CtrlPTag<CR>

That reduces navigations like <C-p>foo_file_c<CR>/bar_func n n n to <C-b>bar_func.

  1. Ctrl+] is pretty hard to reach on a German keyboard layout, so I mapped that to Ctrl+i.

A lot has been written about Keybase.io, a public directory of public encryption keys associated with usernames and additional “verification proofs”. Yesterday, I was admitted to the circle of alpha testers and could grab the keybase.io/matze user name. Despite some initial problems, the website itself works just fine. Using the keybase client turned out to be a dead end though. It requires a fairly recent NodeJS and npm which are both not packaged for my long-term choice of Linux distribution. Thus, right now, the service offered to me is quite limited, because I am also not willing to upload my client-encrypted key.


I have four invites left, so if you are interested in trying that service, just drop me a line. And yes, I have a Twitter account for five years now, but this is and (probably will) be the last occasion that I use it.

To analyze the run-time behaviour of an application, a common technique is to record traces of code execution by inserting statements like these:

start_trace ("foo");
do_foo ();
end_trace ("foo");

This is an effective way to analyze concurrent applications that are usually difficult to reason about. If the IDE1 does not support it, visualizing this kind of data can be tricky. Fortunately, the Chrome browser exposes its internal trace viewer via a generic JSON format interface. All you have to do is generate the appropriate data and load it in the about:tracing page:

2014-04-07/vis.png

Here is a very simple way how you could trace the execution of Python code without interspersing your code like stupid:

import os
import time
import threading
import functools
import json


class Manager(object):

    _START_CLOCK = time.time()

    def __init__(self):
        self._events = []
        self._pid = os.getpid()

    def _new_event(self, func, event):
        tid = threading.current_thread().ident
        timestamp = (time.time() - self._START_CLOCK) * 1000 * 1000
        self._events.append(dict(name=func.__name__,
                                 cat='f', ph=event,
                                 ts=timestamp,
                                 tid=tid, pid=self._pid))

    def trace(self, func):
        @functools.wraps(func)
        def record(*args, **kwargs):
            self._new_event(func, 'B')
            func(*args, **kwargs)
            self._new_event(func, 'E')

        return record

    def __del__(self):
      with open('trace.json', 'w') as fp:
          json.dump(dict(traceEvents=self._events), fp)

The Manager records all events for functions that are decorated with the trace decorator, nothing fancy here. The distinction between the thread id tid and the process id pid stems from the fact that Chrome has a multi-process architecture, but you can of course use these fields in any way you like. Just remember that events from the same thread id are layed out in the same row and therefore need correctly ordered time stamps. Note that I also didn’t took special care for the category field, i.e. just set it to “f”. In the Managers destructor2 I just dump the events in the correct format.

The following test program demonstrates how to use the Manager and was used to made the top image:

m = Manager()

@m.trace
def foo(t):
    print 'going to sleep for {} seconds'.format(t)
    time.sleep(t)

threads = []

for i in range(25):
    thread = threading.Thread(target=foo, args=(random.random() * 0.25,))
    thread.start()
    threads.append(thread)
    time.sleep(random.random() * 0.025)

for thread in threads:
    thread.join()

So, now stop wasting your time guessing the run-time behaviour of your application and measure it!

  1. As far as I know, Eclipse has a mode to show thread execution.

  2. This pattern is typically frowned upon by seasoned Python hackers but once in a while it can be of a good use.

Literate programming is a programming paradigm that intermingles natural language comments with short snippets of source code from which then both compiled code and documentation can be generated. Knuth’s TeX is probably the most famous project written in a literate programming style.

Although, I am not a big fan of literate programming myself, I appreciate the general idea of interweaving natural language with code snippets. For example, I am always intrigued by explorative documents for research, in which you develop an idea in words and code. IPython notebooks come pretty close, but they are not what I would call plain text.

I was then looking for alternatives that mix and match Markdown with Python code and output static Markdown or HTML. I found Stijn Debrouwere’s python-literate, but it is too focused too much on the literate programming part and tries to invent basically anything from scratch.

So, I sat down and wrote a tiny script called pyl that does exactly one job, execute Python code and output results. It uses Pandoc to parse Markdown1 into Pandoc’s JSON syntax tree representation, traverses the tree, executes all code blocks within Python and replaces inline code with defined variables. It then outputs the altered syntax tree from which a second Pandoc instance can generate the final output in any desired target format.

With that 30-odd line long Python script, you can turn

Here is some Python code

    x = 2 * 3 + 4
    z = 'A fine string'

Now, is `x` = 10? and `z` a fine string?

into this

Here is some Python code

    x = 2 * 3 + 4
    z = 'A fine string'

Now, is 10 = 10? and A fine string a fine string?

Because there are no restrictions, you can do all kinds of crazy and potentially dangerous things. Just have a look at the example gallery.

Again, one word of warning: pyl executes arbitrary code in a non-sandboxed Python environment. This gives a lot of opportunities but can be a major security problem if building documents from untrusted sources.

  1. Actually anything that Pandoc can parse should work with pyl, but I haven’t checked that yet.