Is Cursive Virtuous?

Irreal has a large corpus on the problems with cursive handwriting (see here, here, here, here, here, here, and here) but I haven’t written about it for a while. I was going through my queue of unpublished blog ideas and came across this New Yorker article on The Lost Virtue of Cursive by Mark Oppenheimer.

Oppenheimer begins with a nostalgia-soaked story of writing his daughter longhand letters while she was at camp and how it reminded him of getting such letters from his parents when he was a child at camp. He goes on to say how he always gets a warm feeling when he reads about efforts to keep cursive in the curriculum:

When I read that Washington state is now considering Senate Bill 6469, “an act related to requiring that cursive writing be taught in common schools,” I gave a little fist pump in the air.

But then he writes, “This is sheer nonsense, of course.” Of course it is. He admits that it’s just nostalgia and snobbery. It’s fine to bring up memories of those golden feelings one got as a child upon receiving a letter from Mom or Dad but that’s no reason to inflict cursive on children who neither want nor need it.

If this subject interests you, Anne Trubek, whom I’ve mentioned before, has a book out on The History and Uncertain Future of Handwriting. I really enjoyed the articles she wrote on the subject and am looking forward to reading her book.

Posted in General | Tagged | 4 Comments

I Stand Corrected…

Last Week I wrote that I’d finally gotten mu4e working and that after I moved to elfeed, I would have everything except browsing and iMessage running under Emacs. I remarked that I didn’t expect to have iMessage or a (full-featured) browser working under Emacs anytime soon so that once I got elfeed going, I would be as Emacs-centric as I was going to get.

It turns out that I was wrong about iMessage. On a whim, I asked DuckDuckGo if there were any packages for using iMessage from within Emacs and to my surprise there is one. Chad Sahlhoff has an iMessage for Emacs package available on GitHub. It’s not available in Elpa, which is probably why I missed it at first.

The package needs Helm, which I don’t use, so I haven’t installed it yet. After a quick look at the code, it doesn’t seem like it would be difficult to use Ivy or Ido instead. Maybe I’ll take a closer look as soon as I get time.

More generally, I’m really enjoying mu4e and it really does change the way you deal with email. The tight coupling with Org mode means that every email can be dealt with at the time you read it—even if “dealing with it” means putting it on a TODO list for later action—so my INBOX is always empty when I finish an email session. No more keeping an email around even for a couple of hours. And did I mention no mouse?

I now spend almost all my time in Emacs or Safari. There’s simply no reason to use other standalone applications except for occasional special tasks. For you dedicated Emacsers, I can’t recommend this way of life enough. It just makes your day a whole lot easier and pleasanter.

Posted in General | Tagged | 12 Comments

Fire Adtech

Irreal readers who have been around for a while know of my deep and abiding hatred for adtech, a term used here to mean the technology that advertisers use to spy on and track Web users. I’ve written before that I consider legitimate advertising a fair cost for the content that it’s paying for but I really, really don’t like tracking. As a partial fix for that I use Ghostery to block tracking ads. Sadly for the advertisers, that means that almost all ads are blocked but that’s on the advertisers. I have the “do not track” bit set on my browsers but, of course, that’s almost universally ignored. Hence Ghostery.

Doc Searls over at Art+Marketing has an article up entitled Brands need to fire adtech. I can only agree. Searls explains in detail why adtech is a terrible practice, why it’s mostly fraud, how it’s a major malware vector, and, most importantly for advertisers, why it doesn’t work. The recent kerfuffle involving Google ads appearing next to what many consider “offensive content” could finally be the last straw. Many companies are refusing to place ads with YouTube and more and joining the movement.

In the meantime, the EU will make tracking illegal starting in May 2018. The fines for breaking that law are truly breathtaking. That doesn’t help those of us in the U.S. of course but users are getting better and better tools with which to fight back. Ghostery and its siblings are only the beginning. Searls says that new technology is coming that will allow advertisers to make money without resorting to the despicable practice of tracking and spying on their customers. It can’t come too soon.

Posted in General | Tagged | Leave a comment

Ivy 0.9.0

If you’re an Ivy user, you’ll be delighted to know that abo-abo has released the latest version, 0.9.0. Take a look at his blog for an overview of what’s new. If you aren’t using Ivy, you should definitely give it a try. I got turned on to it by this video from Mike Zamansky, and now I wouldn’t want to be without it.

Posted in General | Tagged | Leave a comment

A Better RETURN for Org

John Kitchin has an interesting piece of Elisp that helps when you’re writing in structured Org mode. If you’re in a bullet list, for example, you can type Meta+Return (or is it Ctrl+Return? I always get it wrong) at the end of an item to automatically begin another list item. Kitchin’s code allows you to just type return and it will do the right thing. It’s return-dwim. A double Return will end the structuring and do what a normal Return does now.

The code works for bullet lists, headings, and tables. I like it because I don’t have to stop and think which modifier key to use or, worse yet, undo the change and try the other modifier. If you do a lot of writing in Org mode, you should probably try Kitchin’s code out. It’s short and easy to paste into your init.el and if you don’t like it, you can just delete it. I’ve been using it for a couple of days and I’m still not sure if I’m going to keep it but, as I said, it’s easy to delete if I decide I don’t like it.

Posted in General | Tagged , | Leave a comment

Publishing a Book with Leanpub and Org Mode

Angelo Basile has a nice post on publishing a book with Leanpub and Org Mode. I’ve written about this before when I discussed Lakshmi Narasimhan’s workflow with Leanpub. Narasimhan used Dropbox, which some may find inconvenient so Basile employs an alternative method that uses BitBucket (or GitHub if you prefer).

I’ve never published with Leanpub so I don’t know how they are to work with but you certainly couldn’t ask for an easier publishing pipeline. If you use Basile’s method, you simply

  • Set up a new book with Leanpub (they say it takes 30 seconds)
  • Set up a repository for the book on BitBucket or GitHub
  • Add a file, Book.txt, that tells Leanpub the names (and order) of your chapters
  • Write your book adding the file or files to Book.txt
  • Use Leanpub’s publishing mechanism to preview or publish your book with a single click

Leanpub wants their input in Markdown but Juan Reyero has an Org mode to Leanpub Markdown exporter that will take your Org files and output them in Leanpub compatible Markdown (Markua). You can keep both sets of files in your repository as long as Book.txt has only the names of the Markdown files in them.

Be sure to take a look at Narasimhan’s post too because he has some Elisp to automate almost everything but the writing. If you want to self publish, it’s hard to imagine an easier way of doing so.

Posted in General | Tagged , | Leave a comment

Hacker Archetypes

Eric Raymond (ESR) has an interesting post on hacker archetypes. The list grew out of a discussion between ESR and one of his regular readers, Susan Sons. At the moment, they’ve identified 8 archetypes. You’ll want to read his post to see what they are and where you fit in but here’s an example to give you the flavor.

Algorithmicists:

  • Good at algorithms and intricate coding
  • High tolerance for complexity
  • Good mathematical intuition
  • Likes correctness proofs and thinks in terms of invariants
  • Tends to gravitate to compiler writing and crypto
  • Often has poor social skills
  • Tends to fail by excessive cleverness

That’s just the first archetype; there are 7 more and all are described in more detail than just the list of traits I gave above. ESR says that no hacker is only one of the archetypes. He describes himself as exhibiting the traits of three of them although one does dominate. That’s probably true of most of us.

Head on over to Armed and Dangerous and see which archetypes apply to you.

Posted in General | Tagged | Leave a comment

A Simple Programming Praxis Solution in Elisp

Programming Praxis has a simple problem that is meant to explore how easy your favorite programming language makes it to work with strings. The problem is to double every blank in a string. That’s pretty simple but some languages make you deal with string allocation or perhaps, in the case of languages with immutable strings, repeatedly allocate new strings.

I have two solutions for this using Elisp. The first is a sort of direct solution that doesn’t think too hard about the special functions Emacs has for dealing with strings.

(defun double-blanks (string)
  (with-temp-buffer
    (dolist (ch (string-to-list string))
      (insert ch)
      (if (eql ch ? ) (insert ? )))
    (buffer-string)))

This code deals with the fact that strings in Elisp are immutable by doing all the work in a temporary buffer as I discussed in this post. Except for the temporary buffer trick, it’s pretty much what any programmer would write. Of course, that string-to-list call is going to do a lot of consing, so for a really long string it might make sense to get the string characters by hand.

Of course, this is Emacs so there’s a prebuilt solution.

(defun double-blanks (string)
  (replace-regexp-in-string " " "  " string))

The replace-regexp-in-string function works by building up a list of matches and combining the list into a single string at the end so it also avoids the problem a immutable strings. If there are a lot of blanks, replace-regexp-in-string is going to do a lot of consing too.

If you’re dealing with large strings with lots of blanks, the best strategy is probably to combine the two approaches above: use a regular expression search for the blanks and build the output string in a buffer as you find them. That wouldn’t be hard and makes a good exercise for anyone interested in learning Elisp.

UPDATE [2017-04-10 Mon 13:49]: In the comments Phil remarks that string-to-list isn’t very efficient and suggests another strategy. I replied that it would be interesting to see if my (unimplemented) strategy or his would be more efficient and said that perhaps I’d try them out and report back. Phil, being Phil, took care of that before I could get around to it and go some interesting results.

For some reason his main post with the results isn’t showing even though it appears in the recent comments bar. Here’s the meat of that comment. I have to agree with Phil that it’s a bit surprising that the split-string method was the winner but that goes to show that one’s intuition about these things is most often wrong.

(length teststr)    
2070    

(length (split-string teststr " "))    
553    

(benchmark-run 10000 (double-blanks1 teststr)) ;; string-to-list    
(28.203663436 967 6.414597634999999) ;; uncompiled    
(23.110737061000002 968 8.26656119499986) ;; compiled    

(benchmark-run 10000 (double-blanks2 teststr)) ;; replace-regexp-in-string    
(21.614643389999998 1913 11.981117643999973) ;; uncompiled    
(25.317938649 1913 15.727532714000041) ;; compiled    

(benchmark-run 10000 (double-blanks3 teststr)) ;; search-forward/insert    
(8.588276816 149 0.9523469339999999) ;; uncompiled    
(8.355207331 147 1.2536677860000367) ;; compiled    

(benchmark-run 10000 (double-blanks4 teststr)) ;; split-string/mapconcat    
(7.9514880880000005 476 3.2033875379999657) ;; uncompiled    
(7.953855983 477 3.237625087999996) ;; compiled
Posted in Programming | Tagged , | 6 Comments

Mu4e Configuration

This post is the latest in my series on installing and configuring mu4e on a Mac and using Apple as a mail provider. As I wrote in my post on mbsync configuration, setting up mu4e is simple by comparison. On my MacBook Pro, I compiled the mu package from source. On my iMac I installed it with homebrew. Either way works fine. The advantage of homebrew is that it will load all the libraries that you need but aren’t included in the base macOS install.

My configuration is an adaption of Charl Botha’s, which uses some of the features in the latest release, with the addition of some ideas from Ben Maughan and a few bits of my own:

  1: (require 'mu4e)
  2: 
  3: ;; Call EWW to display HTML messages
  4: (defun jcs-view-in-eww (msg)
  5:   (eww-browse-url (concat "file://" (mu4e~write-body-to-html msg))))
  6: 
  7: ;; Arrange to view messages in either the default browser or EWW
  8: (add-to-list 'mu4e-view-actions '("ViewInBrowser" . mu4e-action-view-in-browser) t)
  9: (add-to-list 'mu4e-view-actions '("Eww view" . jcs-view-in-eww) t)
 10: 
 11: ;; From Ben Maughan: Get some Org functionality in compose buffer
 12: (add-hook 'message-mode-hook 'turn-on-orgtbl)
 13: (add-hook 'message-mode-hook 'turn-on-orgstruct++)
 14: 
 15: ;; Call mu every 5 minutes to update and index Maildir
 16: (setq mu4e-update-interval 300)
 17: 
 18: ;; Set format=flowed
 19: ;; mu4e sets up visual-line-mode and also fill (M-q) to do the right thing
 20: ;; each paragraph is a single long line; at sending, emacs will add the
 21: ;; special line continuation characters.
 22: (setq mu4e-compose-format-flowed t)
 23: 
 24: ;; every new email composition gets its own frame! (window)
 25: ;;(setq mu4e-compose-in-new-frame t)
 26: 
 27: ;; give me ISO(ish) format date-time stamps in the header list
 28: (setq mu4e-headers-date-format "%Y-%m-%d %H:%M")
 29: 
 30: ;; show full addresses in view message (instead of just names)
 31: ;; toggle per name with M-RET
 32: (setq mu4e-view-show-addresses 't)
 33: 
 34: ;;store org-mode links to messages
 35: (require 'org-mu4e)
 36: ;;store link to message if in header view, not to header query
 37: (setq org-mu4e-link-query-in-headers-mode nil)
 38: 
 39: ;;rename files when moving
 40: ;;NEEDED FOR MBSYNC
 41: (setq mu4e-change-filenames-when-moving t)
 42: 
 43: ;; Try to show images
 44: (setq mu4e-view-show-images t
 45:       mu4e-show-images t
 46:       mu4e-view-image-max-width 800)
 47: 
 48: ;; path to our Maildir directory
 49: (setq mu4e-maildir "~/Maildir")
 50: 
 51: ;; the next are relative to `mu4e-maildir'
 52: ;; instead of strings, they can be functions too, see
 53: ;; their docstring or the chapter 'Dynamic folders'
 54: (setq mu4e-sent-folder   "/icloud/Sent Messages"
 55:       mu4e-drafts-folder "/icloud/Drafts"
 56:       mu4e-trash-folder  "/icloud/Trash")
 57: 
 58: ;; the maildirs you use frequently; access them with 'j' ('jump')
 59: (setq   mu4e-maildir-shortcuts
 60:         '(("/icloud/Archive"             . ?a)
 61:           ("/icloud/inbox"               . ?i)
 62:           ("/icloud/Saved"               . ?v)
 63:           ("/icloud/Sent Messages"       . ?s)))
 64: 
 65: ;; the list of all of my e-mail addresses
 66: (setq mu4e-user-mail-address-list '("XXX@mac.com"
 67:                                     "YYY@irreal.org"))
 68: 
 69: ;; the headers to show in the headers list -- a pair of a field
 70: ;; and its width, with `nil' meaning 'unlimited'
 71: ;; (better only use that for the last field.
 72: ;; These are the defaults:
 73: (setq mu4e-headers-fields
 74:     '( (:date          .  25)    ;; alternatively, use :human-date
 75:        (:flags         .   6)
 76:        (:from          .  22)
 77:        (:subject       .  nil))) ;; alternatively, use :thread-subject
 78: 
 79: ;; Program to get mail.
 80: ;; Called when 'U' is pressed in main view.
 81: 
 82: ;; If you get your mail without an explicit command,
 83: ;; use "true" for the command (this is the default)
 84: ;; when I press U in the main view, or C-c C-u elsewhere,
 85: ;; this command is called, followed by the mu indexer
 86: (setq mu4e-get-mail-command "mbsync icloud")
 87: 
 88: ;; not using smtp-async yet
 89: ;; some of these variables will get overridden by the contexts
 90: (setq
 91:  send-mail-function 'smtpmail-send-it
 92:  message-send-mail-function 'smtpmail-send-it)
 93: 
 94: ;; don't keep message buffers around
 95: (setq message-kill-buffer-on-exit t)
 96: 
 97: ;; Contexts: One for each mail personality.
 98: (setq mu4e-contexts
 99:       `( ,(make-mu4e-context
100:            :name "a XXX@mac.com"
101:            :enter-func (lambda () (mu4e-message "Enter XXX@mac.com context"))
102:            :leave-func (lambda () (mu4e-message "Leave XXX@mac.com context"))
103:            ;; Match based on the contact-fields of the message (that we are replying to)
104:            :match-func (lambda (msg)
105:                          (when msg 
106:                            (mu4e-message-contact-field-matches msg 
107:                                                                :to "XXX@mac.com")))
108:            :vars '( ( user-mail-address      . "XXX@mac.com"  )
109:                     ( user-full-name         . "Jon Snader" )
110:                     ( smtpmail-smtp-server   . "smtp.mail.me.com" )
111:                     ( smtpmail-smtp-service  . 587)
112:                     ( smtpmail-stream-type   . starttls)))
113: 
114:          ,(make-mu4e-context
115:            :name "i YYY@irreal.org"
116:            :enter-func (lambda () (mu4e-message "Enter YYY@irreal.org context"))
117:            :leave-func (lambda () (mu4e-message "Leave YYY@irreal.org context"))
118:            ;; we match based on the contact-fields of the message
119:            :match-func (lambda (msg)
120:                          (when msg 
121:                            (mu4e-message-contact-field-matches msg 
122:                                                                :to "YYY@irreal.org")))
123:            :vars '( ( user-mail-address       . "YYY@irreal.org" )
124:                     ( user-full-name          . "Jon Snader" )
125:                     ( smtpmail-smtp-server    . "smtp-server.tampabay.rr.com" )
126:                     ( smtpmail-stream-type    . plain)
127:                     ( smtpmail-smtp-service   . 25)))))
128: 
129: 
130: ;; start with the first (default) context; 
131: (setq mu4e-context-policy 'pick-first)
132: 
133: ;; compose with the current context if no context matches;
134: (setq mu4e-compose-context-policy nil)
135: 
136: (global-set-key (kbd "C-<f6>") 'mu4e)

As you can see, it’s very similar to Botha’s. Some emails, especially commercial ones (like those from Amazon) and those from professional groups like ACM, don’t render very well so I prefer to view them in a browser environment. Usually, EWW is sufficient but sometimes I need the full Safari treatment. Lines 39 show how to do that. If I press a while viewing a message, it will bring up a menu with various viewing options. If I choose E the message is displayed in EWW. V displays it in the default browser, Safari in my case.

The other noteworthy thing about the configuration are the contexts, which are configured on lines 97134. All my emails are filtered through the Apple server so the contexts allow me to send mail either from my Apple account or my Irreal account. When I respond to an email, the correct “From:” address is chosen from the “To:” line of the original message.

Finally, there’s the matter of sending messages. Many writers recommend third party packages to handle multiple accounts but I’ve found the contexts in mu4e handles that nicely. Unless you have special needs, like Ben Maughan, using the built-in smtpmail functionality is fine. You’ll want to set up an .authinfo file to list the servers, accounts, and passwords. The line for the apple server looks like

machine smtp.mail.me.com login XXX@mac.com password same-password-as-for-mbsync

You’ll want to encrypt the file for security, but Emacs only asks for the password one time per (Emacs) session so that’s not burdensome.

Posted in General | Tagged , | Leave a comment

Configuring mbsync for Apple Mail

As a first step in realizing my goal of running mu4e as my email client, I had to get mbsync running. Mbsync is a process that communicates with one or more IMAP servers to keep your email clients in sync. My primary email is through Apple so one of my goals was to be able to use mu4e on my Macs but still have fully synced access to mail on my iPhone and iPad. That’s pretty easy because Apple mail is IMAP based and keeping multiple clients in sync is the point of IMAP.

There are two problems to solve for getting mbsync working on the Mac. The first is specifying your mail server password to mbsync. You could, of course, just put the password in your mbsync configuration file but that’s horribly insecure and, happily, unnecessary. Here’re the directions for setting up a password in your keychain from the sample configuration that comes with mbsync.

# On Mac OS X, run "KeyChain Access" -- File->New Password Item. Fill out form using
#  "Keychain Item Name" http://IMAPSERVER  (note: the "http://" is a hack)
#  "Account Name" USERNAME
#  "Password" PASSWORD

That brings us to the second problem: what to use for a password. You might think your icloud password is what’s needed here but if you have two-factor authentication enabled—which you almost certainly do if you’re running Sierra or later—you need to generate an application specific password. You can do that by following these instructions. Failure to understand this point was the source of almost all my problems in getting things working.

I keep all my saved emails in a single folder for reasons I’ve discussed before. Your setup may be a little different but if so you just need to adjust the list of mailboxes on the Patterns line in the configuration below. I added an icloud subdirectory under Maildir because I intend to add a separate mail repository for Gmail later. Right now, the configuration communicates only with the Apple mail server.

Here is my .mbsyncrc file. It normally lives in your home directory.

# Based on http://www.macs.hw.ac.uk/~rs46/posts/2014-01-13-mu4e-email-client.html
IMAPAccount icloud
Host imap.mail.me.com
User XXX #not XXX@me.com etc.
PassCmd "security find-generic-password -s mbsync-icloud-password -w"
Port 993
SSLType IMAPS
SSLVersions TLSv1.2
AuthMechs PLAIN

IMAPStore icloud-remote
Account icloud

MaildirStore icloud-local
Path ~/Maildir/icloud/
Inbox ~/Maildir/icloud/inbox
Trash Trash

#
# Channels and Groups 
# (so that we can rename local directories and flatten the hierarchy)
#
#
Channel icloud-folders
Master :icloud-remote:
Slave :icloud-local:
Patterns "INBOX" "Saved" "Drafts" "Archive" "Sent*" "Trash"
Create Both
Expunge Both
SyncState *

Group icloud
Channel icloud-folders

Once you get everything set up you can try retrieving your mail with

mbsync -a

or, if you have more than one mail server configured

mbsync icloud #or whatever your mail group name is

In the case of Apple, the server doesn’t like users sucking up bandwidth so if you have a large repository on the server, it may drop off after a while. That’s not fatal because you can just restart the download and it will take up where it left off. You can help a bit by rate limiting your network I/O as described by Ben Maughan in this post. That post also has a nice configuration for Gmail if that’s what you need. After the initial download everything will work smoothly.

Shortly, I’ll publish my next post in this series about mu4e with a discussion of my mu4e configuration.

Posted in General | Tagged , | 1 Comment