Below are the five most recent posts in my weblog. You can also see a chronological list of all posts, dating back to 1999.

Chemical Brothers — Out Of Control (21 Minutes of Madness remix)
Copy 1143 of 1999

Chemical Brothers — Out Of Control (21 Minutes of Madness remix) Copy 1143 of 1999

Also known as The Secret Psychedelic Mix. I picked this up last year. It was issued to promote the 20th anniversary re-issue of the parent album "Surrender". I remember liking this song back when it came out. At that time I didn't know who the guest singer was — Bernard Sumner — and if I had it wouldn't mean anything to me.

This is a pretty good mix. There's nothing "extra" in the mix, really, it's the same elements as the original 7 minute version, for 21 minutes this time, with perhaps some more production elements (more dubby stuff) but it doesn't seem to overstay its welcome.

Tags:

Primal Scream — Come Together

This one rarely returns to its proper place, instead living in the small pile of records permanently next to my turntable. I'm a late convert to Primal Scream: I first heard the 10 minute Andrew Weatherall mix of Come Together on Tom Robinson's 6Music show. It's a remarkable record, more so to think that it's quite hard, in isolation, to actually hear Primal Scream's contribution. This is very much Weatherall's track, and (to me, at least) it does a great job of encapsulating the house music explosion of the time.

It's interesting to hear Terry Farley's mix, partially because the band's contribution is more evident, so you can get a glimpse of the material that Weatherall had to work with.

RIP Andrew Weatherall, 1963-2020.

Tags:

When I did the work described earlier in template haskell, I also explored generic programming in Haskell to solve a particular problem. StrIoT is a program generator: it outputs source code, which may depend upon other modules, which need to be imported via declarations at the top of the source code files.

The data structure that StrIoT manipulates contains information about what modules are loaded to resolve the names that have been used in the input code, so we can walk that structure to automatically derive an import list. The generic programming tools I used for this are from Scrap Your Boilerplate (SYB), a module written to complement a paper of the same name. In this code snippet, everything and mkQ are from SYB:

extractNames :: Data a => a -> [Name]
extractNames = everything (++) (\a -> mkQ [] f a)
     where f = (:[])

The input must be any type which implements typeclass Data, as must all its members (and their members etc.): This holds for the Template Haskell Exp types. The output is a normal list of Names. The utility function has a more specific type Name -> [Name]. This is all that's needed to walk over the heterogeneous data structures and do something specific (f) when we encounter a Name.

Post-processing the Names to get a list of modules is simple

 nub . catMaybes . map nameModule . concatMap extractNames

Unfortunately, there's a weird GHC behaviour relating to the module names for some Prelude functions that makes the above less useful in practice. For example, the Prelude function words :: String -> [String] can normally be used without an explicit import (since it's a Prelude function). However, once round-tripped through a Name, it becomes GHC.OldList.words. Attempting to import GHC.OldList fails in some contexts, because it's a hidden module or package. I've been meaning to investigate further and, if necessary, file a GHC bug about this.

For this reason I've scrapped all the above and gone with a different plan. We go back to requiring the user to specify their required import list explicitly. We then walk over the Exp data type prior to code generation and decanonicalize all the Names. I also use generic programming/SYB to do this:

unQualifyNames :: Exp -> Exp
unQualifyNames = everywhere (\a -> mkT f a)
     where f :: Name -> Name
           f n = if n == '(.)
            then mkName "."
            else (mkName . last . splitOn "." . pprint) n

I've had to special-case composition (.) since that code-point is also used as the delimiter between package, module and function. Otherwise this looks very similar to the earlier function, except using everywhere and mkT (make transformation) instead of everything and mkQ (make query).

Tags:

At the start of the year I begun keeping a daily diary for work as a simple text file. I've used various other approaches for this over the years, including many paper diaries and more complex digital systems. One great advantage of the one-page text file was it made assembling my weekly status report email very quick, nearly just a series of copies and pastes. But of course there are drawbacks and room for improvement.

vimwiki is a personal wiki plugin for the vim and neovim editors. I've tried to look at it before, years ago, but I found it too invasive, changing key bindings and display settings for any use of vim, and I use vim a lot.

I decided to give it another look. The trigger was actually something completely unrelated: Steve Losh's blog post "Coming Home to vim". I've been using vim for around 17 years but I still learned some new things from that blog post. In particular, I've never bothered to Use The Leader for user-specific shortcuts.

The Leader, to me, feels like a namespace that plugins should not touch: it's like the /usr/local of shortcut keys, a space for the local user only. Vimwiki's default bindings include several incorporating the Leader. Of course since I didn't use the leader, those weren't the ones that bothered me: It turns out I regularly use carriage return and backspace for moving the cursor around in normal mode, and Vimwiki steals both of those. It also truncates the display of (what it thinks are) URIs. It turns out I really prefer to see exactly what's in the file I'm editing. I haven't used vim folds since I first switched to it, despite them being why I switched.

Disabling all the default bindings and URI concealing stuff and Vimwiki is now much less invasive and I can explore its features at my own pace:

let g:vimwiki_key_mappings = { 'all_maps': 0, }
let g:vimwiki_conceallevel = 0
let g:vimwiki_url_maxsave = 0 

Followed by explicitly configuring the bindings I want. I'm letting it steal carriage return. And yes, I've used some Leader bindings after all.

nnoremap <leader>ww :VimwikiIndex<cr>
nnoremap <leader>wi :VimwikiDiaryIndex<cr>
nnoremap <leader>wd :VimwikiMakeDiaryNote<cr>

nnoremap <CR> :VimwikiFollowLink<cr>
nnoremap <Tab> :VimwikiNextLink<cr>
nnoremap <S-Tab> :VimwikiPrevLink<cr>
nnoremap <C-Down> :VimwikiDiaryNextDay<cr>
nnoremap <C-Up> :VimwikiDiaryPrevDay<cr>

,wd (my leader) now brings me straight to today's diary page, and I can create separate, non-diary pages for particular work items (e.g. a Ticket reference) that will span more than one day, and keep all the relevant stuff in one place.

Tags:

This is the tenth part in a series of blog posts. The previous post was Amiga floppy recovery project: what next?. The whole series is available here: Amiga.

Rotary encoder, OLED display and mount

Rotary encoder, OLED display and mount

I haven't made any substantive progress on my Amiga floppy recovery project for a while, but I felt like some retail therapy a few days ago so I bought a rotary encoder and OLED display for the Gotek floppy disk emulator along with a 3D-printed mount for them. I'm pleased with the results! The rather undescriptive "DSKA0001" in the picture is a result of my floppy image naming scheme: the display is capable of much more useful labels such as "Lemmings", "Deluxe Paint IV", etc.

The Gotek and all the new bits can now be moved inside the Amiga A500's chassis.

Tags:

Older posts are available on the all posts page.


Comments