Fix Missing Font Fallbacks for NSTextView

Rich Siegel recently wondered on Slack why NSTextView would suddenly display empty placeholders for some glyphs when the font does not support them, instead of falling back to a safe font like it usually does. Chinese characters never got displayed. Michel Fortin remembered a similar problem, and the potential fix was quite simple:

In summary, if you have to change the font after the text storage was edited, do it in willProcessEditing and it’ll do the right thing. Don’t do it in didProcessEditing.

That turned out to be what tripped up Mr Siegel’s text view, which now happily displays CJK/CJKV again. For more details and some background about how you can detect this problem in your apps, read Michel’s post.

Building a Rich Domain In Iterations

I’m currently revising code from 3 years ago. The result is a replica of the old stuff – updating isn’t worth the effort, it’s written in Swift 3 and the code base is small, so I rewrite it and copy useful parts over. The public interface already differs from what I wrote 3 years ago.

In the first step, I translated the old code but took what was there. For example, back then I had a DateRange type. Swift Ranges were less powerful back then, so I added a couple of convenient methods that I can now replace with the standard library protocols instead. So I demoted the type to typealias DateRange = Range<Date>. I also had a Date type (this was before NSDate dropped the ”NS”) that I renamed to NormalizedDate. In the domain I work on, a date isn’t a date-time-combination, but just the year, month, and day. Confusingly, this type was a mere wrapper for NSDate that dropped the time information for quick comparisons.

Later, as I worked on the protocols that this module would expose, I figured that the notion of a “range of days” is missing. Sure, Range<NormalizedDate> did the job, but a DayRange type was better. It’s became a RawRepresentable, backed by Range<NormalizedDate>.

After this change, though, I found the name “normalized date” too general. Sure, I am normalizing the date-time to drop the time information completely. But I really want to work with a Day-date type. So I introduced Day, which is backed by a NormalizedDate and specifies its own normalization rules. This is oddly satisfying. The Day type knows the normalization rules to create a NormalizedDate from a regular old NSDate.

As I write about all this, I notice that I should’ve made an additional step and replaced Day with a struct that has year, month, and day only and constructs NSDates where needed, instead of relying on that type to represent its values. Excuse me for a bit while I change the domain to accommodate this insights.

Prevent Emacs Compilation Window From Displaying Other Content

By accident I found a setting for emacs windows that prevents a window from displaying any other content than what it currently is showing. It is not locking the textual contents but the buffer. That means you cannot show the contents of another file, or change the currently visible help page, or whatever.

And, just what I needed: you can prevent the small compilation results window from changing contents. Sometimes I have the compilation window focused and want to look at a code listing; now the code listing would open inside the tiny compilation window!

To prevent this, you can lock a window to its current buffer by making it “dedicated”. Call the non-interactive function (set-window-dedicated-p WINDOW t) to enable this, and (set-window-dedicated-p WINDOW nil) to disable this again.

I added it to the code where I create the compilation window to limit its height to 10 lines of text, and enable the flag after the window’s buffer is configured:

(setq compilation-window-height 10)

(defun ct/create-proper-compilation-window ()
  "Setup the *compilation* window with custom settings."
  (when (not (get-buffer-window "*compilation*"))
    (save-selected-window
      (save-excursion
        (let* ((w (split-window-vertically))
               (h (window-height w)))
          (select-window w)
          (switch-to-buffer "*compilation*")

          ;; Reduce window height
          (shrink-window (- h compilation-window-height))

          ;; Prevent other buffers from displaying inside
          (set-window-dedicated-p w t) 
  )))))
(add-hook 'compilation-mode-hook 'ct/create-proper-compilation-window)

That does the job. Now the tiny compilation window contents are locked and the madness of displaying anything anywhere is over!

Quit and Close Emacs Special Windows Like Help and Compilation Results

Emacs can display interactive help windows (the content/buffer name is called ”*Apropos*”), and compilation results. I managed to limit the height of the compilation window to 10 lines already. But when I have the compilation results pane focused, I want to close and dismiss it quickly.

This kind of window (or panes) is in the so-called special-mode. That’s one mode where you do not interactively enter text, but can move the caret around freely. These non-text “special” windows have dedicated key bindings as well. One key is q which closes the currently visible contents, but leaves the window pane on screen. (The function that’s called is named quit-window.) When the content is closed, the next best content is displayed in its stead.

Update: Turns out the compilation window is not reacting to the special-mode-hook, so I had to add a hook for it, too. The rest remains valid, though.

Let me explain how this works. When I compile a project in emacs, the compilation window is created by splitting my current window in two. The bottommost window is displaying the very same buffer (or in-memory contents that are related to the file I’m viewing) as my original window. That’s the default behavior of the split command at least. Then the newly created window is set to display the compilation results. That operation is similar to all other buffer display operations: it puts the compilation buffer on top of the window’s buffer stack, and the topmost item is going to be displayed. The rest of the stack can still be navigated to by switching buffers if you want. (C-x b is the fundamental command you learn early, corresponding to the switch-buffer function. It changes what you see in the window.) You can also pop the stack’s tip from it and have the new tip become active automatically. That’s similar to when you close tabs in your browser: the adjacent tab becomes focused. But I don’t want this to happen when I compile a project. I don’t want a source file to become visible in the small bottom pane.

So I figured I want to overwrite the lowercase-q shortcut to a “quit and remove window” action.

(defun ct/quit-and-kill-auxiliary-windows ()
  "Kill buffer and its window on quitting"
  (local-set-key (kbd "q") 'kill-buffer-and-window))
(add-hook 'special-mode 'ct/quit-and-kill-auxiliary-windows)
(add-hook 'compilation-mode-hook 'ct/quit-and-kill-auxiliary-windows)

Emacs Settings for PHP Development

PHP file in the main pane, with a unit test/compilation result pane at the bottom, and the neotree directory view to the right

The project that I’ve been working on over the weekend, I worked on in emacs. This is part of my re-learning the basics of text editing and programming in emacs to slowly move away from TextMate when it comes to scripts. I want to move away from TextMate because I eventually want to transition to be productive on a Linux machine – that means, to create stuff in an otherwise foreign operating system. Emacs is portable, so that’s a good start.

Projectile and Neo Tree project settings

In general, I am using Neo Tree to display the project directory in a window on the right, and I use projectile to quickly find files inside the project context (C-c p f), switch between tests and implementations (C-c p t), and run the tests with a shortcut (C-c p P, note it’s an uppercase “P”, so you need to press shift).

It didn’t take long to commit C-c p P to muscle memory to execute the tests; and the C-c p t accord works really well to switch back and forth between implementation and tests. When I read about Projectile’s default shortcuts, I frowned at the prospect of memorizing all that stuff, but it wasn’t that bad at all.

In my emacs init.el, I have these projectile settings:

(use-package projectile
  :ensure t
  :config 
    ;; Global configuration
    (setq projectile-switch-project-action 'neotree-projectile-action
          projectile-enable-caching t
          projectile-create-missing-test-files t
          projectile-switch-project-action #'projectile-commander
          projectile-ignored-project-function 'file-remote-p)
    (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
    ;; Register custom PHP project type
    (projectile-register-project-type 'php '("composer.json")
                                      :src-dir "src"
                                      :test "composer test"
                                      :run "composer serve"
                                      :test-suffix "Test"
                                      :test-dir "tests"))
(use-package counsel-projectile 
  :ensure t)

Apart from some configuration options, the most interesting part is the projectile-register-project-type command. PHP is not shipped by default, so I set it to discover the project type by looking for a composer.json file in the project root, then I configured the source and test directory according to the new-found conventions.

When I’m in a source file, I can quickly jump to the tests and back again with C-c p t. In my book, that’s better than having to have both files open at all times and switch back and forth most of the time.

And here are the Neo Tree settings:

(use-package neotree
  :ensure t
  :config (global-set-key [f8] 'neotree-project-dir)
          ; Every time when the neotree window is opened, let it find current file and jump to node.
          (setq neo-smart-open t)
          ; Do not autorefresh directory to show current file
          (setq neo-autorefresh nil))

I found the default behavior to be odd. When I switch files inside of a project, Neo Tree by default highlights the file in the directory listing to the right, but also switches focus to the file’s directory. When I would open a test file, only the test/ directory remained visible. Hiding all the sibling directories, including src/, wasn’t what I wanted – I wanted to see an overview of the whole project. With Projectile’s file finding being limited to the current project directory by default, the visual overview became less and less useful. Maybe I’ll ditch Neo Tree in the future. I do like Neo Tree when I get back to old projects for which I don’t remember what I put where, heh.

Code Completion

I also use the Comp[lete]any[thing] mode to have code-completion – to my amazement this apparently even works across files in the same project!

; Install company
(use-package company
  :ensure t
  :config (add-hook 'prog-mode-hook 'company-mode)
          (global-set-key (kbd "M-i") 'company-complete))
(use-package company-anaconda 
  :defer
  :after company
  :config (add-to-list 'company-backends 'company-anaconda))

; Company language package for PHP
(use-package company-php
  :defer
  :after company)

; Just as an example, aso Ruby:
(use-package robe ;; company-robe is a Ruby mode
  :ensure t
  :after company
  :config (add-to-list 'company-backends 'company-robe)
          (add-hook 'ruby-mode-hook 'robe-mode))

General programming mode settings

Scroll to the bottom of the compilation results window. I discovered two settings and show both here. I picked the one where the window scrolls to the first error of the compilation or test results; but scrolling to the bottom was just as nice.

;; Scroll to the bottom of the compilation buffer:
; (setq compilation-scroll-output t)

;; Scroll to the bottom OR the first error in the compilation buffer
(setq compilation-scroll-output 'first-error)

I also limit the bottom compilation window to a height of 10 lines – otherwise it would pop up at 50% height:

(setq compilation-window-height 10)

(defun ct/compilation-hook ()
  (when (not (get-buffer-window "*compilation*"))
    (save-selected-window
      (save-excursion
        (let* ((w (split-window-vertically))
               (h (window-height w)))
          (select-window w)
          (switch-to-buffer "*compilation*")
          (shrink-window (- h compilation-window-height)))))))
(add-hook 'compilation-mode-hook 'ct/compilation-hook)

I also have the following minor modes enabled by default:

  1. Display line numbers,
  2. break lines visually, e.g. at the edge of the window, instead of cutting them off,
  3. highlight paired parens as I open or close them, or hover over them with the cursor, and
  4. hide/show code blocks aka folding methods or class definitions.
(add-hook 'prog-mode-hook 'linum-mode)
(add-hook 'prog-mode-hook 'visual-line-mode)
(add-hook 'prog-mode-hook 'show-paren-mode)
(add-hook 'prog-mode-hook 'hs-minor-mode)

The Archive Update Hiatus Due to a Severe Bug in Xcode 11

This announcement is a very difficult one: I cannot work on The Archive for the next week or two, maybe, more. That’s because with Xcode 11 and Swift 5.1, UI Tests stopped to work. Like, at all. I have created a Feedback ticket (FB7338237) and now also have a Technical Support incident open, awaiting a reply by Apple engineers to help with this.

All this puts me into a conundrum: Without functional UI tests, I cannot guarantee that complex interaction patterns with the app don’t break with the next update. I could write a simple wrapper that replicates the UI tests’s functionality but uses the Accessibility API directly to remote-control the app – but this will probably take a week, and that doesn’t seem worth it since I sincerely hope the Apple engineers have something helpful to say, rather sooner than later.

So instead of spending time to get the development environment back up to 100% again, I will spend the time on different projects. Like, new functionality for the WordCounter.

The Xcode bug that I am struggling with puts the following into the Xcode console:

error: module importing failed: invalid pathname
dyld: Library not loaded: @rpath/CoreSymbolicationDT.framework/Versions/A/CoreSymbolicationDT
  Referenced from: ~/Library/Developer/Xcode/DerivedData/TheArchive-bdfzgzxhmswchfaskemobshbdnic/Build/Products/Debug/TheArchiveUITests-Runner.app/Contents/Frameworks/XCTest.framework/Versions/A/XCTest
  Reason: image not found

It looks like the UI testing process doesn’t embed some testing frameworks into either the app or the test runner.

I can replicate this exact error message in a vanilla project: I just have to embed and link to all RxSwift frameworks in the app target, including RxSwift, RxText, RxBlocking, RxCocoa. Then the UI tests of that project will fail for the same reasons. (It doesn’t matter if I build dependencies via Carthage, CocoaPods, or on my own.)

The thing is: I removed all code from The Archive, and all framework dependencies, and the error still doesn’t go away.

This is a weird one. I’m puzzled; I asked around and had people replicate the bug. It’s a real show-stopper.

I learned that you can add the DYLD_PRINT_RPATHS=1 environment variable to the scheme in Xcode and have the path lookups printed to the console. The dyld error is related to the app, not the UI test process, and in the sample app the CoreSymbolicationDT framework is reported to indeed be found and the path resolved. This makes it all even more puzzling.

Now I do hope for a quick resolution. To all fans of The Archive: I’m sorry for the lack of updates in the past weeks due to this problem.

Now I’m looking forward to work on the long-awaited analytics/statistics module for the WordCounter and see where this goes.

Starting PHP Development in 2019: Project Setup and Dependencies

I was experimenting with PHP development over the weekend to whip up a properly unit-tested library to generate license codes, hosted on your own web server. I wanted to make use of my newfound emacs prowess and figure out how programming is supposed to work with the stuff I have and have not prepared so far.

But how do you start a PHP project? From the Ruby community, I know that there are widely-adopted conventions regarding the root-level directory structure that some tools even rely on. Convention is part of Ruby on Rails’s magic, so I’m eager to figure out what the PHP community adopted so far to get productive quickly.

Modern PHP is object-oriented and comes with Java-like namespaces. The namespace of the app or library here is replaced with LIBRARYNAME. Insert your own package name there. There probably is a tool to set all of this up for you, but I didn’t stumple upon one and did all the following manually, figuring out how namespace resolving etc. works.

Directory structure

The basic structure I adopted is:

  • src/LIBRARYNAME to put all my module code into;
  • tests/LIBRARYNAME contains all the tests, mirroring the directory structure of src.
  • config/ for the development and production environment changes. I want to use SQLite locally and MySQL/Maria DB on the server.
  • public/ contains web-facing files, i.e. the index.php that will create a server instance and forward requests. That’ll end up in the public htdocs of my server.
  • vendor/ contains dependencies, managed by the PHP Composer dependency manager.

Project settings

PHPUnit allows configuration via XML files. It’s optional, but I figured I might as well add the default configuration to a file. So phpunit.xml reads:

<?xml version="1.0" encoding="utf-8" ?>
<phpunit bootstrap="./vendor/autoload.php">
    <testsuites>
        <testsuite name="The project's test suite">
            <directory>./tests</directory>
        </testsuite>
    </testsuites>
</phpunit>

Then this is the project’s composer.json I have:

{
  "license": "MIT",
  "authors": [
    {
      "name": "Christian Tietze",
      "email": "hi@christiantietze.de",
      "homepage": "https://christiantietze.de"
    }
  ],
  "autoload": {
    "psr-0": {
      "LIBRARYNAME": "src/"
    }
  },
  "scripts": {
    "test": [
      "phpunit -c phpunit.xml"
    ],
    "serve": [
      "php -S localhost:8888 -t public/"
    ]
  },
  "require": {
    "php": "^7.1"
  },
  "require-dev": {
    "phpunit/phpunit": "^8.4"
  }
}

I require PHP 7.1 or newer to get optional return values in type annotations. (See “Misc” below.)

I added the latest PHPUnit library, and also created two script shorthands. I can run compose test and have phpunit execute in the project context with my project settings. I can also spin up the PHP server for local testing from the public/ subdirectory without cd‘ing inside. Nice.

The autoload convention I use here is “psr-0”. I didn’t get “psr-4” to work right away and figured I might as well use the version 0 convention. It basically expects the LIBRARYNAME namespace inside the src/ subdirectory. Namespaces are resolved as part of the directory structure, so it’ll look in src/LIBRARYNAME/ for files of that namespace.

With the project metadata set up, now to actual code.

Production and Development Environment Configurations

I added a type that handles the configurations in src/LIBRARYNAME/Config.php:

<?php
namespace LIBRARYNAME;

/**
 * Configuration pattern via <https://stackoverflow.com/a/3724689/1460929>
 */
abstract class Config {
    /** Storage for DB / passwords etc */
    static private $protected = array();

    /** Storage for public, aka client-facing metadata */
    static private $public = array();

    public static function getProtected($key) {
        return isset(self::$protected[$key]) ? self::$protected[$key] : false;
    }

    public static function getPublic($key) {
        return isset(self::$public[$key]) ? self::$public[$key] : false;
    }

    public static function setProtected($key, $value) {
        self::$protected[$key] = $value;
    }

    public static function setPublic($key, $value) {
        self::$public[$key] = $value;
    }

    public function __get($key) {
        return isset(self::$public[$key]) ? self::$public[$key] : false;
    }

    public function __isset($key) {
        return isset(self::$public[$key]);
    }
}

With this configuration type, which is just a glorified dictionary (or rather: PHP array), here’s config/config.dev.php:

<?php
use LIBRARYNAME\Config;

Config::setProtected("environment", "this is the development environment");

The actual setting is nonsensical, but it serves the purpose of demonstrating how to use the type. In config/config.prod.php I set a different value.

Please note that the first line of code is not require __DIR__."/../vendor/autoload.php" which a lot of scripts on the web are using. I don’t know why. Maybe the autoloader was less powerful when the projects started; maybe I am excluding part of the world’s PHP configuration by not requiring the autoload.php script here. This works for me so far, because public/index.php is requiring the autoloader already, and the configuration files are not individually executed.

Serving different configuration from the web

When I run composer serve, my public/index.php is listening at port 8888. This file currently takes care of switching configuration files:

<?php
require __DIR__."/../vendor/autoload.php";
ini_set('display_errors', 1);
error_reporting(E_ALL);

define("DEVELOPMENT", 0);
define("PRODUCTION", 1);
define("DEFAULT_ENV", DEVELOPMENT);
define("ENV",
       (getenv("ENV") == "production")
           ? PRODUCTION
           : ((getenv("ENV") == "development")
               ? DEVELOPMENT
               : DEFAULT_ENV));

function loadConfiguration() {
    $suffix = (ENV == PRODUCTION) ? "prod" : "dev";
    $filename = "config.".$suffix.".php";
    require_once __DIR__."/../config/".$filename;
}

loadConfiguration();

print "Current env: ".LIBRARYNAME\Config::getProtected("environment")."\n";

This is not very interesting; it defines a couple of environment constants first, then sets the current ENV depending on the actual environment setting and a fallback value. Then the matching config file is loaded from disk.

This script only prints the nonsensical configuration variable so far.

I can switch environments by setting an environment varaible when running the program:

$ ENV=production composer serve
$ ENV=development composer serve

That’s all I need to run the server with each setting. I like that part, though I didn’t use it so far, heh.

Writing tests

Here’s a single unit test for a value type in the domain I’m working on. I picked the most interesting one.

The test file is tests/LIBRARYNAME/HashablePayloadTest.php:

<?php
use PHPUnit\Framework\TestCase;
use LIBRARYNAME\HashablePayload;

final class HashablePayloadTest extends TestCase {
    public function testHash_TwoDataParameters_ReturnsMD5OfValuesSortedsByKeyAndPrivateKeySuffix() {
        $privateKey = "the private key";
        $data = array('unsorted' => '123', 'data' => '456');
        $payload = new HashablePayload($data, $privateKey);

        $result = $payload->hash();

        $this->assertEquals(
            md5('456123'.$privateKey),
            $result
        );
    }
}

This is, by the way, the algorithm used by FastSpring for order completion callbacks. A shared key is appended to the concatenation of all request values (sorted by key), then an MD5 checksum is generated and passed along with the request. Since the key is private, this is already pretty hard to break.

And here’s the implementation, src/LIBRARYNAME/HashablePayload.php:

<?php
namespace FastSpringMate;

function array_ksorted(array $data) : array {
    $result = $data;
    ksort($result);
    return $result;
}

final class HashablePayload {
    public function __construct(array $data, string $privateKey) {
        $this->data = $data;
        $this->privateKey = $privateKey;
    }

    public function data() : array {
        return $this->data;
    }

    public function hash() : string {
        return md5($this->sortedDataString().$this->privateKey);
    }

    private function sortedDataString() : string {
        private function sortedDataString() : string {
        return join(array_values(array_ksorted($this->data)));
    }
}

Miscellanea

  • Autoloading seems to be widely adopted, albeit in different ways; composer comes with its own implementation that seems to Just Work, so I stick to that
  • PHP supports type annotations for parameters and return values! function foo(string $input = "default") : int
  • PHP 7.1 supports optional return values, too, so you can return null when object creation fails, for example: function bar() : ?string
  • Unlike Swift, PHP doesn’t have failable initializers. You are supposed to throw exceptions when the initialization fails.
  • When you use namespaces and autoloading, during tests every type will be assumed to be part of project namespace, including RuntimeException. To tell PHP that you want the type from the global PHP namespace and not want to look for a type of this name inside your project namespace, prefix it with a \\RuntimeException.
  • Namespaces in general still look weird: LIBRARYNAME\Namespace1\Namespace2\TypeName. Like DOS paths.
  • PHP closures have explicit capture lists in use(...). For example: function ($param) use ($captureThis) { return $captureThis == $param; }
  • Composer is PHP’s dependency and package manager. Use it to create a project and set up dependencies. If you know npm or rubygems, you know composer.
  • PHPUnit Skeleton shows a simple directory structure for a library that’s separated into lib/APPNAME and tests/APPNAME with PHPUnit and Composer settings
  • PHP Settings type to store public and protected settings.
  • PHP The Right Way is a collection of coding standards; for a beginner like me, this is as good as any convention, so I immediately liked it!
  • PHP Best Practices similarly showed me that you can rely on autoloading nowadays. That’s nice, and with a composer-based package, it also doesn’t require any work on your part.
  • A nice example project setup: OAuth2 Demo PHP is a package that you run as a server, which in turn depends on the OAuth2 Server PHP library. The library is unit tested and does not have a web-facing directory; the server in turn has mostly settings and virtually no logic.

Making os_log public on macOS Catalina

Since macOS 10.15 Catalina, you cannot easily make public logging the default anymore. os_log hides contents from string interpolation by replacing the string with <private>, unless you explicitly annotate the value with %{public}. That’s probably supposed to force developers to think which parts absolutely need to be part of the log and thus reduce accidental logging of private information. Saagar Jha shows how you can enable your dev machine to log everything again.

Xcode 11 Displays Crash Logs in Context of Your Projects

For all throughout human history, you had to symbolicate your user’s crash logs using atos or a 3rd party tool to get human-readable output. Otherwise, you will not know the symbol or method name of your app’s parts that are involved and see memory offsets instead.

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib                 0x00007fff68656e9d objc_msgSend + 29
1   com.apple.AppKit                0x00007fff3e925c4f -[NSView _removeNextPointersToMe] + 829
2   com.apple.AppKit                0x00007fff3e9258f5 -[NSView _removeFromKeyViewLoop] + 203
3   com.apple.AppKit                0x00007fff3f1da8aa -[NSView _finalize] + 830
4   com.apple.AppKit                0x00007fff3e92557a -[NSView dealloc] + 164
5   com.apple.AppKit                0x00007fff3ea2bc42 -[NSControl dealloc] + 148
6   com.apple.AppKit                0x00007fff3ea2bb9f -[NSTextField dealloc] + 124
7   libobjc.A.dylib                 0x00007fff6865eff5 objc_object::rootRelease_underflow(bool) + 339
8   libobjc.A.dylib                 0x00007fff686591f2 objc_release + 162
9   libobjc.A.dylib                 0x00007fff6865a042 (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 812
10  com.apple.CoreFoundation        0x00007fff41362896 _CFAutoreleasePoolPop + 22
11  com.apple.Foundation            0x00007fff434ad8ad -[NSAutoreleasePool drain] + 144
12  com.apple.AppKit                0x00007fff3e9278e5 -[NSApplication run] + 860
13  com.apple.AppKit                0x00007fff3e8f6a72 NSApplicationMain + 804
14  de.zettelkasten.TheArchive      0x000000010b007a79 0x10b003000 + 19065
15  libdyld.dylib                   0x00007fff6927b015 start + 1

But with Xcode 11, double-clicking a .crash file now opens Xcode instead of Console, and you can view the crash log in the context of a project. That’s very nice.

Crash log entries are still not symbolicated – maybe this is different for iOS apps and/or TestFlight where Apple’s servers can take care of re-symbolication? I’m not sure. But this is an interesting new direction that I like to see explored further.

Xcode 11 screenshot of the parsed crash log lines

Also, I cannot figure out how to “close” or detach the crash log again without closing the whole project, yet.

Update 2019-10-14: Vadim Shpakovski (@vadimshpakovski) mentioned on Twitter that you can “close” the crash files by hitting the delete key when you select the crash in the left sidebar. Delete! Of course!

See also:

Processing David Epstein: Range (S01E04)

I uploaded another episode of the video series where I document how someone might process reading notes from a book after reading it. I don’t have any Range related project, so here I’m just processing the book from start to finish instead of looking for anything in particular.

This episode is shorter, because I didn’t find many useful ideas in Chapter 3. And the ideas I did find interesting were not citable, so I had to look the originals up. That took most of the time, but did ultimately not produce many new notes. It’s interesting that after a couple of session I already begin to form an opinion of the quality of Epstein’s research. There’s lots of endnotes, but the quality is … well, enjoy this episode to find out more!

Episode list:

  • Episode 1: Introduction
  • Episode 2: Chapter 1, “The Cult of the Head Start”
  • Episode 3: Chapter 2, “How the Wicked World Was Made”
  • Episode 4: Chapter 3, “When Less of the Same Is More”

→ Blog Archive