comparison lisp/net/rcirc.el @ 91085:880960b70474

Merge from emacs--devo--0 Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-283
author Miles Bader <miles@gnu.org>
date Sun, 11 Nov 2007 00:56:44 +0000
parents 4bc33ffdda1a 41cfd60a7993
children 2fcaae6177a5
comparison
equal deleted inserted replaced
91084:a4347a111894 91085:880960b70474
91 91
92 VALUE must be a list of strings describing which channels to join 92 VALUE must be a list of strings describing which channels to join
93 when connecting to this server. If absent, no channels will be 93 when connecting to this server. If absent, no channels will be
94 connected to automatically." 94 connected to automatically."
95 :type '(alist :key-type string 95 :type '(alist :key-type string
96 :value-type (plist :options ((nick string) 96 :value-type (plist :options ((:nick string)
97 (port integer) 97 (:port integer)
98 (user-name string) 98 (:user-name string)
99 (full-name string) 99 (:full-name string)
100 (channels (repeat string))))) 100 (:channels (repeat string)))))
101 :group 'rcirc) 101 :group 'rcirc)
102 102
103 (defcustom rcirc-default-port 6667 103 (defcustom rcirc-default-port 6667
104 "The default port to connect to." 104 "The default port to connect to."
105 :type 'integer 105 :type 'integer
320 320
321 (defvar rcirc-prompt-start-marker nil) 321 (defvar rcirc-prompt-start-marker nil)
322 (defvar rcirc-prompt-end-marker nil) 322 (defvar rcirc-prompt-end-marker nil)
323 323
324 (defvar rcirc-nick-table nil) 324 (defvar rcirc-nick-table nil)
325
326 (defvar rcirc-recent-quit-alist nil
327 "Alist of nicks that have recently quit or parted the channel.")
325 328
326 (defvar rcirc-nick-syntax-table 329 (defvar rcirc-nick-syntax-table
327 (let ((table (make-syntax-table text-mode-syntax-table))) 330 (let ((table (make-syntax-table text-mode-syntax-table)))
328 (mapc (lambda (c) (modify-syntax-entry c "w" table)) 331 (mapc (lambda (c) (modify-syntax-entry c "w" table))
329 "[]\\`_^{|}-") 332 "[]\\`_^{|}-")
415 (cons (process-contact (get-buffer-process 418 (cons (process-contact (get-buffer-process
416 (current-buffer)) :host) 419 (current-buffer)) :host)
417 connected-servers)))))))) 420 connected-servers))))))))
418 (when connected-servers 421 (when connected-servers
419 (message "Already connected to %s" 422 (message "Already connected to %s"
420 (concat (mapconcat 'identity (butlast connected-servers) ", ") 423 (if (cdr connected-servers)
421 ", and " (car (last connected-servers)))))))) 424 (concat (mapconcat 'identity (butlast connected-servers) ", ")
425 ", and "
426 (car (last connected-servers)))
427 (car connected-servers)))))))
422 428
423 ;;;###autoload 429 ;;;###autoload
424 (defalias 'irc 'rcirc) 430 (defalias 'irc 'rcirc)
425 431
426 432
761 (mapcar (lambda (x) (cons x nil)) 767 (mapcar (lambda (x) (cons x nil))
762 (rcirc-channel-nicks (rcirc-buffer-process) 768 (rcirc-channel-nicks (rcirc-buffer-process)
763 rcirc-target)))))) 769 rcirc-target))))))
764 (let ((completion (car rcirc-nick-completions))) 770 (let ((completion (car rcirc-nick-completions)))
765 (when completion 771 (when completion
766 (rcirc-put-nick-channel (rcirc-buffer-process) completion rcirc-target)
767 (delete-region (+ rcirc-prompt-end-marker 772 (delete-region (+ rcirc-prompt-end-marker
768 rcirc-nick-completion-start-offset) 773 rcirc-nick-completion-start-offset)
769 (point)) 774 (point))
770 (insert (concat completion 775 (insert (concat completion
771 (if (= (+ rcirc-prompt-end-marker 776 (if (= (+ rcirc-prompt-end-marker
797 (define-key rcirc-mode-map (kbd "C-c C-l") 'rcirc-toggle-low-priority) 802 (define-key rcirc-mode-map (kbd "C-c C-l") 'rcirc-toggle-low-priority)
798 (define-key rcirc-mode-map (kbd "C-c C-d") 'rcirc-cmd-mode) 803 (define-key rcirc-mode-map (kbd "C-c C-d") 'rcirc-cmd-mode)
799 (define-key rcirc-mode-map (kbd "C-c C-m") 'rcirc-cmd-msg) 804 (define-key rcirc-mode-map (kbd "C-c C-m") 'rcirc-cmd-msg)
800 (define-key rcirc-mode-map (kbd "C-c C-r") 'rcirc-cmd-nick) ; rename 805 (define-key rcirc-mode-map (kbd "C-c C-r") 'rcirc-cmd-nick) ; rename
801 (define-key rcirc-mode-map (kbd "C-c C-o") 'rcirc-omit-mode) 806 (define-key rcirc-mode-map (kbd "C-c C-o") 'rcirc-omit-mode)
807 (define-key rcirc-mode-map (kbd "M-o") 'rcirc-omit-mode)
802 (define-key rcirc-mode-map (kbd "C-c C-p") 'rcirc-cmd-part) 808 (define-key rcirc-mode-map (kbd "C-c C-p") 'rcirc-cmd-part)
803 (define-key rcirc-mode-map (kbd "C-c C-q") 'rcirc-cmd-query) 809 (define-key rcirc-mode-map (kbd "C-c C-q") 'rcirc-cmd-query)
804 (define-key rcirc-mode-map (kbd "C-c C-t") 'rcirc-cmd-topic) 810 (define-key rcirc-mode-map (kbd "C-c C-t") 'rcirc-cmd-topic)
805 (define-key rcirc-mode-map (kbd "C-c C-n") 'rcirc-cmd-names) 811 (define-key rcirc-mode-map (kbd "C-c C-n") 'rcirc-cmd-names)
806 (define-key rcirc-mode-map (kbd "C-c C-w") 'rcirc-cmd-whois) 812 (define-key rcirc-mode-map (kbd "C-c C-w") 'rcirc-cmd-whois)
825 (defvar rcirc-last-post-time nil) 831 (defvar rcirc-last-post-time nil)
826 832
827 (defvar rcirc-log-alist nil 833 (defvar rcirc-log-alist nil
828 "Alist of lines to log to disk when `rcirc-log-flag' is non-nil. 834 "Alist of lines to log to disk when `rcirc-log-flag' is non-nil.
829 Each element looks like (FILENAME . TEXT).") 835 Each element looks like (FILENAME . TEXT).")
836
837 (defvar rcirc-current-line 0
838 "The current number of responses printed in this channel.
839 This number is independent of the number of lines in the buffer.")
830 840
831 (defun rcirc-mode (process target) 841 (defun rcirc-mode (process target)
832 "Major mode for IRC channel buffers. 842 "Major mode for IRC channel buffers.
833 843
834 \\{rcirc-mode-map}" 844 \\{rcirc-mode-map}"
848 (setq rcirc-topic nil) 858 (setq rcirc-topic nil)
849 (make-local-variable 'rcirc-last-post-time) 859 (make-local-variable 'rcirc-last-post-time)
850 (setq rcirc-last-post-time (current-time)) 860 (setq rcirc-last-post-time (current-time))
851 (make-local-variable 'fill-paragraph-function) 861 (make-local-variable 'fill-paragraph-function)
852 (setq fill-paragraph-function 'rcirc-fill-paragraph) 862 (setq fill-paragraph-function 'rcirc-fill-paragraph)
863 (make-local-variable 'rcirc-recent-quit-alist)
864 (setq rcirc-recent-quit-alist nil)
865 (make-local-variable 'rcirc-current-line)
866 (setq rcirc-current-line 0)
853 867
854 (make-local-variable 'rcirc-short-buffer-name) 868 (make-local-variable 'rcirc-short-buffer-name)
855 (setq rcirc-short-buffer-name nil) 869 (setq rcirc-short-buffer-name nil)
856 (make-local-variable 'rcirc-urls) 870 (make-local-variable 'rcirc-urls)
857 (setq use-hard-newlines t) 871 (setq use-hard-newlines t)
872
873 ;; setup for omitting responses
874 (setq buffer-invisibility-spec '())
875 (setq buffer-display-table (make-display-table))
876 (set-display-table-slot buffer-display-table 4
877 (let ((glyph (make-glyph-code
878 ?. 'font-lock-keyword-face)))
879 (make-vector 3 glyph)))
858 880
859 (make-local-variable 'rcirc-decode-coding-system) 881 (make-local-variable 'rcirc-decode-coding-system)
860 (make-local-variable 'rcirc-encode-coding-system) 882 (make-local-variable 'rcirc-encode-coding-system)
861 (dolist (i rcirc-coding-system-alist) 883 (dolist (i rcirc-coding-system-alist)
862 (let ((chan (if (consp (car i)) (caar i) (car i))) 884 (let ((chan (if (consp (car i)) (caar i) (car i)))
876 (rcirc-update-prompt) 898 (rcirc-update-prompt)
877 (goto-char rcirc-prompt-end-marker) 899 (goto-char rcirc-prompt-end-marker)
878 (make-local-variable 'overlay-arrow-position) 900 (make-local-variable 'overlay-arrow-position)
879 (setq overlay-arrow-position (make-marker)) 901 (setq overlay-arrow-position (make-marker))
880 (set-marker overlay-arrow-position nil) 902 (set-marker overlay-arrow-position nil)
881
882 (setq buffer-invisibility-spec '(rcirc-ignored-user))
883 903
884 ;; if the user changes the major mode or kills the buffer, there is 904 ;; if the user changes the major mode or kills the buffer, there is
885 ;; cleanup work to do 905 ;; cleanup work to do
886 (add-hook 'change-major-mode-hook 'rcirc-change-major-mode-hook nil t) 906 (add-hook 'change-major-mode-hook 'rcirc-change-major-mode-hook nil t)
887 (add-hook 'kill-buffer-hook 'rcirc-kill-buffer-hook nil t) 907 (add-hook 'kill-buffer-hook 'rcirc-kill-buffer-hook nil t)
1003 ;; create the buffer 1023 ;; create the buffer
1004 (with-rcirc-process-buffer process 1024 (with-rcirc-process-buffer process
1005 (let ((new-buffer (get-buffer-create 1025 (let ((new-buffer (get-buffer-create
1006 (rcirc-generate-new-buffer-name process target)))) 1026 (rcirc-generate-new-buffer-name process target))))
1007 (with-current-buffer new-buffer 1027 (with-current-buffer new-buffer
1008 (rcirc-mode process target)) 1028 (rcirc-mode process target)
1009 (rcirc-put-nick-channel process (rcirc-nick process) target) 1029 (rcirc-put-nick-channel process (rcirc-nick process) target
1030 rcirc-current-line))
1010 new-buffer))))) 1031 new-buffer)))))
1011 1032
1012 (defun rcirc-send-input () 1033 (defun rcirc-send-input ()
1013 "Send input to target associated with the current buffer." 1034 "Send input to target associated with the current buffer."
1014 (interactive) 1035 (interactive)
1088 (defun rcirc-edit-multiline () 1109 (defun rcirc-edit-multiline ()
1089 "Move current edit to a dedicated buffer." 1110 "Move current edit to a dedicated buffer."
1090 (interactive) 1111 (interactive)
1091 (let ((pos (1+ (- (point) rcirc-prompt-end-marker)))) 1112 (let ((pos (1+ (- (point) rcirc-prompt-end-marker))))
1092 (goto-char (point-max)) 1113 (goto-char (point-max))
1093 (let ((text (buffer-substring rcirc-prompt-end-marker (point))) 1114 (let ((text (buffer-substring-no-properties rcirc-prompt-end-marker
1115 (point)))
1094 (parent (buffer-name))) 1116 (parent (buffer-name)))
1095 (delete-region rcirc-prompt-end-marker (point)) 1117 (delete-region rcirc-prompt-end-marker (point))
1096 (setq rcirc-window-configuration (current-window-configuration)) 1118 (setq rcirc-window-configuration (current-window-configuration))
1097 (pop-to-buffer (concat "*multiline " parent "*")) 1119 (pop-to-buffer (concat "*multiline " parent "*"))
1098 (funcall rcirc-multiline-major-mode) 1120 (funcall rcirc-multiline-major-mode)
1185 (const :tag "Default" t)) 1207 (const :tag "Default" t))
1186 :value-type string) 1208 :value-type string)
1187 :group 'rcirc) 1209 :group 'rcirc)
1188 1210
1189 (defcustom rcirc-omit-responses 1211 (defcustom rcirc-omit-responses
1190 '("JOIN" "PART" "QUIT") 1212 '("JOIN" "PART" "QUIT" "NICK")
1191 "Responses which will be hidden when `rcirc-omit-mode' is enabled." 1213 "Responses which will be hidden when `rcirc-omit-mode' is enabled."
1192 :type '(repeat string) 1214 :type '(repeat string)
1193 :group 'rcirc) 1215 :group 'rcirc)
1194 1216
1195 (defun rcirc-format-response-string (process sender response target text) 1217 (defun rcirc-format-response-string (process sender response target text)
1279 "Non-nil means log IRC activity to disk. 1301 "Non-nil means log IRC activity to disk.
1280 Logfiles are kept in `rcirc-log-directory'." 1302 Logfiles are kept in `rcirc-log-directory'."
1281 :type 'boolean 1303 :type 'boolean
1282 :group 'rcirc) 1304 :group 'rcirc)
1283 1305
1306 (defcustom rcirc-omit-threshold 100
1307 "Number of lines since last activity from a nick before `rcirc-omit-responses' are omitted."
1308 :type 'integer
1309 :group 'rcirc)
1310
1311 (defun rcirc-last-quit-line (process nick target)
1312 "Return the line number where NICK left TARGET.
1313 Returns nil if the information is not recorded."
1314 (let ((chanbuf (rcirc-get-buffer process target)))
1315 (when chanbuf
1316 (cdr (assoc-string nick (with-current-buffer chanbuf
1317 rcirc-recent-quit-alist))))))
1318
1319 (defun rcirc-last-line (process nick target)
1320 "Return the line from the last activity from NICK in TARGET."
1321 (let* ((chanbuf (rcirc-get-buffer process target))
1322 (line (or (cdr (assoc-string target
1323 (gethash nick (with-rcirc-server-buffer
1324 rcirc-nick-table)) t))
1325 (rcirc-last-quit-line process nick target))))
1326 (if line
1327 line
1328 ;;(message "line is nil for %s in %s" nick target)
1329 nil)))
1330
1331 (defun rcirc-elapsed-lines (process nick target)
1332 "Return the number of lines since activity from NICK in TARGET."
1333 (let ((last-activity-line (rcirc-last-line process nick target)))
1334 (when (and last-activity-line
1335 (> last-activity-line 0))
1336 (- rcirc-current-line last-activity-line))))
1337
1284 (defvar rcirc-markup-text-functions 1338 (defvar rcirc-markup-text-functions
1285 '(rcirc-markup-attributes 1339 '(rcirc-markup-attributes
1286 rcirc-markup-my-nick 1340 rcirc-markup-my-nick
1287 rcirc-markup-urls 1341 rcirc-markup-urls
1288 rcirc-markup-keywords 1342 rcirc-markup-keywords
1289 rcirc-markup-bright-nicks 1343 rcirc-markup-bright-nicks)
1290 rcirc-markup-fill)
1291 1344
1292 "List of functions used to manipulate text before it is printed. 1345 "List of functions used to manipulate text before it is printed.
1293 1346
1294 Each function takes two arguments, SENDER, RESPONSE. The buffer 1347 Each function takes two arguments, SENDER, and RESPONSE. The
1295 is narrowed with the text to be printed and the point is at the 1348 buffer is narrowed with the text to be printed and the point is
1296 beginning of the `rcirc-text' propertized text.") 1349 at the beginning of the `rcirc-text' propertized text.")
1297 1350
1298 (defun rcirc-print (process sender response target text &optional activity) 1351 (defun rcirc-print (process sender response target text &optional activity)
1299 "Print TEXT in the buffer associated with TARGET. 1352 "Print TEXT in the buffer associated with TARGET.
1300 Format based on SENDER and RESPONSE. If ACTIVITY is non-nil, 1353 Format based on SENDER and RESPONSE. If ACTIVITY is non-nil,
1301 record activity." 1354 record activity."
1303 (unless (and (or (member sender rcirc-ignore-list) 1356 (unless (and (or (member sender rcirc-ignore-list)
1304 (member (with-syntax-table rcirc-nick-syntax-table 1357 (member (with-syntax-table rcirc-nick-syntax-table
1305 (when (string-match "^\\([^/]\\w*\\)[:,]" text) 1358 (when (string-match "^\\([^/]\\w*\\)[:,]" text)
1306 (match-string 1 text))) 1359 (match-string 1 text)))
1307 rcirc-ignore-list)) 1360 rcirc-ignore-list))
1308 (not (string= sender (rcirc-nick process)))) 1361 ;; do not ignore if we sent the message
1362 (not (string= sender (rcirc-nick process))))
1309 (let* ((buffer (rcirc-target-buffer process sender response target text)) 1363 (let* ((buffer (rcirc-target-buffer process sender response target text))
1310 (inhibit-read-only t)) 1364 (inhibit-read-only t))
1311 (with-current-buffer buffer 1365 (with-current-buffer buffer
1312 (let ((moving (= (point) rcirc-prompt-end-marker)) 1366 (let ((moving (= (point) rcirc-prompt-end-marker))
1313 (old-point (point-marker)) 1367 (old-point (point-marker))
1348 (point))) 1402 (point)))
1349 (when (rcirc-buffer-process) 1403 (when (rcirc-buffer-process)
1350 (save-excursion (rcirc-markup-timestamp sender response)) 1404 (save-excursion (rcirc-markup-timestamp sender response))
1351 (dolist (fn rcirc-markup-text-functions) 1405 (dolist (fn rcirc-markup-text-functions)
1352 (save-excursion (funcall fn sender response))) 1406 (save-excursion (funcall fn sender response)))
1353 (save-excursion (rcirc-markup-fill sender response))) 1407 (when rcirc-fill-flag
1408 (save-excursion (rcirc-markup-fill sender response))))
1354 1409
1355 (when rcirc-read-only-flag 1410 (when rcirc-read-only-flag
1356 (add-text-properties (point-min) (point-max) 1411 (add-text-properties (point-min) (point-max)
1357 '(read-only t front-sticky t)))) 1412 '(read-only t front-sticky t))))
1358 ;; make text omittable 1413 ;; make text omittable
1359 (when (and (member response rcirc-omit-responses) 1414 (let ((last-activity-lines (rcirc-elapsed-lines process sender target)))
1360 (> start (point-min))) 1415 (if (and (not (string= (rcirc-nick process) sender))
1361 (put-text-property (1- start) (1- rcirc-prompt-start-marker) 1416 (member response rcirc-omit-responses)
1362 'invisible 'rcirc-omit)))) 1417 (or (not last-activity-lines)
1418 (< rcirc-omit-threshold last-activity-lines)))
1419 (put-text-property (1- start) (1- rcirc-prompt-start-marker)
1420 'invisible 'rcirc-omit)
1421 ;; otherwise increment the line count
1422 (setq rcirc-current-line (1+ rcirc-current-line))))))
1363 1423
1364 (set-marker-insertion-type rcirc-prompt-start-marker nil) 1424 (set-marker-insertion-type rcirc-prompt-start-marker nil)
1365 (set-marker-insertion-type rcirc-prompt-end-marker nil) 1425 (set-marker-insertion-type rcirc-prompt-end-marker nil)
1366 1426
1367 ;; truncate buffer if it is very long 1427 ;; truncate buffer if it is very long
1440 Log data is written to `rcirc-log-directory'." 1500 Log data is written to `rcirc-log-directory'."
1441 (make-directory rcirc-log-directory t) 1501 (make-directory rcirc-log-directory t)
1442 (dolist (cell rcirc-log-alist) 1502 (dolist (cell rcirc-log-alist)
1443 (with-temp-buffer 1503 (with-temp-buffer
1444 (insert (cdr cell)) 1504 (insert (cdr cell))
1445 (write-region (point-min) (point-max) 1505 (let ((coding-system-for-write 'utf-8))
1446 (concat rcirc-log-directory "/" (car cell)) 1506 (write-region (point-min) (point-max)
1447 t 'quiet))) 1507 (concat rcirc-log-directory "/" (car cell))
1508 t 'quiet))))
1448 (setq rcirc-log-alist nil)) 1509 (setq rcirc-log-alist nil))
1449 1510
1450 (defun rcirc-join-channels (process channels) 1511 (defun rcirc-join-channels (process channels)
1451 "Join CHANNELS." 1512 "Join CHANNELS."
1452 (save-window-excursion 1513 (save-window-excursion
1468 "Return list of channels for NICK." 1529 "Return list of channels for NICK."
1469 (with-rcirc-process-buffer process 1530 (with-rcirc-process-buffer process
1470 (mapcar (lambda (x) (car x)) 1531 (mapcar (lambda (x) (car x))
1471 (gethash nick rcirc-nick-table)))) 1532 (gethash nick rcirc-nick-table))))
1472 1533
1473 (defun rcirc-put-nick-channel (process nick channel) 1534 (defun rcirc-put-nick-channel (process nick channel &optional line)
1474 "Add CHANNEL to list associated with NICK." 1535 "Add CHANNEL to list associated with NICK.
1536 Update the associated linestamp if LINE is non-nil.
1537
1538 If the record doesn't exist, and LINE is nil, set the linestamp
1539 to zero."
1475 (let ((nick (rcirc-user-nick nick))) 1540 (let ((nick (rcirc-user-nick nick)))
1476 (with-rcirc-process-buffer process 1541 (with-rcirc-process-buffer process
1477 (let* ((chans (gethash nick rcirc-nick-table)) 1542 (let* ((chans (gethash nick rcirc-nick-table))
1478 (record (assoc-string channel chans t))) 1543 (record (assoc-string channel chans t)))
1479 (if record 1544 (if record
1480 (setcdr record (current-time)) 1545 (when line (setcdr record line))
1481 (puthash nick (cons (cons channel (current-time)) 1546 (puthash nick (cons (cons channel (or line 0))
1482 chans) 1547 chans)
1483 rcirc-nick-table)))))) 1548 rcirc-nick-table))))))
1484 1549
1485 (defun rcirc-nick-remove (process nick) 1550 (defun rcirc-nick-remove (process nick)
1486 "Remove NICK from table." 1551 "Remove NICK from table."
1512 (let ((record (assoc-string target v t))) 1577 (let ((record (assoc-string target v t)))
1513 (if record 1578 (if record
1514 (setq nicks (cons (cons k (cdr record)) nicks))))) 1579 (setq nicks (cons (cons k (cdr record)) nicks)))))
1515 rcirc-nick-table) 1580 rcirc-nick-table)
1516 (mapcar (lambda (x) (car x)) 1581 (mapcar (lambda (x) (car x))
1517 (sort nicks (lambda (x y) (time-less-p (cdr y) (cdr x))))))) 1582 (sort nicks (lambda (x y)
1583 (let ((lx (or (cdr x) 0))
1584 (ly (or (cdr y) 0)))
1585 (< ly lx)))))))
1518 (list target)))) 1586 (list target))))
1519 1587
1520 (defun rcirc-ignore-update-automatic (nick) 1588 (defun rcirc-ignore-update-automatic (nick)
1521 "Remove NICK from `rcirc-ignore-list' 1589 "Remove NICK from `rcirc-ignore-list'
1522 if NICK is also on `rcirc-ignore-list-automatic'." 1590 if NICK is also on `rcirc-ignore-list-automatic'."
1591 If enabled, \"uninteresting\" lines are not shown. 1659 If enabled, \"uninteresting\" lines are not shown.
1592 Uninteresting lines are those whose responses are listed in 1660 Uninteresting lines are those whose responses are listed in
1593 `rcirc-omit-responses'." 1661 `rcirc-omit-responses'."
1594 (interactive) 1662 (interactive)
1595 (setq rcirc-omit-mode (not rcirc-omit-mode)) 1663 (setq rcirc-omit-mode (not rcirc-omit-mode))
1596 (let ((line (1- (count-screen-lines (point) (window-start))))) 1664 (if rcirc-omit-mode
1597 (if rcirc-omit-mode 1665 (progn
1598 (progn 1666 (add-to-invisibility-spec '(rcirc-omit . t))
1599 (add-to-invisibility-spec 'rcirc-omit) 1667 (message "Rcirc-Omit mode enabled"))
1600 (message "Rcirc-Omit mode enabled")) 1668 (remove-from-invisibility-spec '(rcirc-omit . t))
1601 (remove-from-invisibility-spec 'rcirc-omit) 1669 (message "Rcirc-Omit mode disabled"))
1602 (message "Rcirc-Omit mode disabled")) 1670 (recenter (when (> (point) rcirc-prompt-start-marker) -1)))
1603 (recenter line))
1604 (force-mode-line-update))
1605 1671
1606 (defun rcirc-switch-to-server-buffer () 1672 (defun rcirc-switch-to-server-buffer ()
1607 "Switch to the server buffer associated with current channel buffer." 1673 "Switch to the server buffer associated with current channel buffer."
1608 (interactive) 1674 (interactive)
1609 (switch-to-buffer rcirc-server-buffer)) 1675 (switch-to-buffer rcirc-server-buffer))
1634 (let* ((pair (rcirc-split-activity rcirc-activity)) 1700 (let* ((pair (rcirc-split-activity rcirc-activity))
1635 (lopri (car pair)) 1701 (lopri (car pair))
1636 (hipri (cdr pair))) 1702 (hipri (cdr pair)))
1637 (if (or (and (not arg) hipri) 1703 (if (or (and (not arg) hipri)
1638 (and arg lopri)) 1704 (and arg lopri))
1639 (switch-to-buffer (car (if arg lopri hipri)) t) 1705 (progn
1706 (switch-to-buffer (car (if arg lopri hipri)))
1707 (when (> (point) rcirc-prompt-start-marker)
1708 (recenter -1)))
1640 (if (eq major-mode 'rcirc-mode) 1709 (if (eq major-mode 'rcirc-mode)
1641 (switch-to-buffer (rcirc-non-irc-buffer)) 1710 (switch-to-buffer (rcirc-non-irc-buffer))
1642 (message (concat 1711 (message (concat
1643 "No IRC activity." 1712 "No IRC activity."
1644 (when lopri 1713 (when lopri
2167 (defun rcirc-markup-fill (sender response) 2236 (defun rcirc-markup-fill (sender response)
2168 (when (not (string= response "372")) ; /motd 2237 (when (not (string= response "372")) ; /motd
2169 (let ((fill-prefix 2238 (let ((fill-prefix
2170 (or rcirc-fill-prefix 2239 (or rcirc-fill-prefix
2171 (make-string (- (point) (line-beginning-position)) ?\s))) 2240 (make-string (- (point) (line-beginning-position)) ?\s)))
2172 (fill-column (cond ((eq rcirc-fill-column 'frame-width) 2241 (fill-column (- (cond ((eq rcirc-fill-column 'frame-width)
2173 (1- (frame-width))) 2242 (1- (frame-width)))
2174 (rcirc-fill-column 2243 (rcirc-fill-column
2175 rcirc-fill-column) 2244 rcirc-fill-column)
2176 (t fill-column)))) 2245 (t fill-column))
2246 ;; make sure ... doesn't cause line wrapping
2247 3)))
2177 (fill-region (point) (point-max) nil t)))) 2248 (fill-region (point) (point-max) nil t))))
2178 2249
2179 ;;; handlers 2250 ;;; handlers
2180 ;; these are called with the server PROCESS, the SENDER, which is a 2251 ;; these are called with the server PROCESS, the SENDER, which is a
2181 ;; server or a user, depending on the command, the ARGS, which is a 2252 ;; server or a user, depending on the command, the ARGS, which is a
2182 ;; list of strings, and the TEXT, which is the original server text, 2253 ;; list of strings, and the TEXT, which is the original server text,
2183 ;; verbatim 2254 ;; verbatim
2184 (defun rcirc-handler-001 (process sender args text) 2255 (defun rcirc-handler-001 (process sender args text)
2185 (rcirc-handler-generic process "001" sender args text) 2256 (rcirc-handler-generic process "001" sender args text)
2186 ;; set the real server name
2187 (with-rcirc-process-buffer process 2257 (with-rcirc-process-buffer process
2188 (setq rcirc-connecting nil) 2258 (setq rcirc-connecting nil)
2189 (rcirc-reschedule-timeout process) 2259 (rcirc-reschedule-timeout process)
2190 (setq rcirc-server-name sender) 2260 (setq rcirc-server-name sender)
2191 (setq rcirc-nick (car args)) 2261 (setq rcirc-nick (car args))
2199 sender)) 2269 sender))
2200 (message (or (cadr args) ""))) 2270 (message (or (cadr args) "")))
2201 (if (string-match "^\C-a\\(.*\\)\C-a$" message) 2271 (if (string-match "^\C-a\\(.*\\)\C-a$" message)
2202 (rcirc-handler-CTCP process target sender (match-string 1 message)) 2272 (rcirc-handler-CTCP process target sender (match-string 1 message))
2203 (rcirc-print process sender "PRIVMSG" target message t)) 2273 (rcirc-print process sender "PRIVMSG" target message t))
2204 ;; update nick timestamp 2274 ;; update nick linestamp
2205 (if (member target (rcirc-nick-channels process sender)) 2275 (with-current-buffer (rcirc-get-buffer process target t)
2206 (rcirc-put-nick-channel process sender target)))) 2276 (rcirc-put-nick-channel process sender target rcirc-current-line))))
2207 2277
2208 (defun rcirc-handler-NOTICE (process sender args text) 2278 (defun rcirc-handler-NOTICE (process sender args text)
2209 (let ((target (car args)) 2279 (let ((target (car args))
2210 (message (cadr args))) 2280 (message (cadr args)))
2211 (if (string-match "^\C-a\\(.*\\)\C-a$" message) 2281 (if (string-match "^\C-a\\(.*\\)\C-a$" message)
2226 (defun rcirc-handler-WALLOPS (process sender args text) 2296 (defun rcirc-handler-WALLOPS (process sender args text)
2227 (rcirc-print process sender "WALLOPS" sender (car args) t)) 2297 (rcirc-print process sender "WALLOPS" sender (car args) t))
2228 2298
2229 (defun rcirc-handler-JOIN (process sender args text) 2299 (defun rcirc-handler-JOIN (process sender args text)
2230 (let ((channel (car args))) 2300 (let ((channel (car args)))
2231 (rcirc-get-buffer-create process channel) 2301 (with-current-buffer (rcirc-get-buffer-create process channel)
2302 ;; when recently rejoining, restore the linestamp
2303 (rcirc-put-nick-channel process sender channel
2304 (let ((last-activity-lines
2305 (rcirc-elapsed-lines process sender channel)))
2306 (when (and last-activity-lines
2307 (< last-activity-lines rcirc-omit-threshold))
2308 (rcirc-last-line process sender channel)))))
2309
2232 (rcirc-print process sender "JOIN" channel "") 2310 (rcirc-print process sender "JOIN" channel "")
2233 2311
2234 ;; print in private chat buffer if it exists 2312 ;; print in private chat buffer if it exists
2235 (when (rcirc-get-buffer (rcirc-buffer-process) sender) 2313 (when (rcirc-get-buffer (rcirc-buffer-process) sender)
2236 (rcirc-print process sender "JOIN" sender channel)) 2314 (rcirc-print process sender "JOIN" sender channel))))
2237
2238 (rcirc-put-nick-channel process sender channel)))
2239 2315
2240 ;; PART and KICK are handled the same way 2316 ;; PART and KICK are handled the same way
2241 (defun rcirc-handler-PART-or-KICK (process response channel sender nick args) 2317 (defun rcirc-handler-PART-or-KICK (process response channel sender nick args)
2242 (rcirc-ignore-update-automatic nick) 2318 (rcirc-ignore-update-automatic nick)
2243 (if (not (string= nick (rcirc-nick process))) 2319 (if (not (string= nick (rcirc-nick process)))
2244 ;; this is someone else leaving 2320 ;; this is someone else leaving
2245 (rcirc-remove-nick-channel process nick channel) 2321 (progn
2322 (rcirc-maybe-remember-nick-quit process nick channel)
2323 (rcirc-remove-nick-channel process nick channel))
2246 ;; this is us leaving 2324 ;; this is us leaving
2247 (mapc (lambda (n) 2325 (mapc (lambda (n)
2248 (rcirc-remove-nick-channel process n channel)) 2326 (rcirc-remove-nick-channel process n channel))
2249 (rcirc-channel-nicks process channel)) 2327 (rcirc-channel-nicks process channel))
2250 2328
2274 (when (rcirc-get-buffer (rcirc-buffer-process) nick) 2352 (when (rcirc-get-buffer (rcirc-buffer-process) nick)
2275 (rcirc-print process sender "KICK" nick message)) 2353 (rcirc-print process sender "KICK" nick message))
2276 2354
2277 (rcirc-handler-PART-or-KICK process "KICK" channel sender nick reason))) 2355 (rcirc-handler-PART-or-KICK process "KICK" channel sender nick reason)))
2278 2356
2357 (defun rcirc-maybe-remember-nick-quit (process nick channel)
2358 "Remember NICK as leaving CHANNEL if they recently spoke."
2359 (let ((elapsed-lines (rcirc-elapsed-lines process nick channel)))
2360 (when (and elapsed-lines
2361 (< elapsed-lines rcirc-omit-threshold))
2362 (let ((buffer (rcirc-get-buffer process channel)))
2363 (when buffer
2364 (with-current-buffer buffer
2365 (let ((record (assoc-string nick rcirc-recent-quit-alist t))
2366 (line (rcirc-last-line process nick channel)))
2367 (if record
2368 (setcdr record line)
2369 (setq rcirc-recent-quit-alist
2370 (cons (cons nick line)
2371 rcirc-recent-quit-alist))))))))))
2372
2279 (defun rcirc-handler-QUIT (process sender args text) 2373 (defun rcirc-handler-QUIT (process sender args text)
2280 (rcirc-ignore-update-automatic sender) 2374 (rcirc-ignore-update-automatic sender)
2281 (mapc (lambda (channel) 2375 (mapc (lambda (channel)
2282 (rcirc-print process sender "QUIT" channel (apply 'concat args))) 2376 ;; broadcast quit message each channel
2377 (rcirc-print process sender "QUIT" channel (apply 'concat args))
2378 ;; record nick in quit table if they recently spoke
2379 (rcirc-maybe-remember-nick-quit process sender channel))
2283 (rcirc-nick-channels process sender)) 2380 (rcirc-nick-channels process sender))
2284
2285 ;; print in private chat buffer if it exists
2286 (when (rcirc-get-buffer (rcirc-buffer-process) sender)
2287 (rcirc-print process sender "QUIT" sender (apply 'concat args)))
2288
2289 (rcirc-nick-remove process sender)) 2381 (rcirc-nick-remove process sender))
2290 2382
2291 (defun rcirc-handler-NICK (process sender args text) 2383 (defun rcirc-handler-NICK (process sender args text)
2292 (let* ((old-nick sender) 2384 (let* ((old-nick sender)
2293 (new-nick (car args)) 2385 (new-nick (car args))