Browsing other people’s code is a necessity, especially in Haskell where one wants to understand how to tweak types presented by a package beyond its normal APIs. Or, for understanding the deep inner workings of a framework.
Luckily, we can employ our Emacs editor to our benefit when trying to browse through an installed Cabal repository.
First, we need to make sure hashtags is installed:
cabal install hasktags
Next, we use a bash script that creates an Emacs ETAGS file of all installed packages sources:
#!/bin/bash mkdir -r ~/.cabal/packages/src cd ~/.cabal/packages/src || exit -1 chmod a+w -R pkg rm -rf pkg mkdir pkg find .. -name \*.tar.gz | xargs -l1 tar -C pkg --wildcards \*.hs -zxf chmod a-w -R pkg ~/.cabal/bin/hasktags -e pkg
This script keeps an extracted copy of all sources, so we can tag and browse.
Next, we should tell Emacs to use that tag file whenever we load an Haskell source:
(add-hook 'haskell-mode-hook (lambda () (visit-tags-table "~/.cabal/packages/src/TAGS")))
Bonus: If you are uncomfortable using the regular functions for tag search (find-tag, find-tag-other-window), you can use the following function:
(defvar dax-tag-browsing-list '()) (defun dax-find-tag () "Find the next definition of the tag already specified, but in another window only if we have started browsing tags" (interactive) (let ((this (current-buffer))) (if (memql this dax-tag-browsing-list) (progn (find-tag (current-word)) (if (not (eq this (current-buffer))) (add-to-list 'dax-tag-browsing-list (current-buffer))) ) (save-selected-window (save-excursion (find-tag-other-window (current-word)) (setq dax-tag-browsing-list '()) (if (not (eq this (current-buffer))) (add-to-list 'dax-tag-browsing-list (current-buffer))) )) ) ) )
The two key properties that this function has when searching for tags:
- When you are editing your own code and looking up a tag, it will open up a new window in the current frame but keep the focus in the current one. Most likely you only needed to look at that other code and not edit it, so in that case hit ESC-ESC and resume working.
- In case you decided to browse deeper, switch to the other window. Now you can go own with the nested tag searching – further tag lookups replace the buffer in the new window, keeping your original editing window as it is.