On this page:

Keeping a process journal

I post a lot of notes on my blog, and I keep more snippets in my personal files so that I can learn from them and turn them into blog posts later. There’s something still missing here, though, something I can tweak. Reading Louise DeSalvo’s The Art of Slow Writing (2014), I recognized part of what was missing in her description of process journals. Here’s a relevant excerpt:

p82. In Steinbeck’s April 9, 1951, entry, written as he composed East of Eden, he evaluates his desk’s new surface, determines how to keep his pencil drafts from smudging, figures when it’s best to do his laundry, plans his week’s work, determines to try to write somewhat more, assesses his energy level, discusses his fear of interruptions derailing his work, pledges maintaining his focus to complete the work by managing his work in his journal.

… Here we see Steinbeck deliberately managing his work before he begins the labor of writing. He evaluates his tools–his desk and pencils–shapes his day, sketches the new scene, deals with his emotions, summarizes and evaluates his progress, and figures how to move his work forward. And Steinbeck engaged in this process each day.

(Oh! I love writers Have Thought About Stuff. It’s like the way programmers also tend to apply tools and systems to more than just programming… Come to think of it, I wonder how geeks of other persuasions end up applying their geekdoms to the rest of life!)

Anyway: a place to clear your thoughts, a deliberate reflection on processes and practices, and perhaps a way to browse through those entries in chronological order or based on context… My blog is a little like that, but there’s so much more stuff than I publish on it and it will continue to be like that if I insist on keeping to my mostly-one-post-a-day limit and scheduling things in advance.

I’ve been keeping a small journal–just a few keywords per day, scribbled into a paper notebook shortly before going to bed–for the past three months. It’s amazing how that’s enough to help me get back to those days, remembering more details than I could without them.

Org Mode for Emacs has built-in support for quickly capturing notes and organizing them in an outline by date. I think I’ll use that for at least quick memories, since those make sense in a timeline, and then I’ll keep the larger notes in a topic-focused outline. Technically, I’m using a computer, so I should be able to organize things both ways: using tags and links to connect items by topic, and using Org’s log view to view things by date.

It would be good to start with this kind of deliberate, constant improvement in a few areas of my life:

  • Web development: I’d like to learn more about design, and also developing better code
  • Writing: I can pay more attention to the questions I formulate and how I explore them
  • Cooking: Hmm, more notes on how we make the recipes and what the cooking process is like?

If I make Fridays the days I focus on harvesting my notes from the previous week and plan some ideas for the next one, that would fit in nicely with reviewing this process journal and seeing what I can build on the next week. (I’m still going to post random snippets during the week, probably… =) )

Beginner web dev tip: Use Inspect Element to learn more about HTML and CSS on a page

One of the neat things about learning web development is that the Web is full of examples you can learn from. You can use your browser’s View Page Source or View Source command (available from the right-click menu in Google Chrome, Mozilla Firefox, or Internet Explorer). An even better way to explore, though, is to use the Inspect Element action from the right-click menu in those browsers. If you right-click on the item you want to learn more about, you’ll be able to see the HTML and the current CSS applied to the page.

I use Google Chrome most of the time, so I’ll show you Inspect Element screen in that browser. Here we’re looking at the button on CSS-Tricks.com:

2014-11-10 15_37_06-CSS-Tricks.png

You’ll see the HTML on the left side and the CSS on the right. You can check or uncheck different CSS rules, and you can double-click on things to edit them. Check out the right-click menus for even more options.

Sometimes you may need to click on a different element in order to see the CSS rules that are relevant to what you’re curious about. As you hover over different elements, you’ll see them highlighted on the page.

If you click on the Console tab, you can experiment with Javascript too. If you want to view both the inspect element information and the Javascript console at the same time, click on the icon that looks like a > on the right side. This is particularly handy if you have a large screen.

Hope that helps!

First steps towards Javascript testing

I know, I know, it’s about time I got the hang of this. Better late than never, right? =) Anyway, I spent some time going through tutorials for QUnit and Jasmine. For QUnit, I followed this Smashing Magazine tutorial on Javascript unit testing. I modified the code a little bit to add the Z timezone to the test data, since my tests initially didn’t pass.

test.html

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title>Refactored date examples</title>
    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.15.0.css" />
    <script src="http://code.jquery.com/qunit/qunit-1.15.0.js"></script>
    <script src="prettydate.js"></script>
    <script>
     test("prettydate.format", function() {
       function date(then, expected) {
         equal(prettyDate.format('2008/01/28 22:25:00Z', then), expected);
       }
       date("2008/01/28 22:24:30Z", "just now");
       date("2008/01/28 22:23:30Z", "1 minute ago");
       date("2008/01/28 21:23:30Z", "1 hour ago");
       date("2008/01/27 22:23:30Z", "Yesterday");
       date("2008/01/26 22:23:30Z", "2 days ago");
       date("2007/01/26 22:23:30Z", undefined);
     });
     function domtest(name, now, first, second) {
       test(name, function() {
         var links = document.getElementById('qunit-fixture').getElementsByTagName('a');
         equal(links[0].innerHTML, 'January 28th, 2008');
         equal(links[2].innerHTML, 'January 27th, 2008');
         prettyDate.update(now);
         equal(links[0].innerHTML, first);
         equal(links[2].innerHTML, second);
       });
     }

     domtest("prettyDate.update", '2008-01-28T22:25:00Z', '2 hours ago', 'Yesterday');
     domtest("prettyDate.update, one day later", '2008-01-29T22:25:00Z', 'Yesterday', '2 days ago');
    </script>
</head>
<body>
  <div id="qunit"></div>
  <div id="qunit-fixture">
    <ul>
      <li class="entry" id="post57">
        <p>blah blah blah…</p>
        <small class="extra">
          Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-28T20:24:17Z">January 28th, 2008</a></span>
          by <span class="author"><a href="/john/">John Resig</a></span>
        </small>
      </li>
      <li class="entry" id="post57">
        <p>blah blah blah…</p>
        <small class="extra">
          Posted <span class="time"><a href="/2008/01/blah/57/" title="2008-01-27T22:24:17Z">January 27th, 2008</a></span>
          by <span class="author"><a href="/john/">John Resig</a></span>
        </small>
      </li>
    </ul>
  </div>
</body>
</html>

For practice, I converted the QUnit tests to Jasmine. The first part of the test was easy, but I wanted a clean way to do the HTML fixture-based tests for prettydate.update too. Jasmine-JQuery gives you a handy way to have HTML fixtures. Here’s what my code ended up as:

spec/DateSpec.js

describe("PrettyDate.format", function() {
    function checkDate(name, then, expected) {
        it(name, function() {
            expect(prettyDate.format('2008/01/28 22:25:00Z', then)).toEqual(expected);
        });
    }
    checkDate("should display recent times", '2008/01/28 22:24:30Z', 'just now');
    checkDate("should display times within a minute", '2008/01/28 22:23:30Z', '1 minute ago');
    checkDate("should display times within an hour", '2008/01/28 21:23:30Z', '1 hour ago');
    checkDate("should display times within a day", '2008/01/27 22:23:30Z', 'Yesterday');
    checkDate("should display times within two days", '2008/01/26 22:23:30Z', '2 days ago');
});
describe("PrettyDate.update", function() {
    function domtest(name, now, first, second) {
       it(name, function() {
           loadFixtures('test_fixture.html');
           var links = document.getElementById('qunit-fixture').getElementsByTagName('a');
           expect(links[0].innerHTML).toEqual('January 28th, 2008');
           expect(links[2].innerHTML).toEqual('January 27th, 2008');
           prettyDate.update(now);
           expect(links[0].innerHTML).toEqual(first);
           expect(links[2].innerHTML).toEqual(second);
       });
    }
    domtest("prettyDate.update", '2008-01-28T22:25:00Z', '2 hours ago', 'Yesterday');
    domtest("prettyDate.update, one day later", '2008-01-29T22:25:00Z', 'Yesterday', '2 days ago');
});

jasmine.html

<!DOCTYPE HTML>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Jasmine Spec Runner v2.0.2</title>

  <link rel="shortcut icon" type="image/png" href="lib/jasmine-2.0.2/jasmine_favicon.png">
  <link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.2/jasmine.css">

  <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
  <script type="text/javascript" src="lib/jasmine-2.0.2/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-2.0.2/jasmine-html.js"></script>
  <script type="text/javascript" src="lib/jasmine-2.0.2/boot.js"></script>
  <script type="text/javascript" src="jasmine-jquery.js"></script>

  <!-- include source files here... -->
  <script type="text/javascript" src="prettydate.js"></script>

  <!-- include spec files here... -->
  <script type="text/javascript" src="spec/DateSpec.js"></script>

</head>

<body>
</body>
</html>

I’m looking forward to learning how to use Jasmine to test Angular applications, since behaviour-driven testing seems to be common practice there. Little steps! =)

Emacs: Limiting Magit status to a directory

I’m probably using Git the wrong way. In addition to the nice neat repositories I have for various projects, I also sometimes have a big grab-bag repository that has random stuff in it, just so that I can locally version-control individual files without fussing about with Emacs’ numbered version systems. Sometimes I even remember to organize those files into directories.

When you have a Git repository that’s not one logical project but many little prototypes, using Magit status to work across the entire project can sometimes mean running into lots of distracting work in progress. I wanted a way to limit the scope of Magit status to a specific directory.

Here’s the experimental code I came up with:

      (defvar sacha/magit-limit-to-directory nil "Limit magit status to a specific directory.")
      (defun sacha/magit-status-in-directory (directory)
        "Displays magit status limited to DIRECTORY.
Uses the current `default-directory', or prompts for a directory
if called with a prefix argument. Sets `sacha/magit-limit-to-directory'
so that it's still active even after you stage a change. Very experimental."
        (interactive (list (expand-file-name
                            (if current-prefix-arg
                                (read-directory-name "Directory: ")
                              default-directory))))
        (setq sacha/magit-limit-to-directory directory)
        (magit-status directory))

      (defadvice magit-insert-untracked-files (around sacha activate)
        (if sacha/magit-limit-to-directory
            (magit-with-section (section untracked 'untracked "Untracked files:" t)
              (let ((files (cl-mapcan
                            (lambda (f)
                              (when (eq (aref f 0) ??) (list f)))
                            (magit-git-lines
                             "status" "--porcelain" "--" sacha/magit-limit-to-directory))))
                (if (not files)
                    (setq section nil)
                  (dolist (file files)
                    (setq file (magit-decode-git-path (substring file 3)))
                    (magit-with-section (section file file)
                      (insert "\t" file "\n")))
                  (insert "\n"))))
          ad-do-it))

      (defadvice magit-insert-unstaged-changes (around sacha activate)
        (if sacha/magit-limit-to-directory
            (let ((magit-current-diff-range (cons 'index 'working))
                  (magit-diff-options (copy-sequence magit-diff-options)))
              (magit-git-insert-section (unstaged "Unstaged changes:")
                  #'magit-wash-raw-diffs
                "diff-files"
                "--" sacha/magit-limit-to-directory
                ))
          ad-do-it))

      (defadvice magit-insert-staged-changes (around sacha activate)
        "Limit to `sacha/magit-limit-to-directory' if specified."
        (if sacha/magit-limit-to-directory
            (let ((no-commit (not (magit-git-success "log" "-1" "HEAD"))))
              (when (or no-commit (magit-anything-staged-p))
                (let ((magit-current-diff-range (cons "HEAD" 'index))
                      (base (if no-commit
                                (magit-git-string "mktree")
                              "HEAD"))
                      (magit-diff-options (append '("--cached") magit-diff-options)))
                  (magit-git-insert-section (staged "Staged changes:")
                      (apply-partially #'magit-wash-raw-diffs t)
                    "diff-index" "--cached" base "--" sacha/magit-limit-to-directory))))
          ad-do-it)))

Now I can bind C-x v C-d to sacha/magit-status-in-directory and get something that lets me focus on one directory tree at a time. You can see my config in context at http://sachachua.com/dotemacs#magit

It feels like I’m probably trying to do things the Wrong Way and I should probably just break things out into separate repositories. Even though I realized this early on, though, I ended up digging into how to implement it just for the sheer heck of seeing if Emacs would let me do it. =) I don’t know how often I’ll use this function, but it was a good excuse to learn more about the way Magit works.

It took me an hour to find my way around magit.el, but that’s more my fault than the code’s. At first I tried to override magit-diff-options, but I eventually remembered that the paths need to come at the end of the command line arguments. (I had a cold! My brain was fuzzy!) It was fun poking around, though. Looking forward to learning even more about Magit!

My current book workflow

I pick up a lot of information from books. We have an amazing public library system, and I’m at the library at least once a week. Here’s my current workflow for reading and taking notes on books.

Finding books to read: I check the library’s new releases for interesting titles. I have a Ruby script that extracts the information and puts it into a text file. I delete anything that doesn’t interest me, and then I copy the IDs into another Ruby on Rails system that requests all the books for me. Sometimes I search for books by topic or get recommendations from other people.

Reading books: I’ve successfully weaned myself off the bad habit of folding over the corners of book pages (dogearing). Instead, I use book darts to point to the passages that I want to copy into my notes. I have only one tin of them, so that encourages me to harvest the notes from books before moving on to other books. If I don’t have my book darts handy, I use strips of paper, but they’re not as awesome.

I also keep paper and pen handy (index cards, or the small notebook I always have in my vest) so that I can take notes on ideas, questions, and other things that aren’t directly in the text of the book.

I mostly read non-fiction, so that’s easy to skim for interesting bits. I usually check the table of contents to get an overview of the book. I have no qualms about jumping straight to specific chapters and then wandering around a bit, or even picking just a few pages out of a book. I rarely use the index (and most books don’t have a good one anyway), although maybe I should check that more often.

Taking notes: I keep individual text files named after the title of the book (and sometimes authors as well). I usually include the ISBN so that I can easily look up a book later. The text files contain quotes, ideas, TODOs, and other notes.

If no one else is around and I feel like patiently dealing with speech recognition, I open Dragon Naturally Speaking and dictate the passages from the books. This helps me train Dragon’s speech model as well, which might be handy someday. If other people are around, though, I’ll just type in the segments from the book.

I usually type in my paper notes so that they’re more coherent (since I tend to write keywords instead of full thoughts). If I want to scan my index cards or notebook pages, I pop those into my Fujitsu Scansnap ix500 and scan them as JPG. I convert the JPGs to PNG and rename them with the date and title, and then I move them to a folder that gets automatically imported into Evernote. Evernote lets me search for text, and it also tries to find text even in scans of handwriting. It’s not perfect, but it’s decent, and I’ve learned to write more clearly because of that.

Looking things up: Since most of my notes are text, I can use grep to search through them.

Sharing what I know: I sometimes include excerpts or ideas in my blog posts. When I do, I link to the blog post from my text notes as well, so I can see what I’ve digested further and shared. If I’m reading a book that I know I’ll want to share with other people later (or if the authors have asked me nicely =) ), I sometimes visually summarize the book.

Following up on ideas: I add TODOs to my Org Mode agenda. I can also schedule reminders for things. I’m a little hesitant to add my books directory to the org-agenda-files list that Org Mode checks for TODO items (I have hundreds of book notes now!), so I’ve defined a custom agenda command that looks at just the book directory instead. Alternatively, it’s easy enough to grep the TODO keyword.

Planned improvements: I’m curious about the idea of a syntopicon, which I picked up from Adler and van Doren’s How to Read a Book. A syntopicon is a map of ideas across multiple books. With Org Mode’s support for indexing and links, I should be able to make something like it. I’m also looking forward to writing more about what I do with what I’m learning from books. This helps me challenge myself to learn actively instead of just letting a book flow through my brain.

Mmm, books!

If you’re curious, you can read about my past workflows:

Weekly review: Week ending November 14, 2014

I’m going to be out of commission for the next little while, probably resurfacing sometime late December. I’ve scheduled lots of posts in advance (I learned a lot over the past two weeks!), so you’ll still keep reading stuff, but I might be even slower to respond to things and I’ll probably stay close to home. Nothing to worry about, just something I have to take care of. Good thing there’s enough slack in my life for stuff like this.

Blog posts

Sketches

Focus areas and time review

  • Business (23.2h – 13%)
    • Earn (9.3h – 39% of Business)
      • E1: Plan how I can work from home for the next few weeks
      • Earn: E1: 1-2 days of consulting
    • Build (8.4h – 36% of Business)
      • Set up faster searching with ace-jump, isearch, helm-swoop
      • Drawing (1.4h)
      • Delegation (0.0h)
      • Packaging (0.0h)
      • Paperwork (1.5h)
        • Review bookkeeper feedback for tax return
    • Connect (5.5h – 23% of Business)
      • Coach Lucas on programming
  • Relationships (16.4h – 9%)
    • Follow up on insurance paperwork
  • Discretionary – Productive (15.9h – 9%)
    • Emacs (0.3h – 0% of all)
    • Quantified Awesome
      • Add want interface for groceries
      • Fix edit screen
      • I can restore an item
      • I can clear all crossed-off items
      • I can see when it was last synchronized
      • Our lists are synchronized
    • ER for I2
    • Cancel GICs
    • File insurance claims
    • Find a Japanese plain past tense practice tool
    • Find a Tableau e-book and put it on my laptop/tablet
    • Find an e-book for learning Japanese and put it on my laptop & tablet
    • Go through a Jasmine tutorial
    • Go through a QUnit tutorial
    • Minna no Nihongo Chapter 13-16
    • Move my dentist appointment
    • Set up folder synchronization for my tablet
    • Write about beginner steps for testing
    • Writing (7.5h)
  • Discretionary – Play (12.9h – 7%)
  • Personal routines (24.5h – 14%)
  • Unpaid work (4.5h – 2%)
  • Sleep (70.7h – 42% – average of 10.1 per day)