Endless Parentheses

Concise ramblings on Emacs productivity.

Support on Gratipay
profile for Malabarba on Stack Exchange

Mold Slack entirely to your liking with Emacs

Although fine-tuning your slack notifications is already reason enough to run slack in Emacs, that’s only the beginning. Once everything is up and running you get to decide what you want out of your slack. Some of the snippets below simply make up for missing functionality, other customize the package beyond what you can do on the Slack Webapp.

Priorities first. The most important improvement you can implement is install emojify-mode and turn it on for slack chats.

(add-hook 'slack-mode-hook #'emojify-mode)

Secondly, make sure you costumize the chat faces to your liking. Just open a chat buffer, place your cursor on a piece of text whose face you want to customize, and call customize-face.

In order to keep track of new messages in the mode-line, slack.el uses a package called tracking, which is the same one circe uses for IRC chats. The command tracking-next-buffer is a fantastic way to cycle through your pending messages, bind it to something short.

(with-eval-after-load 'tracking
  (define-key tracking-mode-map [f11]
;; Ensure the buffer exists when a message arrives on a
;; channel that wasn't open.
(setq slack-buffer-create-on-notify t)

I’ll never know who thought user statuses were a good idea for Slack. But, thanks to a tip by _asummers on HackerNews, I can live in a world where they don’t exist.

(defun slack-user-status (_id _team) "")

I like notifications with minimal titles, and the package is kind enough to make these configurable.

;;; Channels
(setq slack-message-notification-title-format-function
      (lambda (_team room threadp)
        (concat (if threadp "Thread in #%s") room)))

(defun endless/-cleanup-room-name (room-name)
  "Make group-chat names a bit more human-readable."
   "--" " "
   (replace-regexp-in-string "#mpdm-" "" room-name)))

;;; Private messages and group chats
 (lambda (_team room threadp)
   (concat (if threadp "Thread in %s") 
           (endless/-cleanup-room-name room))))

Slack.el uses lui for the chat buffers. If you, like me, are a heavy user of abbrevs in Emacs, you’ll find it annoying that the final word of each message won’t get expanded unless you explicitly hit SPC before RET. That’s easy to remedy with an advice.

(advice-add #'lui-send-input :before
            (lambda (&rest _)
              (ignore-errors (expand-abbrev))))

Finally, the biggest missing feature from this package is that it displays the author on every message output, even when the same user sends several messages in a row. The snippet below adds a hook to omit the author name for a message whenever it’s the same author as the previous message.

(defun endless/-author-at (pos)
   (rx "\n" (* anything)) ""
   (or (get-text-property pos 'lui-raw-text) "")))

(defun endless/-remove-slack-author ()
  "Remove author here if it's the same as above."
  (let ((author-here (endless/-author-at (point)))
        (author-above (endless/-author-at (1- (point)))))
    (when (and (looking-at-p (regexp-quote author-here))
               (equal author-here author-above))
      (delete-region (1- (point))
                     (1+ (line-end-position))))))

(defun endless/remove-slack-author-hook ()
  "For usage in `lui-pre-output-hook'."
  (when (derived-mode-p 'slack-mode)
      (goto-char (point-min))

(add-hook 'lui-pre-output-hook

You don’t have to stop here, of course. Want to fine-tune which buffers get tracked on the mode-line? Hack into tracking.el. Want to change the face used for your own messages, or even align them to the right? Redefine slack-buffer-insert. Your workflow is yours to build.

Tags: slack, init.el, emacs

Support on Gratipay
comments powered by Disqus