The perfect erc setup for System Crafters

I’m currently fighting with my erc config.
As System Crafters has a channel on Libera.Chat, as do a lot of tangential projects like emacs, guix, rde, and erc itself, I was thinking, if a proper blessed System Crafters erc example would be called for.


  • load on use with use-package
  • authinfo for credentials to make sharing easier
  • known to work with Libera.Chat
  • optionally auto join channels after cloak takes effect

Currently I work with this mess of a config:


machine Libera.Chat login USER password SECRET
(use-package erc
  ;;:commands (erc erc-tls)
  ;;:straight (:type built-in)
  (defun my/erc-browse-last-url ()
    "Search backwards through an ERC buffer, looking for a URL. When a URL is
     found, it prompts you to open it."
      (let ((ffap-url-regexp "\\(https?://\\)."))
	(ffap-next-url t t))))

  (defun my/erc-notify (nickname message)
    "Displays a notification message for ERC."
    (let* ((channel (buffer-name))
	   (nick (erc-hl-nicks-trim-irc-nick nickname))
	   (title (if (string-match-p (concat "^" nickname) channel)
		    (concat nick " (" channel ")")))
	   (msg (s-trim (s-collapse-whitespace message))))
      (alert (concat nick ": " msg) :title title)))

  (defun my/erc-preprocess (string)
    "Avoids channel flooding."
    (setq str (string-trim (replace-regexp-in-string "\n+" " " str))))

  (defun my/erc-reset-track-mode ()
    "Resets ERC track mode."
    (setq erc-modified-channels-alist nil)

  (defun dgr/erc-start-or-switch ()
    "Connects to ERC, or switch to last active buffer."
    (if (get-buffer "Libera.Chat")
	(erc-track-switch-buffer 1)
	  ((auth-info (auth-source-search :host "Libera.Chat" :require '(:user :secret)))
	   (user-id (plist-get (car auth-info) :user))
	   (password (funcall (plist-get (car auth-info) :secret))))
	   ; (erc-sasl-auth-source-function #'erc-sasl-auth-source-password-as-host))
	   :server ""
	   :port 6697
	   :nick global-nick
	   :user user-id
	   :password password))))

  (defun dgr/auth-source-libera (&rest _)
    (let* ((host (read-string "host: " nil nil "default"))
	   (pass (auth-source-pick-first-password :host host)))
      (if (and pass (string-search "Libera.Chat" host))
	  (concat global-nick ":" pass)

  ((ercn-notify . my/erc-notify)
   (erc-send-pre . my/erc-preprocess))
  ;; (erc-action-face ((t (:foreground "#8fbcbb"))))
  ;; (erc-error-face ((t (:foreground "#bf616a"))))
  ;; (erc-input-face ((t (:foreground "#ebcb8b"))))
  ;; (erc-notice-face ((t (:foreground "#ebcb8b"))))
  ;; (erc-timestamp-face ((t (:foreground "#a3be8c"))))
  (erc-fill-function 'erc-fill-static)
  (erc-fill-static-center 22)
  (erc-header-line-format "%n on %t (%m)")
  (erc-hide-list '("JOIN" "PART" "QUIT"))
  (erc-lurker-threshold-time 43200)
  (erc-lurker-hide-list '("JOIN" "PART" "QUIT"))
  (erc-track-exclude-types '("JOIN" "MODE" "NICK" "PART" "QUIT"
			     "324" ; modes
			     "329" ; channel creation date
			     "332" ; topic notice
			     "333" ; who set the topic
			     "353" ; names notice
  (erc-join-buffer 'window)
  ;;(erc-prompt-for-password nil)
  ;;(erc-prompt-for-nickserv-password nil)
  ;;(erc-server-reconnect-attempts 5)
  ;;(erc-server-reconnect-timeout 3)
  ;;(erc-use-auth-source-for-nickserv-password t)
   '(("Libera.Chat" "#emacs" "#erc" "#tropin" "#guix" "#systemcrafters")))
  (erc-log-channels-directory "~/.erc/logs")
  (erc-modules '(autojoin
  (erc-services-mode t)
  (erc-prompt (lambda () (concat "[" (buffer-name) "]")))
  ; (erc-sasl-auth-source-function 'dgr/auth-source-libera)
  :bind ("C-c i l" . dgr/erc-start-or-switch))

What is your erc config looking like - post it?
Any ideas for improvements?

EDIT: updated version with less missing modules

1 Like

TODO: add auto rotate to erc-image.el
yesterday I saw a picture in #systemcrafters / coffeecrafters and it was sideways.


Looks like the metadata request a 90° rotation against the clock and most other applications respect this.

Details about the file in Dolphin: Screenshot_20240401_153142

I tried to fix it but I’m getting errors

error in process filter: cond: Symbol’s value as variable is void: orientation
error in process filter: Symbol’s value as variable is void: orientation


(defun erc-image--maybe-rescale (image file-name dimensions height width)
"Rescale FILE-NAME to have max DIMENSIONS of HEIGHT or WIDTH, or return IMAGE.
Helper function for erc-image-create-image."
(let ((imagemagick-p (and (fboundp 'imagemagick-types) 'imagemagick))
      (orientation (shell-command-to-string (concat "exiftool --Orientation -b " file-name " 2>/dev/null")))
      (rotation (cond ((equal orientation "1") '0)
		      ((equal orientation "8") '90)
      		      ((equal orientation "3") '180)
		      ((equal orientation "6") '270)
		      (t '0))))
  (message "Debug: Orientation is %s" orientation)
  (message "Debug: Rotation is %s" rotation)
  (if (or (> (car dimensions) width)
          (> (cdr dimensions) height))
      ;; Figure out in which direction we need to scale
      (if (> (cdr dimensions) (car dimensions))
          (create-image file-name imagemagick-p nil :height height :rotation rotation)
        (create-image file-name imagemagick-p nil :width width :rotation rotation))
    ;; Image is smaller than erc-image-inline-rescale, just give that back

Any pointers are very welcome.

ha! Sorry my photo showed up sideways! I thought I only stripped out the gps metadata but maybe it removed more.

I’m not an erc user and looks like crafted-emacs does not have a erc section but @benoitj is an erc user and his config looks nice.

@shom your photo is ok, the EXIF data shows a orientation of 6 (-90°) so erc-image has a bug and ignores the standard as I found it described at Rotate Photos to be Upright - Sirv Help Center

1 Like

I’ve been investigating improving my own ERC configuration for Emacs, I’ve made several enhancements aimed at improving functionality, readability, and maintainability.

When I saw your post, I looked at your configuration and my own and have come up with a merged configuration.

Below, you’ll find an updated configuration snippet with explanations for the changes.

Functional Enhancements

  1. Enhanced URL Browsing: Improved URL detection and handling in my/erc-browse-last-url for a more reliable browsing experience.
  2. Notification Improvements: Updated my/erc-notify to differentiate between direct messages and channel messages more clearly.
  3. Preprocessing String Fix: Corrected an issue in my/erc-preprocess where a variable was used before assignment, which could lead to runtime errors.
  4. SASL Authentication: Suggested to ensure erc-sasl-auth-source-function is correctly set for better authentication handling.
  5. Auto-Reconnection: To be implemented

Code Refinements

  • Ensured variable naming consistency and added error handling where appropriate.
  • Improved function documentation for better clarity.

Updated Configuration Snippet

(use-package erc
  (defun my/erc-browse-last-url ()
    "Search backwards through an ERC buffer for a URL and prompt to open it."
      (let ((url-regexp "\\(http\\|https\\|ftp\\|gopher\\)://[^\t\n\r\f <>\"{}|\\^`]*"))
        (if (re-search-backward url-regexp nil t)
            (browse-url (match-string 0))
          (message "No URL found in buffer.")))))

  (defun my/erc-notify (nickname message)
    "Displays a notification for an ERC message."
    (let* ((channel (buffer-name))
           (nick (erc-hl-nicks-trim-irc-nick nickname))
           (title (if (string-match-p (concat "^" nickname) channel)
                      (concat "PM from " nick)
                    (concat nick " (" channel ")")))
           (msg (s-trim (s-collapse-whitespace message))))
      (alert (concat nick ": " msg) :title title)))

  (defun my/erc-preprocess (string)
    "Avoids channel flooding by trimming and replacing newlines in messages."
    (setq string (string-trim (replace-regexp-in-string "\n+" " " string))))

  ((ercn-notify . my/erc-notify)
   (erc-send-pre . my/erc-preprocess))
  ;; Include the rest of your configuration as is, without changes.

Additional Considerations

  • Custom Faces: You may want to uncomment and adjust the :custom-face settings according to your personal preferences.
  • Testing: Ensure to test these changes in your setup to validate their effectiveness in various scenarios.

I haven;t got around to deploying this solution myself just yet, so if you decide to incorporate any of it I would be interested in hearing your thoughts for improving it further.

1 Like