After waking my laptop from sleep, rcirc is usually disconnected from the server, but doesn’t know it.
/reconnect command will force a reconnect. Since it deletes the existing process, too, rcirc will reuse your buffers, which is the important part. The code also attempts to connect to the same channels you were connected to before, irrespective of
(eval-after-load 'rcirc '(defun-rcirc-command reconnect (arg) "Reconnect the server process." (interactive "i") (unless process (error "There's no process for this target")) (let* ((server (car (process-contact process))) (port (process-contact process :service)) (nick (rcirc-nick process)) channels query-buffers) (dolist (buf (buffer-list)) (with-current-buffer buf (when (eq process (rcirc-buffer-process)) (remove-hook 'change-major-mode-hook 'rcirc-change-major-mode-hook) (if (rcirc-channel-p rcirc-target) (setq channels (cons rcirc-target channels)) (setq query-buffers (cons buf query-buffers)))))) (delete-process process) (rcirc-connect server port nick rcirc-default-user-name rcirc-default-full-name channels))))
On Emacs21 (21.4.1),
process-contact accepts only one parameter; I had to change line 6 to read:
(port (nth 1 (process-contact process)))
OK, after a lot of tweaking and using other people’s code, I finally managed to make rcirc to auto-reconnect when connection breaks. The above reconnect function doesn’t work when rcirc process is disconnected, so it needs to be changed. I make it join default channels for the server it reconnects to (from rcirc-server-alist). I’m not sure how to make it track down channels that the user was in at the time of disconnect.
(defun-rcirc-command reconnect (arg) "Reconnect the server process." (interactive "i") (if (buffer-live-p rcirc-server-buffer) (with-current-buffer rcirc-server-buffer (let ((reconnect-buffer (current-buffer)) (server (or rcirc-server rcirc-default-server)) (port (if (boundp 'rcirc-port) rcirc-port rcirc-default-port)) (nick (or rcirc-nick rcirc-default-nick)) channels) (dolist (buf (buffer-list)) (with-current-buffer buf (when (equal reconnect-buffer rcirc-server-buffer) (remove-hook 'change-major-mode-hook 'rcirc-change-major-mode-hook) (let ((server-plist (cdr (assoc-string server rcirc-server-alist)))) (when server-plist (setq channels (plist-get server-plist :channels)))) ))) (if process (delete-process process)) (rcirc-connect server port nick nil nil channels))))) ;;; Attempt reconnection at increasing intervals when a connection is ;;; lost. (defvar rcirc-reconnect-attempts 0) ;;;###autoload (define-minor-mode rcirc-reconnect-mode nil nil " Auto-Reconnect" nil (if rcirc-reconnect-mode (progn (make-local-variable 'rcirc-reconnect-attempts) (add-hook 'rcirc-sentinel-hooks 'rcirc-reconnect-schedule nil t)) (remove-hook 'rcirc-sentinel-hooks 'rcirc-reconnect-schedule t))) (defun rcirc-reconnect-schedule (process &optional sentinel seconds) (condition-case err (when (and (eq 'closed (process-status process)) (buffer-live-p (process-buffer process))) (with-rcirc-process-buffer process (unless seconds (setq seconds (exp (1+ rcirc-reconnect-attempts)))) (rcirc-print process "my-rcirc.el" "ERROR" rcirc-target (format "scheduling reconnection attempt in %s second(s)." seconds) t) (run-with-timer seconds nil 'rcirc-reconnect-perform-reconnect process))) (error (rcirc-print process "RCIRC" "ERROR" nil (format "%S" err) t))) ) (defun rcirc-reconnect-perform-reconnect (process) (when (and (eq 'closed (process-status process)) (buffer-live-p (process-buffer process)) ) (with-rcirc-process-buffer process (when rcirc-reconnect-mode (if (get-buffer-process (process-buffer process)) ;; user reconnected manually (setq rcirc-reconnect-attempts 0) (let ((msg (format "attempting reconnect to %s..." (process-name process) ))) (rcirc-print process "my-rcirc.el" "ERROR" rcirc-target msg t)) ;; remove the prompt from buffers (condition-case err (progn (save-window-excursion (save-excursion (rcirc-cmd-reconnect nil))) (setq rcirc-reconnect-attempts 0)) ((quit error) (incf rcirc-reconnect-attempts) (rcirc-print process "my-rcirc.el" "ERROR" rcirc-target (format "reconnection attempt failed: %s" err) t) (rcirc-reconnect-schedule process))))))))
Now, the above code is probably supposed to go to a separate elisp file so as not to clutter up your .emacs. Also setting up rcirc-reconnect-mode manually is annoying, so here’s how to enable it for a specific server:
(add-hook 'rcirc-mode-hook (lambda () (if (string-match (regexp-opt '("irc.freenode.net" "irc.inet.tele.dk" "irc.perl.org") (buffer-name)) (rcirc-reconnect-mode 1))))
Add this to .emacs and you will never stay disconnected from this IRC server again.