9

From time to time I like to engage in a round of vimgolf. It can be enlightening.

How are they able to record all the keystrokes? That must be a vim feature. Anybody any idea how to do that. It could come in handy to record everything in certain circumstances.

  • I just found out that we have a pretty similar question here – statox Dec 6 '17 at 14:12
9

They probably use the built-in parameter -w, see :h -w:

-w {scriptout}  All the characters that you type are recorded in the file
        "scriptout", until you exit Vim.  This is useful if you want
        to create a script file to be used with "vim -s" or
        ":source!".  When the "scriptout" file already exists, new
        characters are appended.  See also |complex-repeat|.
        {scriptout} cannot start with a digit.
        {not in Vi}

Edit As @B Layer pointed out the actual code uses the -W parameter which is basically the same as -w but the log file is overwritten instead of appending the keystrokes to it (:h -W):

-W {scriptout}  Like -w, but do not append, overwrite an existing file.
        {not in Vi}
  • Good guess! It's -W not -w (see my answer) but still... – B Layer Dec 6 '17 at 12:38
  • @BLayer Well played I was too lazy to look at their code :-) I'll update with the doc for -W which is basically the same. – statox Dec 6 '17 at 12:40
  • 1
    Yep. Just append vs write. – B Layer Dec 6 '17 at 12:40
  • A (good) guess outvotes and gets accepted over a well-researched, fact-based answer? A grave injustice has been done. :( ... LOL – B Layer Dec 8 '17 at 19:46
  • 1
    'Tis a noble gesture. I humbly accept your vote, good sir or madam. Dilly dilly. – B Layer Dec 11 '17 at 20:40
14

I don't think it's quite that simple but you can look at the Ruby code yourself here:

https://github.com/igrigorik/vimgolf/tree/master/lib/vimgolf

I see a class for keylogging, for one.

Here's the command that is used to launch vim in lib/vimgolf/cli.rb:

 vimcmd = GOLFVIM.shellsplit + %W{-Z -n --noplugin --nofork -i NONE +0 
    -u #{challenge.vimrc_path} -U NONE -W #{challenge.log_path} #{challenge.work_path}}

@statox was (very nearly) right about -w outfile ... -W outfile, actually, which overwrites the file to which the typed characters are sent rather than appending to it. But as I said, not "quite that simple"...compare the contents of one of those files and what gets generated by the vimgolf tool. This is from an actual vimgolf problem...

-W output when copied then pasted here:

GI0. ý`gvgý`ZZ

Several non-printing characters got "lost in translation".

-W output as it appears on-screen:

^VGI0. ^[<80>ý`gvg^A<80>ý`ZZ

Well, that's kinda ugly.

vimgolf displayed/uploaded output:

<C-V>GI0. <Esc>gvg<C-A>ZZ

Ahh, that's better.


Update: I spent a few minutes looking a bit closer at things and have a couple new pieces of information.

First, the keylogger class keylog.rb that I mention above is indeed a major piece of the puzzle but it's actually fairly straightforward. The keycodes that Vim emits and which are saved in the -W log file are either one byte or three bytes (indicated by a first byte value of 0x80) and there is a hash map for each of the two sets.

The one-byte version maps the byte value to a string representation of the keycode such as 0 or g. The three-byte version similarly maps to a string (e.g. <Esc> or <C-V>) but using as the key the combined values of bytes two and three. There are some exceptions/corner-cases that are handled differently but the vast majority of keycodes are resolved through simple lookups in these two maps.

Seeing how basic the key logger code was I could tell something was wrong with what I was seeing in the keycode log files (such as the example pasted in above). It turns out I should have used the vimrc file required by VimGolf rules. In particular this line

set t_RV= 

results in the correct logging. The "appears on-screen" example above actually would look like this:

^VGI0. ^[gvg^AZZ

Now one can see the straight line from this "raw" string to VimGolf's rendered form.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.