This blog has my random thoughts; game-related posts go here.

Building Mac OS X Emacs 26

On 11 Oct 2017 Emacs 26.0.90 pretest was released. For Mac, there's a build on I have been using the "Mac port" from Mitsuharu Yamamoto because it feels smoother and faster on my system, and I decided to try his development branch. Here's what I ran:

brew install gnutls texinfo libxml2
cd ~/Projects/src
git clone --branch work --depth 1
cd emacs-mac
export PATH=/usr/local/opt/texinfo/bin/:$PATH
export PKG_CONFIG_PATH=/usr/local/opt/libxml2/lib/pkgconfig
./configure --with-mac \
     --prefix=/PersonalApplications/ \
make install

It runs nicely!

A minor note: the byte-compiled .elc files compiled under Emacs 26 are not compatible with Emacs 25, so if you go back to an older version, you'll need to recompile the .elc files.

Labels: , ,

Panorama to square images for Instagram

Instagram recently added a feature to post up to 10 photos side by side. I saw someone cleverly used it to post a single panoramic photo. You split the panorama into square photos and then post them all at once to Instagram, which then arranges them side by side. Here's a quick & dirty script I wrote to split up my own panoramas into square photos. It uses a few Mac commands to get the size of the image, and ImageMagick to break up the images into smaller ones:


if [ -z "$1" ]; then
    echo "Usage: $0 filename.jpg"


# Original image size
width=$(mdls -raw -name kMDItemPixelWidth "$filename")
height=$(mdls -raw -name kMDItemPixelHeight "$filename")

# Each of the square pieces will be 1/Nth the width
N=$[$width / $height]
if [ $N -gt 10 ]; then N=10; fi  # maximum 10 allowed by instagram

size=$[$width / N]
if [ $height -lt $size ]; then size=$height; fi

# Use the center of the x,y range
x_offset=$[$[$width - $size * N] / 2]
y_offset=$[$[$height - $size] / 2]

echo  "$filename : ${width}x${height}, $N parts"

if [ $x_offset -gt 0 ]; then
    echo "Wide image; truncating $[2 * $x_offset] pixels"

if [ $y_offset -gt 0 ]; then
    echo "Tall image; truncating $[2 * $y_offset] pixels"

for part in $(seq $[$N - 1] -1 0); do
    crop="${size}x${size}+$[${x_offset} + ${size}*${part}]+${y_offset}"
    echo "  part $part : $crop"
    convert "$filename" -crop "$crop" $part.jpg

I'm sure there are lots of things I could do better but I just wanted to get something working quickly.


Emacs spaceline mode line

Back in 2011 I posted my Emacs mode line configuration. At the time I was thinking it'd be nice to have a more modular way to define the mode line. A few weeks ago I rewrote my mode line configuration to use Spaceline, the mode line library used in Spacemacs. I made it match my tabbar:


Rewriting part of my Emacs configuration is an opportunity to simplify. Instead of starting with my old setup and throwing away parts of it, I decided to start over and copy over any bits I wanted to keep. This is a minimal setup:

(use-package spaceline :ensure t
  (setq-default mode-line-format '("%e" (:eval (spaceline-ml-main)))))

(use-package spaceline-config :ensure spaceline
  (spaceline-helm-mode 1)

I like to customize things more, especially my mode line. Spaceline's configuration is defined in terms of segments on the left or right side. I looked at spaceline-config.el for the spaceline-emacs-theme function, which called spaceline--theme, and decided this was a good starting point:

(use-package spaceline-config :ensure spaceline
  (spaceline-helm-mode 1)
     ((remote-host buffer-id) :face highlight-face)
     (process :when active))
   '((selection-info :face region :when mark-active)
     ((flycheck-error flycheck-warning flycheck-info) :when active)
     (version-control :when active)
     (global :when active)

 powerline-height 24
 powerline-default-separator 'wave
 spaceline-flycheck-bullet "❖ %s"
 spaceline-separator-dir-left '(right . right)
 spaceline-separator-dir-right '(left . left))

I need to call spaceline-install with a name, a list of things on the left, and a list of things on the right. Each item in the list is either a spaceline segment name or a list of names, and maybe some properties. I went through the things I was using to decide which segments I needed:

  1. Buffer status. Spaceline colors the buffer name. I instead want a brightly colored block on the left for modified:

    and a different block for read only:
  2. Directory and buffer name. Spaceline by default shows the buffer name, just like Emacs does, but I wanted it to match the color of the tabbar. I wanted to show the directory name too but not in the same color. I put these two next to each other without a separator shape.
  3. Other indicators. Line number, column number, major mode, version control, recursive edit, process status, nyan mode, and more are all directly supported in Spaceline. Here's the count of lines in the selected region:

    I added segments for the week number and the current character if it's non-ascii:

One by one I modified the starting point code above into this:

(use-package spaceline-config :ensure spaceline
  (spaceline-helm-mode 1)

  (spaceline-define-segment my/buffer-status
    "Buffer status (read-only, modified), with color"
    (cond (buffer-read-only (propertize "RO" 'face 'my/spaceline-read-only))
          ((buffer-modified-p) (propertize "**" 'face 'my/spaceline-modified))
          (t "  ")))

  (spaceline-define-segment amitp/project-id
    "Name of project, or folder"
      (cond (buffer-file-name (amitp/project-root-for-file buffer-file-name))
            (t (amitp/project-root-for-directory default-directory)))
      (- (window-width) (length (amitp/spaceline-buffer-id)) 60))
     'face 'amitp/spaceline-filename))

  (spaceline-define-segment amitp/buffer-id
    "Name of filename relative to project, or buffer id"
     'face 'amitp/spaceline-filename))

  (spaceline-define-segment my/unicode-character
    "Description of unicode character we're currently on"
    (let ((ch (following-char)))
      (when (and ch (>= ch 127))
        (get-char-code-property (following-char) 'name))))

  (spaceline-define-segment my/week-number
    "Year and week number, which I use for marking my projects"
    (format-time-string "W%y%V"))

  ;; When there are segments that may or may not appear, they will
  ;; affect the alternating background colors. I try to put the
  ;; indicators that appear/disappear the most towards the center.
   '((my/buffer-status :tight-left t)
     (amitp/project-id :tight-right t)
     (amitp/buffer-id :tight-left t :face highlight-face)
     (process :when active))
   '((selection-info :face region :when mark-active)
     (my/unicode-character :face my/spaceline-unicode-character :when active)
     ((flycheck-error flycheck-warning flycheck-info) :when active)
     (version-control :when active)
     (("L" line column) :separator ":" :when active)
     (my/week-number :when active)
     (global :face highlight-face)

(defun amitp/spaceline-buffer-id ()
  (cond (buffer-file-name
         (s-chop-prefix (amitp/project-root-for-file buffer-file-name) buffer-file-name))
        (t (s-trim (powerline-buffer-id 'mode-line-buffer-id)))))

I haven't included all the amitp/ functions because they're specific to my configuration. Use projectile-project-name instead of amitp/project-root-for-file.

Projects. I've been using Emacs for over 25 years so I have a lot of home grown stuff that predates popular packages, including project management. Maybe one day I'll switch to Projectile, which Spaceline supports directly, but until then I wanted the mode line to show the project name in one color and the file name relative to the project root in the main color. This only works because my project names are the full path to the root folder.

I also use a different color for personal projects (blue) and work projects (red). I implemented this by using Spaceline's highlight face. Spaceline comes with a way to change the highlight when the buffer is modified or to match the evil-mode but I instead use that feature for personal vs work colors.

To implement this I used spaceline-face-func and also defined a whole bunch of faces.

(defun amitp/spaceline-face (face active)
  "For spaceline-face-func"
  ;; Spaceline will use face1/face2 for the segments, and line for the
  ;; blank space between the left and the right sides. It will use highlight
  ;; when the segment calls for :face highlight-face. I find the default behavior
  ;; weird, as it maps face1/face2 to powerline-{in,}active1 and mode-line, and
  ;; uses powerline-{in,}active2 for the blank space. I'm going to use my own faces
  ;; instead.
  (pcase (cons face active)
    ('(face1 . t)   'powerline-active1)
    ('(face1 . nil) 'powerline-inactive1)
    ('(face2 . t)   'powerline-active2)
    ('(face2 . nil) 'powerline-inactive2)
    ('(line . t)    'mode-line)

    ('(line . nil)  'mode-line-inactive)
    ('(highlight . t)
     (case amitp/buffer-type
       (work     'amitp/spaceline-work-active)
       (personal 'amitp/spaceline-personal-active)
       (t        'amitp/spaceline-other-active)))
    ('(highlight . nil)
     (case amitp/buffer-type
       (work     'amitp/spaceline-work-inactive)
       (personal 'amitp/spaceline-personal-inactive)
       (t        'amitp/spaceline-other-inactive)))
    (_ 'error)))

(setq spaceline-face-func 'amitp/spaceline-face)

(defvar-local amitp/buffer-type 'other "Set to 'personal or 'work or 'other per buffer")

(defun amitp/set-local-colors ()
  "Set amitp/buffer-type and also tabbar color"
  (let ((personal (face-background 'amitp/spaceline-personal-active))
        (work (face-background 'amitp/spaceline-work-active)))
     ((s-starts-with? "*" (buffer-name)) (setq amitp/buffer-type 'other))
     ((string-match "redblobgames" (or (buffer-file-name) default-directory))
      (setq amitp/buffer-type 'work)
      (face-remap-add-relative 'tabbar-selected :background work :box nil))
     ((string-match "amitp" (or (buffer-file-name) default-directory))
      (setq amitp/buffer-type 'personal)
      (face-remap-add-relative 'tabbar-selected :background personal :box nil)))))

(cl-loop for buffer in (buffer-list) do
         (with-current-buffer buffer (amitp/set-local-colors)))
(add-hook 'find-file-hook #'amitp/set-local-colors)
(add-hook 'dired-mode-hook #'amitp/set-local-colors)
(add-hook 'change-major-mode-hook #'amitp/set-local-colors)
(add-hook 'temp-buffer-setup-hook #'amitp/set-local-colors)

This too is specific to my setup so I don't think it'll be useful to copy it directly, but it might be useful for anyone who wants to set up different colors for different projects.

Fonts were the other big change. I had been using a proportional font, as it lets me squeeze more information onto the mode line. With Spaceline putting information on both the left and right, I needed to switch back to a monospace font, at least for the right. I decided to use monospace everywhere except the project+file name. Powerline needs to know how big my font is relative to the default font, using powerline-text-scale-factor.

(defun hsl (H S L) ; convenience fn
  (apply 'color-rgb-to-hex (color-hsl-to-rgb (/ H 360.0) S L)))
(defun face (face &rest spec) ; convenience fn
  (face-spec-set face (list (cons t spec))))
(setq powerline-text-scale-factor 0.8)

(face 'mode-line :family "M+ 1m" :height 1.0 :background "gray20" :foreground "gray80" :box nil)
(face 'mode-line-inactive :inherit 'mode-line :background "gray55" :foreground "gray80" :box nil)
(face 'mode-line-highlight :inherit 'mode-line :background "GoldenRod2" :foreground "white" 
      :box '(:line-width -2 :color "GoldenRod2" :style released-button))

(face 'powerline-active1   :inherit 'mode-line          :height powerline-text-scale-factor :background "gray30")
(face 'powerline-inactive1 :inherit 'mode-line-inactive :height powerline-text-scale-factor)
(face 'powerline-active2   :inherit 'mode-line          :height powerline-text-scale-factor :background "gray40")
(face 'powerline-inactive2 :inherit 'mode-line-inactive :height powerline-text-scale-factor)

(face 'spaceline-highlight :inherit 'mode-line :foreground "white" :background "gray80" :height powerline-text-scale-factor)

(face 'amitp/spaceline-personal-active   :inherit 'spaceline-highlight :background (hsl 200 0.5 0.5))
(face 'amitp/spaceline-personal-inactive :inherit 'spaceline-highlight :background (hsl 200 0.2 0.5))
(face 'amitp/spaceline-work-active       :inherit 'spaceline-highlight :background (hsl 0 0.5 0.5))
(face 'amitp/spaceline-work-inactive     :inherit 'spaceline-highlight :background (hsl 0 0.2 0.5))
(face 'amitp/spaceline-other-active      :inherit 'spaceline-highlight :background (hsl 300 0.4 0.5))
(face 'amitp/spaceline-other-inactive    :inherit 'spaceline-highlight :background (hsl 300 0.15 0.5))

(face 'my/spaceline-read-only :background (hsl 300 0.15 0.5) :foreground "gray80" :box `(:line-width -2 :color ,(hsl 300 0.4 0.5)))
(face 'my/spaceline-modified :background "GoldenRod2" :foreground "black")
(face 'my/spaceline-unicode-character :inherit 'mode-line :foreground "black" :background (hsl 50 1.0 0.5))
(face 'amitp/spaceline-filename :family "Helvetica Neue" :foreground nil :background nil :weight 'normal :height (/ 1.0 powerline-text-scale-factor))

Did I mention that I have a lot of faces?

I'm a lot happier with the modular setup. Each segment function is fairly small and easy to understand. I can add, remove, and rearrange them easily.

Update: [2017-04-19] I discovered that the line (add-hook 'first-change-hook #'amitp/set-local-colors) had been interfering with other parts of emacs, including query-replace and org-habits, so I took that out. It gave me "match data clobbered by buffer modification hooks". Ugh! That was many months of frustration during which time I never even suspected my modeline setup could be the cause.

Labels: ,

Tunnels everywhere

Right now tunnel boring machines are expensive and we only use them for a few projects. If they were cheaper we'd have a lot more of them and use them for many more roads.

I've long wanted tunnels for lightweight freight transportation (see my blog post from 2005) but I'd also like tunnels for infrastructure in general — electricity, gas, water, gray water, cable tv, telephone land line, fiber optic internet, mail delivery, trash collection, etc. It's a shame that we have to dig up roads to install or fix any of these. It's a shame that I can't get gray water for my yard and am using drinking water to water my flowers. It's a shame that fiber optic internet access is so expensive to install. It's a shame that we have to see ugly power/telephone/cable lines everywhere. Also, a lot of this stuff would be better out of the weather.

Cheap tunnels would change a lot of things! I'm hoping Elon Musk will make this happen!


Emacs Org-mode 9

Org-mode 9 was just released, and it changed the syntax for export blocks. I need to change:



#+begin_export html

The org-mode changes file includes some elisp to change this. However, I couldn't get it to work, and I also wanted to change all my files, not run this elisp on one file at a time. Here are the commands I ran:

ack -l --type-add=org:ext:org --org '#.begin_html' | xargs -n 1 perl -pi -e 's/#\+end_html/#+end_export/'
ack -l --type-add=org:ext:org --org '#.begin_html' | xargs -n 1 perl -pi -e 's/#\+begin_html/#+begin_export html/'

I only needed this for html, but you may need to extend this for other types you use. See what else you use with:

ack --type-add=org:ext:org --org '#.begin_(html|ascii|latex|odt|markdown|md|org|man|beamer|texinfo|groff|koma-letter)'

Labels: ,