Category Archives: geek

On this page:

Emacs Chat: Christopher Wellons

Christopher Wellons (nullprogram.com, github.com/skeeto/) started using Emacs nine years ago and has built all sorts of nifty customizations since, including something that plays Tetris for you. He demonstrates the benefits of having an HTTP server running inside Emacs by using Skewer to interact with a web browser and Impatient-mode to share his syntax-highlighted buffer through the Web. In addition, he covers foreign function interfaces, packages, and other good things. Check it out!

Links: 

Download the MP3

Hmm, maybe I’m not slacking off after all

Even though I’ve got the steady accumulation of DONE tasks showing my slow-but-constant progress, I still sometimes feel like I’m leaving something on the table when it comes to how I use my time. I feel like I’m living with a more relaxed pace, especially compared with the world of work around me or my fuzzed-by-time recollections of pre-experiment and early-experiment days.

Top line = All tasks excluding cancelled ones, bottom line = DONE

Top line = All tasks excluding cancelled ones, bottom line = DONE

I was thinking about how my time use has shifted over the past few years. I compared my percentages in different categories for 2012, 2013, and for 2014 to date. But the numbers say I’m actually spending more time on work and personal projects, and I do seem to manage to check off lots of things on my TODO list. =) So maybe I’m doing okay with this after all, even though sometimes I think I’m slacking off.

Top-level categories:

  • Sleep: Pretty consistent (34.5-36.6%) – this works out to 8.3-8.8 hours a day.
  • Business: Down, then up lately – 24%, 21%, 26%; but I expect this to be a little lower this year, since I’m taking three months off. =) I’ll probably focus on even more writing, drawing, and Emacs geekery then. (And maybe a crash course in a useful skill…)
    Avg hours per week 2012 2013 2014 to date
    Earn 20 15 17
    Build 12 13 18
    Connect 8 7 9
    Total 40 35 44
  • Discretionary: Up, then down – 18%, 22%, 16%
  • Personal care: Pretty consistent (13-14%)
  • Chores/unpaid work: Pretty consistent (7-8%)

As before, the business/discretionary trade-off is really the main thing that moves. The rest of my life stays pretty much the same. The second level of categories is worth looking at too:

  • Writing is pretty consistent at 3%, or roughly 5 hours a week. Still, I think I’d like to write more. What should get reduced? Ah, video games have been soaking up a little time – although they’re exercise too. Hmm, I could intensify that exercise so that I get more out of it. Oh! I’ve been spending more time gardening lately; that could be another reason. I like both of those alternative activities too, and I think they’ll taper off after a while. That’s okay, there’ll be time enough to write more. Besides, some of my writing is filed under Emacs-related time instead. =)
  • Trending up:
    • Drawing (2.0-4.1%): This is good.
    • Planning (0.2-1.5%): Hmm, this is interesting. Am I running into diminishing returns here? Maybe less time planning, more time experimenting.
    • Emacs (0.4-2.8%), and I’m looking forward to spending even more time on this.
    • Relaxing (0.6-2.0%)
  • Trending down:
    • Tidying up, cleaning the kitchen (2.3-1.6%) – about 3 hours a week? I should do more around the house (or maybe I am, and I’m not tracking it properly)
    • Working on Quantified Awesome (1.4-0.8%) – steady-state since I’m happy with the code so far?
    • Reading fiction (1.2-0.4%) – subsumed into other activities
    • Socializing (8.0-1.4%) – big drop here; winter, becoming more selective?
    • Networking (4.7-1.7%) – big drop here too; not networking as actively
    • Biking (2.4-0.7%) – but then it’s still early in the biking season, and I work fewer days too

I’ll continue to focus on gardening for a bit until the garden is more established. I want to exercise and bike more as well. And there’s all sorts of Emacs coolness to learn about and share! =) Writing will have to be content with these little snippets–thinking out loud, sharing what I learn, and other things like that–until I can spend more time focusing on developing ideas. Mostly, the increase in time on other activities seems to be coming from the time I used to spend socializing. I actually like this new balance. The stuff I make and share online seems to lead to more ongoing conversations than those hi-hellos at tech events, and I’m still happy to spend a few hours getting to know people or going somewhere.

I got the time numbers from http://quantifiedawesome.com and a bit of spreadsheet number-crunching, and the task numbers from Emacs + Org Mode + R. =) Yay data!

Playing around with Clojure, Cider, and 4Clojure

4Clojure has a lovely series of exercises to help you practice Clojure. I don’t know much Clojure yet. I’ve basically been taking what I know of Emacs Lisp and trying to cram it into Clojure syntax. (compose is pretty cool!) I should probably read through a Clojure tutorial and some kind of syntax reference. (Hyperpolyglot is neat!) But hey, I’ve gotten through 21 problems so far.

Tom Marble and I were chatting about Clojure, Emacs, and Org Babel. As it turns out, there are lots of ways to interact with 4clojure problems from within Emacs. Tom told me about the 4clojure package by Joshua Hoff, which is probably slightly improved with the following code:

(require 'clojure-mode)
(defun my/4clojure-check-and-proceed ()
  "Check the answer and show the next question if it worked."
  (interactive)
  (let ((result (4clojure-check-answers)))
    (unless (string-match "failed." result)
       (4clojure-next-question))))
(define-key clojure-mode-map (kbd "C-c C-c") 'my/4clojure-check-and-proceed)

That one doesn’t track your progress on the website, though, so you’ll still want to copy and paste the solution yourself.

I like working within Org Mode so that I can easily take notes along the way. Here are the notes I took while figuring out how to get Clojure and Org to work together. http://www.braveclojure.com/basic-emacs/ is nice. http://bzg.fr/emacs-org-babel-overtone-intro.html has a good introduction. Here’s what I used from those:

Install Java (at least version 6), Clojure and Leiningen.

Install the clojure-mode and cider Emacs packages

Evaluate this by moving the point to the #+begin_src line and running C-c C-c

(add-to-list 'package-archives '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-refresh-contents)
(package-install 'clojure-mode)
(package-install 'cider)

And then evaluate this afterwards:

(add-to-list 'org-babel-load-languages '(emacs-lisp . t))
(add-to-list 'org-babel-load-languages '(clojure . t))
(org-babel-do-load-languages 'org-babel-load-languages org-babel-load-languages)
(setq nrepl-hide-special-buffers t
      cider-repl-pop-to-buffer-on-connect nil
      cider-popup-stacktraces nil
      cider-repl-popup-stacktraces t)
(cider-jack-in)

That should let you evaluate this:

(list? '(1 2 3 4))

—————–
And that let me do stuff like this for #27: Palindrome Detector:

(defn __ [x] (= (seq x) (reverse x)))
(list
  (false? (__ '(1 2 3 4 5)))
  (true? (__ "racecar"))
  (true? (__ [:foo :bar :foo]))
  (true? (__ '(1 1 3 3 1 1)))
  (false? (__ '(:a :b :c))))
true true true true true

If all the results are true, then I’ve passed. Yay! In the web interface, __ is where your answers go. Fortunately, it’s also a valid Lisp name, so I can defn a function to replace it when testing locally. The proper answer would probably be something like (fn [x] (= (seq x) (reverse x))) when submitted through the web interface, which is close enough.

it would be great to have something like 4clojure for Emacs Lisp – a site where you can practise solving small, well-defined problems. =) Has someone already written one?

Cobbling together a semi-auto-responder using Emacs, Gnus, and org-contacts

It turns out that lots of people are interested in an e-mail-based course for learning Emacs Lisp. Yay! =) Maybe it’s the idea of bite-size chunks. Maybe it’s the ease of asking questions. Maybe it’s the regular reminders to work on something. Who knows? Whatever the reason, it’s awesome to see so many people willing to join me on this experiment.

Since this is my first time to venture into the world of teaching people online, I wanted to see how far I could push actually doing all the mails myself, instead of just signing up for an Aweber account and handing everyone off to an impersonal autoresponder. I dusted off Gnus, offlineimap, and org-contacts, and started figuring out my workflow. I’ll share how that workflow’s evolving so that you can get a sense of how someone might write little bits of Emacs Lisp to make something repetitive easier.

For the first little while, I got by with using C-x r s (copy-to-register) and C-x r i (insert-register) to store the text that I needed.
Sometimes I needed to paste in the welcome message and checklist, and sometimes I needed to paste in the first lesson. By using registers, I could insert whatever I wanted instead of going through the kill ring. I also had another bit of templated code in yet another register so that I could easily create an org-contacts entry for the person whose mail I was replying to. In the beginning, I used tasks under each person’s heading to indicate that I had sent them the checklist or that I had sent them the first lesson. Eventually, I changed my org-contacts notes so that the TODO state of each person showed which lesson I was going to send them next, or CHECKLIST if I was waiting for their reply to the checklist. I also set up Org so that it would automatically log when the TODO state was changed.

#+TODO: TODO | DONE
#+TODO: CHECKLIST(c!) BEGINNER1(1!) BEGINNER2(2!) BEGINNER3(3!) BEGINNER4(4!) FULL(f!) | FINISHED(x!)
#+TODO: | CANCELLED

* Who
** CHECKLIST Jane Smith ...
** BEGINNER1 John Smith
   SCHEDULED: <2014-05-28 Wed>
   :PROPERTIES:
   :EMAIL: [email protected]
   :END:
(notes from the messages, etc.)

I wrote some code to make it easier to send someone a checklist and create a note for them in my org-contacts file. I bound it to C-c e c for convenience.
(The bind-key function is defined by a package.)

(setq sacha/elisp-course-checklist-body "... really long text here...")
(defun sacha/elisp-course-checklist ()
  "Copy this message and put it at the end as a checklist item. 
Start a message with the checklist."
  (interactive)
  (gnus-summary-scroll-up 1)
  (with-current-buffer gnus-article-buffer
    (let ((message (buffer-substring-no-properties (point-min) (point-max)))
          (email (cadr (org-contacts-gnus-get-name-email))))
      (with-current-buffer "elisp-course.org"
        (save-excursion
          (goto-char (point-max))
          (save-excursion
            (insert "\n** " message)
            (org-set-property "EMAIL" email)
            (org-todo "CHECKLIST"))))))
  (gnus-summary-followup-with-original nil)
  (goto-char (point-max))
  (insert sacha/elisp-course-checklist-body))
(bind-key "C-c e c" 'sacha/elisp-course-checklist)

This made it easier for me to read the starred messages from my inbox and use C-c e c to get a head start on processing people’s introductory messages.
Yay! I used the register trick to help me reply to people who were ready for the first lesson. After the first few replies, I noticed that the attachment code was fine even if I put that in the register too, so I added it as well.

Things got more complicated when I started processing lesson 2. I didn’t want to have to set up and remember lots of different registers, and I didn’t want to manually update the TODO states either. So I started defining functions that I could call with keyboard shortcuts:

(defun sacha/elisp-course-1 ()
  (interactive)
  (let ((marker (org-contacts-gnus-article-from-get-marker)))
    (if marker
        (org-with-point-at marker
          (org-todo "BEGINNER2"))))
  ;; Find the person's contact record
  (gnus-summary-scroll-up 1)
  (gnus-summary-followup-with-original nil)
  (message-goto-subject)
  (message-delete-line)
  (insert (concat "Subject: " sacha/elisp-course-1-subject "\n"))
  (goto-char (point-max))
  (insert sacha/elisp-course-1-body))
(bind-key "C-c e 1" 'sacha/elisp-course-1)
(defun sacha/elisp-course-2 ()
  (interactive)
  (let ((marker (org-contacts-gnus-article-from-get-marker)))
    (if marker
        (org-with-point-at marker
          (org-todo "BEGINNER3"))))
  ;; Find the person's contact record
  (gnus-summary-scroll-up)
  (gnus-summary-followup-with-original nil)
  (goto-char (point-max))
  (insert sacha/elisp-course-2-body))
(bind-key "C-c e 2" 'sacha/elisp-course-2)

Really, though, it doesn’t make sense to have a lot of duplicated code. So I wrote some code that would use the person’s TODO keyword to look up the message to send them, and then move them to the next keyword. Now I don’t need sacha/elisp-course-1 or sacha/elisp-course-2 any more.

(setq sacha/elisp-course-info
      `(("CHECKLIST" nil ,sacha/elisp-course-checklist-body)
        ("BEGINNER1" ,sacha/elisp-course-1-subject ,sacha/elisp-course-1-body)
        ("BEGINNER2" ,sacha/elisp-course-2-subject ,sacha/elisp-course-2-body)))

(defun sacha/elisp-course-process (subject body &optional state)
  "Process this course entry."
  (if (derived-mode-p 'org-mode)
      (progn
        ;; Move this node to the next state and compose a message
        (if state (org-todo state))
        (org-todo 'right)
        (message-mail (org-entry-get (point) "EMAIL") subject)
        (goto-char (point-max))
        (insert body))
    ;; Doing this from Gnus; find the person's info
    (let ((marker (org-contacts-gnus-article-from-get-marker)))
      (if marker (org-with-point-at marker
                   (if state (org-todo state))
                   (org-todo 'right)))
      ;; Compose a reply
      (gnus-summary-scroll-up 1)
      (gnus-summary-followup-with-original nil)
      (message-goto-subject)
      (message-delete-line)
      (insert (concat "Subject: " subject "\n"))
      (goto-char (point-max))
      (insert body))))

(defun sacha/elisp-course-guess-and-process (&optional state)
  (interactive (list (if current-prefix-arg (read-string "State: "))))
  (let ((current-state
         (or state (elt
                    (if (derived-mode-p 'org-mode)
                        (org-heading-components) 
                      (let ((marker (org-contacts-gnus-article-from-get-marker)))
                        (if marker (org-with-point-at marker (org-heading-components)))))
                    2))))
    (sacha/elisp-course-process
     (elt (assoc current-state sacha/elisp-course-info) 1)
     (elt (assoc current-state sacha/elisp-course-info) 2)
     state)))
(bind-key "C-c e e" 'sacha/elisp-course-guess-and-process)

Come to think of it, I should totally have it schedule the next update for the next Wednesday, too. ;) That’s just (org-schedule "+wed"). Neat, huh?
And I’m sure there are all sorts of ways the code can be simpler, but it works for me at the moment, so hooray!

I really like this approach. It lets me pull in standard information while also letting me customize the messages and how it fits into my task tracking. I can’t get that with Gmail (even with canned responses), and I’m not sure any CRM is going to be quite as awesome as this. I can’t wait to see how else we’ll tweak this as we go through more conversations. I’d like to get better at:

  • having a consistent place where I can process all the messages and make sure nothing falls through the cracks; I currently star messages to make sure I process them, since the Gmail label folder in IMAP seems to be missing some messages
  • seeing all Gnus conversations related to an org-contacts entry
  • reaching out to people proactively with the next lesson, even if they haven’t e-mailed me (or maybe I should wait for them?)

Anyway, that’s an example of writing a little bit of Emacs Lisp in order to connect different packages. Gnus handles mail, Org handles notes, org-contacts links the two together, and with a little bit of custom code, I can make the combination fit what I want to do. I read the source code of org-contacts to find out how I could look up the appropriate note, and I looked at org-shiftright to find out how to move things to the next TODO state. If you know something that works roughly like what you want it to work, you can find out how it does things and then copy that.

As for the course itself: I’ve been sending people links to the HTML output, attached .txt files (with -*- mode: org -*-) so they can open it in Emacs if they want, and inline text so that they can skim it briefly in their e-mail client if they want to. I’m not perfectly happy with the plain-text formats, but it seems to be a reasonable compromise, and so far people have been able to deal with it. I’ve been improving pieces of it based on feedback on clarity, suggestions for good examples, and so on. I didn’t take all the feedback; after thinking about some of the suggestions, I still preferred it my way. It’s shaping up quite nicely, though!

If you’re curious about the beginner’s course on reading Emacs Lisp, e-mail me at [email protected] and we’ll see how this works out. I’m certainly learning a lot. =)

Emacs Chat: Bozhidar Batsov

UPDATE 2014-06-13: The transcript is now available.

Bozhidar Batsov (emacsredux.com) shares how he got into Emacs and Emacs Lisp. He also demonstrates cool features from Prelude and Projectile, which are great if you do a lot of programming. Check it out!

Quick Links: https://twitter.com/bbatsov , https://twitter.com/emacs_knight , http://emacsredux.com , https://github.com/bbatsov/prelude , https://github.com/bbatsov/projectile . If you like his work, there’s https://www.gittip.com/bbatsov/

Guest: Bozhidar Batsov

For the event page, you may click here.

Want just the audio? Get it from archive.org: MP3

Transcript here!

Check out Emacs Chat for more interviews like this. Got a story to tell about how you learned about or how you use Emacs? Get in touch!

Planning an e-mail-based course for Emacs Lisp

I’ve been working on an Emacs Lisp beginner’s course, something focused on helping people become more comfortable configuring Emacs. The web-based guide is taking shape quite nicely, but it’s still a lot of scrolling, and it can still feel overwhelming for newbies. I think it might make sense to offer it as an e-mail course. That way, I can spread the lessons out, help people with their questions, and improve things based on people’s feedback.

2014-05-12 How can I take Learn How to Read Emacs Lisp to the next level #emacs #packaging #writing #teaching

2014-05-12 How can I take Learn How to Read Emacs Lisp to the next level #emacs #packaging #writing #teaching

I can improve the guide by adding more structure, examples, exercises, and so on. I’ve requested several books on e-learning and course design, and I’m looking forward to learning more over the years. And I can also improve it by testing it with people… =)

2014-05-14 Planning an e-mail-based course for Emacs Lisp #emacs #teaching

2014-05-14 Planning an e-mail-based course for Emacs Lisp #emacs #teaching

I floated the idea on Twitter and lots of people e-mailed me to join. Instead of setting up an autoresponder, I decided that I would do things by hand as much as I could. That way, I can personalize the messages based on people’s interests and configuration, and I can enjoy more of the back-and-forth conversation.

After getting annoyed with the SSL hassles of setting up Gnus on Windows, I decided to just use my Linux-based virtual machine for handling mail. That was pretty straightforward, although for some reason, my IMAP view of Gmail doesn’t have all of the messages under a label. It just means that I have to manually re-check the messages to make sure nothing slips through the cracks.

I used an Org file to keep notes on each person, including TODOs under each of them. I sent everyone a checklist to see which section we should start with. A few people are starting at the beginning, and others will get the e-mails once I’ve updated those sections. Text registers (C-x r s) were really helpful since I was pasting different things into different e-mails. I’m still figuring out the workflow for this, and I’m sure I’ll automate pieces of it as more people move through the course.

I’ve sent the first section to some people already, including the Org version in the e-mail body and as an attachment, and linking to the web-based version. The Org version is a little more cluttered than the text export, but the text export uses box quotes, so I figured the Org version was the best to start with.

2014-05-16 A plan for delivering the Emacs Lisp course #emacs #teaching

2014-05-16 A plan for delivering the Emacs Lisp course #emacs #teaching

Want to be part of this? E-mail me at [email protected]