Skip to content
Browse files
add a post on my code::stats plugins
  • Loading branch information
dancek committed Apr 5, 2018
1 parent 717a2cd commit 5347fc0f6d1583c7d356ed08e7c004406d87b1c6
Showing with 52 additions and 0 deletions.
  1. +52 −0 content/post/
@@ -0,0 +1,52 @@
title: "Code::Stats plugins for Zsh and Vim"
date: 2018-04-05T14:30:34+03:00

*To get this blog started, I'm writing about some code I've put online. The most interesting are probably the two Code::Stats plugins I've created.*

[Code::Stats]( is a free service for collecting stats about writing code. It's a for-fun side project of a colleague. Basically the server exposes an API that receives character counts per language along with a timestamp. The data is gathered by editor plugins.

## [Zsh plugin for Code::Stats](

I thought it would be fun to see how much I type in the terminal, so I created a [Zsh]( plugin for that. It wraps some Zsh widgets to be able to capture keystrokes and sends them using a background [curl]( process after any process completes or the shell exits, throttled down to at most once every ten seconds.

The plugin reports Code::Stats XP as language *Terminal (Zsh)*.

## [Vim plugin for Code::Stats](

After I realized it's not too hard to write a plugin and knowing there was some demand for a Vim plugin, I asked the local Vim guru at work for some help to get started.

The Vim plugin was a bit difficult to get working realiably as I wanted to support all the platforms I humanly could:

- Both [Vim]( and [NeoVim](
- As old Vim versions as possible *(The limiting factor became support for the `InsertCharPre` event, needed for counting keystrokes: Vim 7.3.196)*
- All operating systems that could conceivably work (looking at you, Windows)
- Both Python 2 and Python 3

Plain Vimscript couldn't make HTTP requests so it was obvious a script language was needed, and probably Python has the broadest coverage of installations. I also wouldn't rely on async support as that would rule Vim 7.x out, so I needed to handle asynchonous behaviour by creating a background worker process using Python `multiprocessing`. Eventually I got the obvious glitches ironed out and made a release.

Afterwards I sprinkled some unit tests for the Python code and some end-to-end tests that run a mock server and a Vim instance. The end-to-end tests were surprisingly difficult to get working properly. I set up [Gitlab CI for the tests]( and even added (Python) coverage reporting so I get nice icons like this: ![Code coverage status icon for code-stats-vim](

Below is an animation I created for the Gitlab page. It's not perfect by any means but it should convey the idea.

![Animation of code-stats-vim](

## My thoughts

The plugins were a lot of fun to write, and I had to learn a lot of new stuff for both:

- **Zsh specifics**. I usually prefer POSIX-compatible shell scripts, but that wouldn't be idiomatic or good for performance.
- **Quality control for a shell script**. Basically ShellCheck running in Gitlab CI---maybe I should consider unit testing.
- **VimL** (and Python integration).
- **Robust `multiprocessing`**. Distributed systems are difficult to get right.
- **Releasing software for other people to use**. That means prioritizing usability both at install and run time, avoiding all the corner-case glitches that won't happen on my machine, writing good READMEs etc.


Both plugins are under the Code::Stats organization on Gitlab. Both have users beside myself (yay!).


I also [worked a bit on the Code::Stats core]( before creating these plugins. I did like Elixir and Phoenix, but I currently prefer to spend my spare time outside web development.

0 comments on commit 5347fc0

Please sign in to comment.