Vim keystrokes cheatsheet

The time has come for me to list few of the commands and keystrokes that I use (and the ones that I don’t but would like to start) in Vim.

I am actually running a Vim plugin for Visual Studio Code (this and the previous blogs are actually written with this plugin ON) at this very moment.

Bear 🐻 in mind: this blog is aboout keystrokes only, it is not about plugins or configuration I use - I shall cover that one day.

Things I know by heart

  • h, j, k, l for slow but precise character-wise movement
  • w, b for faster forward (and, correspondingly) backward word-by-word movement
  • $ and ^ to go to the last and first word character of the line
  • gg and G to go to the beginning and the end of the file
  • O (capital o) to create a blank line and go to INSERT mode above and below (lower-case o) the cursor
  • f, F and t and T for single character lookup within the current line
  • / and ? to search forwards and backwards
  • c (followed by the object) to change the object; this expands to the following few commands:
    • cw to change the current word under cursor
    • cit to change the text within the current XML tag
    • ca' to change the text surrounded by single quote
    • ci< to change the text surrounded with &lt; and &gt;
    • ci{symbol} to change the text surrounded by symbol, which could be ', ", &#96;; you can also use b( for block of text, surrounded by braces, B{ for block of text surrounded by curly braces or p for paragraph, all instead of symbol
  • v to enter the VISUAL mode, followed by the command:
    • v{select}c immediately change the selection
    • v{select}d cut the selected text
  • y and p copy and paste the selected text (lower-case p pastes above the current line, capital-case P pastes below; capital-case Y copies the entire line, so the duplicate line command in Vim is Y, P)
  • {number}{command} repeat the command number times
  • . (the period or dot symbol) repeats the last command
  • x to remove the character under cursor
  • r{char} to replace the character under cursor with char
  • A to go to the end of the line and enter INSERT mode (“append”)
  • u and Ctrl+r to undo and redo actions
  • > and < adds or removes the indentation

Things that I am still getting used to

  • {number}{motion} instead of h, j, k, l
  • a instead of i to enter INSERT mode after the cursor (as opposed to i which enters INSERT mode before the cursor)
  • H, M and L to go to the top, middle and the bottom of the screen (High, Mid and Low)
  • * and # to search for the word under cursor forwards and backwards
  • {count}/{query}⏎ to go to the count-th occurrence of query; it is same as searching with / and then hitting n count times
  • gd navigates to a definition of an entity under the cursor
  • gf navigates to the path under cursor
  • % moves the cursor to the matching brace, bracket or curly brace
  • g~ toggle the case
  • = format the selection
  • gU makes the selection uppercase

Gantt chart with D3. Part 2

UPDATE: there is a follow-up to this blog, Gantt chart with Canvas.

This is a follow-up to the blog I wrote a bit over three years ago, Gantt chart with D3

In the original blog I claimed to implement something like this:

Yet I ended up implementing something more like this:

Does not look quite same, right? It also does not work quite same and lacks few quite important features too.

Don’t get me wrong, the original implementation did serve project needs, but it was not something anybody could simply use in their project management software and expect customers to love it.

Hence I came up with these complaints about the implementation:

Namely, there are three main issues that I see:

  1. there is a place for mistakes: milestones are allowed to depend on later milestones or simultaneously going ones
  2. there is no clear distinction between the dates each specific milestone starts or ends
  3. if the milestones overlap with current timeframe, current day is not highlighted on the chart (and that often is useful)

Apart from that, there are few technical challenges preventing his whole thing from becoming a real application component:

  • dependency lines look ugly with those sharp corners
  • the implementation is not based on any framework neither does it declare its dependencies (like D3 or MomentJS)

Now I want to revise the original implementation and make it a bit more usable, just like this:

Read more

A response to response to hello world

Recently I’ve received an email from StackOverflow newsletters with a link to a quite controversial (at first glance) blog, A response to Hello World by Caleb Doxsey. This blog is a response to another curious read, Hello world by Drew DeVault.

In the former article, author compared the performance of a tiny “Hello, World” program in Assembly to the same program in Go. He then tried to optimize the program in Go to run faster and towards the end of an article comes up with a program that is faster than its Assembly counterpart.

And this totally makes sense, since if you give it a good read, you will notice that author did optimize the program in Go but did not do that for the Assembly program.

I have decided to burn few hours of my life and jump onto this topic, since, in my opinion, author did not do a fair comparison.

Read more

Erlang in 5 minutes

X = erlang, Y = 5, io:format(“Learn ~s in ~s minutes”, [ X, Y ]).

Welcome to a 5-minute Erlang introduction!

First things first:

  • Erlang is a functional programming language
  • erl is the REPL shell
  • Ctrl + G and then q or q(). to exit the shell
  • c(file_name). to load the code from file

Now, to the language constructs:

  • every statement has to end with a dot (.) symbol
  • multiple statements are separated by comma (,) character
  • constants start with a Capital Letter
  • atoms (yes, like in Ruby) start with lowercase letter
  • atoms are allowed to contain spaces (sic!), but then they have to be quoted: 'atoms are awesome'
  • atoms can also have the at sign (@)
  • anonymous functions are defined as fun() -> return_statement end.
  • last statement before end must not end with comma
  • function signature is function_name/number_of_arguments: factorial/1, format/2
  • comments start with percent (%) symbol
  • lists are [ TheOnlyElement ] or [ Head | TailElements ], where TailElements is also a list
  • pattern matching just works [ Head1 | Head2 | Tails ] = [ 1, 2, 3, 4 ]
  • strings are just "strings"
  • tuples are quirky { elt1, elt2 }
  • maps are even weirder #{ key => value }
  • operators are almost fine:
    • comparison: < (less than), > (greater than), >= (greater than or equals to), =< (equals to or less than), == (equals to), /= (not equals to), =:= (adds type checking on tops, JS equivalent of ===)
    • assignment / pattern matching: =
    • math: +, -, *, /, div, rem (Pascal way)
    • typechecking: is_atom/1, is_function/1, is_number/1, is_boolean/1, is_pid/1, is_list/1, etc.
  • list comprehentions are similar to lists: [ N || N <- [ 1, 2, 3, 4, 5 ], N rem 2 == 0 ].
  • files are modules, defined with few statements:
    • -module(module_name).
    • -export([ list_of_function_signatures ]).
    • -import(module_name, [ list_of_functions ]).
  • calling module’s export be like module_name:function_name(arguments).

Quick recap:

%%% module comment
-module(erlang_example).

% exporting the functions from the module
-export([ factorial/1 ]).

% importing the functions from the other module
-import(my_other_module, [ new_factorial/1 ]).

% constants with pattern matching - will assign the value to non-defined constant on success
X = 5.

% redefinition is prohibited
X = 10. % exception

% functions can also be constants
PlusOne = fun(X) -> X + 1 end.

% or, multiline
PlusTwo = fun(X) ->
  X + 2

  end.

% the standard way
bad_factorial(N) ->
  N * factorial(N - 1).

%% function documentation
% functions can have *guargs*, which are basically pattern matching
% also, function overloading is split with semicolon (;)
factorial(N) when N =< 1 -> 1;

% last overload ends with dot (.)
factorial(N) -> N * factorial(N - 1).

% some return types
string_fn() -> "hello, world!".

list_fn() -> [ 1, "elements could be of different types too", -3.14, atom ].

function_function() ->
  fun(X) -> X mod 2 end.

dict_fn() -> #{ "key" => -3.14 }.

tuple_fn() -> { elt1, elt2, "elt 3" }.

%% note how overriden_function/1 has different definition than overriden_function/2
overriden_function(List) ->
  overriden_function(List, 0).

% the power of pattern matching!
overriden_function([ Head ], Acc) -> Acc + Head;

overriden_function([ Head1 | Head2 ], Acc) -> Acc + Head1 + Head2;

overriden_function([ Head | Tail ], Acc) ->
  overriden_function(Tail, Acc + Head);

overriden_function([], Acc) -> Acc.

complex_function(A, B) when A =< B -> A;
complex_function(A, B) when A > B -> B.

complex_function(A, B, C) ->
  X = complex_function(A, B),
  complex_function(X, C);

complex_function(A, B, C, D) ->
  X = complex_function(A, B),
  Y = complex_function(C, D),
  complex_function(X, Y).

fst({ First, _ }) -> First.

snd({ _, Second }) -> Second.

evens(List) -> [ X || X <- List, X rem 2 == 0 ].

keys(#{ Key => Value, _ => _ })

There also are few good resources on this: [https://learnxinyminutes.com/docs/erlang/](Learn X in Y minutes (where X = erlang)) and [http://erlang.org/doc/apps/inets/http_client.html](Official Erlang docs).

Linq is awesome, right?

Recently I’ve seen a curious blog on Dev.to, C# and .NET Core Appreciation Post. The most beautiful piece of code I have ever seen… this month!.

In short, author was amazed by how beautiful Linq is, supporting their feelings with this code snippet:

public User GetUserByToken(string token) {
  var user = (from u in Users
              join t in Tokens on u.Id equals t.UserId
              where t.Body == token
              select u).SingleOrDefault();

  return user;
}

Let’s tear this example apart and check how really performant beautiful Linq is!

Read more

Partial application vs currying

Here’s a quick explanation of the difference between currying and partial application.

For a one- or two-argument functions there is little to none difference. But for function with multiple arguments…

Say you have a function f(a1, a2, a3, a4) (it does not really matter what it returns or what the arguments are):

  • currying it will give you a function of one argument, which will return a function of one argument (and so on and so forth), calling which (the last one-argument function) will give you same result as calling the original function f with all the arguments of single-argument functions passed at once (curried): curry(f) = f1(x1) => f2(x2) => f3(x3) => f4(x4) === f(x1, x2, x3, x4)

  • partially applying a function to some N values will give you a function of smaller amount of arguments, where the first N arguments are already defined: papply(f, 1, 17) => f1(x3, x4) === f(1, 17, x3, x4)

In Javascript, the two could be implemented like this:

function curry(f) {
    function curry(f) {
    const currySub = function (fn, args) {
        // Surprisingly, `fn.length` returns the number of arguments of a function `fn`
        if (args.length < fn.length) {
            return function (x) {
                return currySub(fn, args.concat([ x ]));
            };
        }

        return f.apply(null, args);
    }

    return currySub(f, []);
}

function papply() {
    const f = arguments[0];
    const args0 = Array.from(arguments).slice(1);

    return function () {
        const args1 = Array.from(arguments);

        const args = args0.concat(args1);

        return f.apply(null, args);
    }
}

Type casts in C++, explained

As explained by my colleague, former professional C++ developer (now writes schwifty Java). Below is a quick explanation of four basic C++ type casts. Just for the matter of shorter post, consider each cast taking a template type T and a parameter value v like this: const_cast<T>(v).

  • const_cast - removes the const from the type of v (think of casting const char* will produce char*)
  • static_cast - C-style, unchecked explicit type casting (just like in old 90s: (int) 3.14)
  • reinterpret_cast - hard low-level treating a block of memory as type T, no matter what resides in that memory
  • dynamic_cast - does the runtime checks of param type and template type

Game development with Newton Game Dynamics and Irrlicht tutorial

Slowpoke image

As there was not a high load on my tutorial on game development with Irrlicht and Newton Game Dynamics engines as a separate site, I have decided to merge them with my blog and proceed with occasional updates to both as a whole.

So far, these are the changes to the tutorial in comparison to what it used to be (long time ago):

  • moved all the build instructions to CMake
  • added scripting with Lua
  • upgraded the whole tutorial to match latest Irrlicht and Newton versions
  • added chapter on modelling with Blender

The things which are already done (just not published yet), in progress and the future plans for this tutorial include:

  • comparison of different build systems for C++ (including CMake, Bazel and Buck)
  • a better approach to application architecture (plus the comparison of different scripting languages - AngelScript, Squirrel, Lua, ChaiScript and Python)
  • a sane 3D modelling in blender lessons (preserving texturing and adding advanced materials, possibly even animation!)
  • advanced topics in Newton Game Dynamics featuring character controller and joints

Tutorial chapters (yet to be updated):

  • Introduction
  •     <li>
            <a href="/irrlicht-newton-tutorials/2015/08/26/application-architecture.html">
                Application architecture
            </a>
        </li>
    
        <li>
            <a href="/irrlicht-newton-tutorials/2015/08/27/first-application.html">
                First application
            </a>
        </li>
    
        <li>
            <a href="/irrlicht-newton-tutorials/2015/08/28/first-script.html">
                First script
            </a>
        </li>
    
        <li>
            <a href="/irrlicht-newton-tutorials/2015/08/29/prepare-to-add-some-newtonianity.html">
                Let's add some physics
            </a>
        </li>
    
        <li>
            <a href="/irrlicht-newton-tutorials/2015/12/15/making-simple-level-with-blender.html">
                Modelling simple level with Blender3D
            </a>
        </li>
    
        <li>
            <a href="/irrlicht-newton-tutorials/2015/12/16/finishing-the-first-scene.html">
                Finishing the first scene
            </a>
        </li>
    </ul>
    

One-night games: snake

source code

Under the cut you can find the interesting algorithmic solutions I’ve mentioned.

Read more

Improving ZSH startup performance

Adding profiling to ZSH

Add this line as the first one, to the very top of your ~/.zshrc:

zmodload zsh/zprof

And add this one to the very bottom of this same file:

zprof

Now, whenever you open up ZSH, you shall see a list of things which start and how much time each entry takes to load. For me it was like this:

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    1        1123.49  1123.49   87.59%   1123.49  1123.49   87.59%  _pyenv-from-homebrew-installed
 2)    1          84.02    84.02    6.55%     59.50    59.50    4.64%  compinit
 3)    3          26.94     8.98    2.10%     26.94     8.98    2.10%  __sdkman_export_candidate_home
 4)    3          25.77     8.59    2.01%     25.77     8.59    2.01%  __sdkman_prepend_candidate_to_path
 5)    2          24.52    12.26    1.91%     24.52    12.26    1.91%  compaudit
 6)    2           7.98     3.99    0.62%      7.98     3.99    0.62%  grep-flag-available
 7)    2           7.54     3.77    0.59%      7.54     3.77    0.59%  env_default
 8)    2           2.43     1.22    0.19%      2.43     1.22    0.19%  _has
 9)   23           2.43     0.11    0.19%      2.43     0.11    0.19%  compdef
10)    1           1.09     1.09    0.09%      1.09     1.09    0.09%  colors
11)   12           0.38     0.03    0.03%      0.38     0.03    0.03%  is_plugin
12)    1           0.38     0.38    0.03%      0.38     0.38    0.03%  is-at-least
13)    1           0.21     0.21    0.02%      0.21     0.21    0.02%  _homebrew-installed
14)    1           0.03     0.03    0.00%      0.03     0.03    0.00%  __sdkman_echo_debug

-----------------------------------------------------------------------------------

I was able to measure the total startup time by running time zsh -i -c exit. And the total startup time was almost two seconds.

zsh -i -c exit  1.16s user 0.73s system 100% cpu 1.889 total

As you can see, pyenv takes whole bunch of time (1123 millis!). So I do have the pyenv plugin for ZSH and I did disable it. Here’s what happened afterwards:

num  calls                time                       self            name
-----------------------------------------------------------------------------------
 1)    1          91.42    91.42   53.38%     62.48    62.48   36.48%  compinit
 2)    2          28.94    14.47   16.90%     28.94    14.47   16.90%  compaudit
 3)    3          28.62     9.54   16.71%     28.62     9.54   16.71%  __sdkman_export_candidate_home
 4)    3          27.65     9.22   16.14%     27.65     9.22   16.14%  __sdkman_prepend_candidate_to_path
 5)    2           8.27     4.14    4.83%      8.27     4.14    4.83%  grep-flag-available
 6)    2           8.22     4.11    4.80%      8.22     4.11    4.80%  env_default
 7)    2           2.55     1.28    1.49%      2.55     1.28    1.49%  _has
 8)   23           2.50     0.11    1.46%      2.50     0.11    1.46%  compdef
 9)    1           1.24     1.24    0.72%      1.24     1.24    0.72%  colors
10)    1           0.41     0.41    0.24%      0.41     0.41    0.24%  is-at-least
11)   10           0.37     0.04    0.21%      0.37     0.04    0.21%  is_plugin
12)    1           0.02     0.02    0.01%      0.02     0.02    0.01%  __sdkman_echo_debug

-----------------------------------------------------------------------------------
zsh -i -c exit  0.28s user 0.23s system 96% cpu 0.526 total

NVM

Not to forget I had NVM installed with the default settings.

With it I had the startup time of 1.9 seconds:

zsh -i -c exit  1.17s user 0.74s system 99% cpu 1.916 total

If you follow this simple instruction or just replace these two lines, initializing NVM in your ~/.zshrc file:

[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion

with these lines:

if [ -s "$HOME/.nvm/nvm.sh" ] && [ ! "$(type __init_nvm)" = function ]; then
 export NVM_DIR="$HOME/.nvm"

 [ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion"

 declare -a __node_commands=('nvm' 'node' 'npm' 'yarn' 'gulp' 'grunt' 'webpack')

 function __init_nvm() {
   for i in "${__node_commands[@]}"; do unalias $i; done
   . "$NVM_DIR"/nvm.sh
   unset __node_commands
   unset -f __init_nvm
 }

 for i in "${__node_commands[@]}"; do alias $i='__init_nvm && '$i; done
fi

The start-up time drops by 0.1 second. But it still is an improvement, right?