KB Paradise V80 Matias Quiet Click

New gadget.


My first PC was an Olivetti 386 so the Olivetti color keycaps was too much of a tease. I’ve wanted to try the Matias switches forever, but I couldn’t dig the looks of Matias’ own keyboards.

I’ve been working off a laptop for the last ~3 years due to mobility requirements and although my Clevo’s keyboard seemed good to type on, I practically lost the muscle memory for the Home/End shortcuts and rued the loss every time I spammed the Ctrl+Arrows to get somewhere. Didn’t care about the layout being US — I still type in Spanish layout but I’ve been touch typing since ever. The only issue I had was the loss of the extra key for lesser/greater (usually between left shift and Z, on my laptop between space bar and right Alt). Spanish layout has a Ç key for catalan, which I never use, so I remapped it with xmodmap -e "keycode 51 = less greater braceright braceright braceright". The only other loss is right hand enters due to the TKL layout, but that’s a worthy trade.

Typing on it after a week I would describe it as “neat”. The build is solid and doesn’t move or flex at all. Keys activate high in a very very reliable way. I feared missing activations or making more typos but that hasn’t been the case. The switches are fairly quiet, tho the chattering is still audible with my headphones on and to anyone nearby. The most noticeable difference is going back to the laptop keyboard, which now feels horribly mushy and unreliable; even tho it felt OK for the last few years, it only took a week to become utter torture. I’m sure I’m going to be often tempted to pack the V80 for travel and just be “that guy” with the clackity clack keyboard plugged to the laptop.

Pet project notes – PHP 7, local git, Composer, Thunderbird mbox – Part 1

#. Using my local git dev repo. I work on it for faster iteration until I have something that works from start to end, then move it to a fresh github.

git init --bare myapp
git clone /media/user/drive/git/myapp

#. The script that tests the component is on a separate project, so I can test pulling the component with composer as a vendor dependency.

composer install; ./test.php

Have to plug things in still though.

#. Adding the local repository to composer.json on the test app.

"repositories": [{
    "package": {
	"name": "FranOntanaya/MyApp",
	"type": "library",
	"version": "1.0.0"

#. Switched stability version to “dev” on request by Composer.


#. Autoloading wasn’t seeing the class on instancing. Online answers were inconsistent. Added debug echos in Composer’s autoloader to see what was it trying to call. Had to add an autoload section to composer.json on the test app, with a full path:

"autoload": {
    "psr-4": {
        "FranOntanaya\\": "vendor/FranOntanaya/MyApp/src"

Works, but it does look odd.

#. Moved component to branch tests for all the little iterations. Edited composer.json on the test app.

"require": {

#. Proper coding now. Considered a few chunking ideas to tail the mbox files and limit the amount of data parsed, but settled on reading backwards from the end, parsing as it goes and stopping at the given number of messages. Can’t really predict how big messages are. Fortunately mbox (or Thunderbird) inserts a blank space before any message body line starting with “From -” so it can’t be mixed up with the start of the headers. Kludgey but I guess it works.

#. Since the component is namespaced, had to point DateTime and DateTimeZone to the root.

$dateTime = new \DateTime($match[1], new \DateTimeZone('UTC'));

#. Adding logger optional dependency from the start. Can live with if check on every call, rather than adding and creating a dummy logger.

if ($this->logger) { $this->logger->warning("MyApp: Invalid date when parsing headers"); } 

#. Things that you wouldn’t do when committing on a shared environment. Arrow up + Enter.

git add -A; git commit -m "Dev iteration"; git push

#. Using PHP 7 type hints and return types. Caught 3-4 issues. Sometimes it’s just half-written code issues, but seeing the type errors helps a lot having direction when picking what to finish next.

function parseMessageId(string $headers): string {

#. Documenting array keys because I like packing arguments. Also, why was I adding @version to every method docblock again?

     * Init
     * @param int $r['limit'] Number of messages to hold
     * @param string $r['file'] File to load from

#. Reading the mbox in reverse because we don’t want to load the whole thing in memory.

if ($mbox = @fopen($this->file, 'r')) {
    fseek($mbox, 0, SEEK_END);
    $pos = -1;
    while (fseek($mbox, $pos, SEEK_END) !== -1) {
        $char = fgetc($mbox);
        if ($char === PHP_EOL) {
        } else {
            $currentLine = $char . $currentLine;

No Yoda conditions. I already avoid ==, so little chance of typing = instead.

#. Mbox uses DOS line breaks. Preserving them for consistency.

$currentMessage = $currentLine . "\r\n" . $currentMessage;

But then I don’t trust myself.

preg_match('/\r?\nContent-Base: (.*)\r?\n/', $headers, $match);

#. Sweet null coalesces.

$parsed['body'] = $matches[2] ?? '';

#. For now, not throwing exceptions on loading, since it’s not this method’s business to decide if failure to open is an error or perfectly fine for the caller.

function load(): bool {
    if ($mbox = @fopen($this->file, 'r')) {
        $this->messages = $parsedMessages;
        if ($this->logger) { $this->logger->info("MyApp: Loaded {$this->file}"); }
        return true;
    if ($this->logger) { $this->logger->error("MyApp: Couldn't open {$this->file}"); }
    return false;

Fiodor Dostoievsky on JavaScript

I tell you, the old-fashioned standard library that handled all basic operations has completely disappeared, now there are only packages, and they advertise all the time in the newspapers. If your string handling hurts, they send you to npm: “there’s a string package there, it does padding”. You go to npm, you get your string parsed: “I can pad only your right side”, it returns, “I don’t pad strings left, it’s not my specialty; but after me, go to back to npm, there’s a separate package there who will finish padding left your string.”

jQuery 3, staying alive

Because not everything needs to be wrapped in a framework.

  • for…of Loop
  • New signature for $.get() and $.post()
  • Use of requestAnimationFrame() for Animations
  • unwrap()
  • :visible and :hidden
  • data()
  • The Deferred Object
  • SVG Documents
  • Deprecation of bind(), unbind(), delegate() and undelegate()
  • Removal of the load(), unload() and error() Methods
  • Removal of context, support and selector
  • No More Rounding for width() and height()
  • wrapAll()

Link: http://developer.telerik.com/featured/whats-new-in-jquery-3/