diff --ignore-space-change -c '-F^[_a-zA-Z0-9$]+ *(' projects/emacs/lisp/erc/ChangeLog projects/emacs-dev/lisp/erc/ChangeLog *** projects/emacs/lisp/erc/ChangeLog 2014-06-10 09:04:50.536885271 -0400 --- projects/emacs-dev/lisp/erc/ChangeLog 2014-06-11 07:30:02.422563635 -0400 *************** *** 1,3 **** --- 1,15 ---- + 2014-06-11 Kelvin White + + * erc-backend.el Handle user modes in relevent server responses + * erc.el Better user mode support. + (erc-channel-user): Add members for new modes. + (erc-channel-member-halfop-p, erc-channel-user-admin-p, erc-channel-user-owner-p): Use new struct members. + (erc-format-nick, erc-format-@nick): Display user modes as nick prefix. + (erc-nick-prefix-face, erc-my-nick-prefix-face): Add new faces to separate colors if desired. + (erc-get-user-mode-prefix): Return symbol for mode prefix. + (erc-update-channel-member, erc-update-current-channel-member, erc-channel-receive-names): Update channel users. + (erc-nick-at-point): Return correct user info. + 2014-04-04 Stefan Monnier * erc.el (erc-invite-only-mode, erc-toggle-channel-mode): Simplify. *************** *** 615,618 **** ;; coding: utf-8 ;; add-log-time-zone-rule: t ;; End: - --- 627,629 ---- diff --ignore-space-change -c '-F^[_a-zA-Z0-9$]+ *(' projects/emacs/lisp/erc/erc-backend.el projects/emacs-dev/lisp/erc/erc-backend.el *** projects/emacs/lisp/erc/erc-backend.el 2014-06-11 06:53:48.176451824 -0400 --- projects/emacs-dev/lisp/erc/erc-backend.el 2014-06-11 06:55:57.682449183 -0400 *************** *** 1244,1250 **** (erc-format-message 'JOIN ?n nick ?u login ?h host ?c chnl)))))) (when buffer (set-buffer buffer)) ! (erc-update-channel-member chnl nick nick t nil nil host login) ;; on join, we want to stay in the new channel buffer ;;(set-buffer ob) (erc-display-message parsed nil buffer str)))))) --- 1244,1250 ---- (erc-format-message 'JOIN ?n nick ?u login ?h host ?c chnl)))))) (when buffer (set-buffer buffer)) ! (erc-update-channel-member chnl nick nick t nil nil nil nil nil host login) ;; on join, we want to stay in the new channel buffer ;;(set-buffer ob) (erc-display-message parsed nil buffer str)))))) *************** *** 1413,1419 **** ;; message. We will accumulate private identities indefinitely ;; at this point. (erc-update-channel-member (if privp nick tgt) nick nick ! privp nil nil host login nil nil t) (let ((cdata (erc-get-channel-user nick))) (setq fnick (funcall erc-format-nick-function (car cdata) (cdr cdata)))))) --- 1413,1419 ---- ;; message. We will accumulate private identities indefinitely ;; at this point. (erc-update-channel-member (if privp nick tgt) nick nick ! privp nil nil nil nil nil host login nil nil t) (let ((cdata (erc-get-channel-user nick))) (setq fnick (funcall erc-format-nick-function (car cdata) (cdr cdata)))))) *************** *** 1470,1476 **** (current-time)))) (pcase-let ((`(,nick ,login ,host) (erc-parse-user (erc-response.sender parsed)))) ! (erc-update-channel-member ch nick nick nil nil nil host login) (erc-update-channel-topic ch (format "%s\C-o (%s, %s)" topic nick time)) (erc-display-message parsed 'notice (erc-get-buffer ch proc) 'TOPIC ?n nick ?u login ?h host --- 1470,1476 ---- (current-time)))) (pcase-let ((`(,nick ,login ,host) (erc-parse-user (erc-response.sender parsed)))) ! (erc-update-channel-member ch nick nick nil nil nil nil nil nil host login) (erc-update-channel-topic ch (format "%s\C-o (%s, %s)" topic nick time)) (erc-display-message parsed 'notice (erc-get-buffer ch proc) 'TOPIC ?n nick ?u login ?h host *************** *** 1800,1807 **** (when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name) (setq hopcount (match-string 1 full-name)) (setq full-name (match-string 2 full-name))) ! (erc-update-channel-member channel nick nick nil nil nil host ! user full-name) (erc-display-message parsed 'notice 'active 's352 ?c channel ?n nick ?a away-flag ?u user ?h host ?f full-name)))) --- 1800,1806 ---- (when (string-match "\\(^[0-9]+ \\)\\(.*\\)$" full-name) (setq hopcount (match-string 1 full-name)) (setq full-name (match-string 2 full-name))) ! (erc-update-channel-member channel nick nick nil nil nil nil nil nil host user full-name) (erc-display-message parsed 'notice 'active 's352 ?c channel ?n nick ?a away-flag ?u user ?h host ?f full-name)))) diff --ignore-space-change -c '-F^[_a-zA-Z0-9$]+ *(' projects/emacs/lisp/erc/erc.el projects/emacs-dev/lisp/erc/erc.el *** projects/emacs/lisp/erc/erc.el 2014-06-11 06:53:48.176451824 -0400 --- projects/emacs-dev/lisp/erc/erc.el 2014-06-11 07:09:49.603393410 -0400 *************** *** 370,376 **** ) (cl-defstruct (erc-channel-user (:type vector) :named) ! op voice ;; Last message time (in the form of the return value of ;; (current-time) ;; --- 370,376 ---- ) (cl-defstruct (erc-channel-user (:type vector) :named) ! voice halfop op admin owner ;; Last message time (in the form of the return value of ;; (current-time) ;; *************** *** 475,480 **** --- 475,496 ---- erc-channel-users) (clrhash erc-channel-users))) + (defsubst erc-channel-user-owner-p (nick) + "Return t if NICK is an owner of the current channel." + (and nick + (hash-table-p erc-channel-users) + (let ((cdata (erc-get-channel-user nick))) + (and cdata (cdr cdata) + (erc-channel-user-owner (cdr cdata)))))) + + (defsubst erc-channel-user-admin-p (nick) + "Return t if NICK is an admin in the current channel." + (and nick + (hash-table-p erc-channel-users) + (let ((cdata (erc-get-channel-user nick))) + (and cdata (cdr cdata) + (erc-channel-user-admin (cdr cdata)))))) + (defsubst erc-channel-user-op-p (nick) "Return t if NICK is an operator in the current channel." (and nick *************** *** 483,488 **** --- 499,512 ---- (and cdata (cdr cdata) (erc-channel-user-op (cdr cdata)))))) + (defsubst erc-channel-user-halfop-p (nick) + "Return t if NICK is a half-operator in the current channel." + (and nick + (hash-table-p erc-channel-users) + (let ((cdata (erc-get-channel-user nick))) + (and cdata (cdr cdata) + (erc-channel-user-halfop (cdr cdata)))))) + (defsubst erc-channel-user-voice-p (nick) "Return t if NICK has voice in the current channel." (and nick *************** *** 1122,1127 **** --- 1146,1159 ---- "ERC default face." :group 'erc-faces) + (defface erc-nick-prefix-face '((t :weight bold)) + "ERC face used for user mode prefix." + :group 'erc-faces) + + (defface erc-my-nick-prefix-face '((t :weight bold)) + "ERC face used for my user mode prefix." + :group 'erc-faces) + (defface erc-direct-msg-face '((t :foreground "IndianRed")) "ERC face used for messages you receive in the main erc buffer." :group 'erc-faces) *************** *** 4192,4215 **** See also `erc-format-nick-function'." (when user (erc-server-user-nickname user))) (defun erc-format-@nick (&optional user channel-data) "Format the nickname of USER showing if USER is an operator or has voice. Operators have \"@\" and users with voice have \"+\" as a prefix. Use CHANNEL-DATA to determine op and voice status. See also `erc-format-nick-function'." (when user ! (let ((op (and channel-data (erc-channel-user-op channel-data) "@")) ! (voice (and channel-data (erc-channel-user-voice channel-data) "+"))) ! (concat voice op (erc-server-user-nickname user))))) (defun erc-format-my-nick () "Return the beginning of this user's message, correctly propertized." (if erc-show-my-nick ! (let ((open "<") (close "> ") ! (nick (erc-current-nick))) (concat (erc-propertize open 'face 'erc-default-face) (erc-propertize nick 'face 'erc-my-nick-face) (erc-propertize close 'face 'erc-default-face))) (let ((prefix "> ")) --- 4224,4257 ---- See also `erc-format-nick-function'." (when user (erc-server-user-nickname user))) + (defun erc-get-user-mode-prefix (user) + (when user + (cond ((erc-channel-user-voice-p user) "+") + ((erc-channel-user-half-op-p user) "%") + ((erc-channel-user-op-p user) "@") + ((erc-channel-user-admin-p user) "&") + ((erc-channel-user-owner-p user) "~") + (t "")))) + (defun erc-format-@nick (&optional user channel-data) "Format the nickname of USER showing if USER is an operator or has voice. Operators have \"@\" and users with voice have \"+\" as a prefix. Use CHANNEL-DATA to determine op and voice status. See also `erc-format-nick-function'." (when user ! (let ((nick (erc-server-user-nickname user))) ! (concat (erc-propertize (erc-get-user-mode-prefix nick) 'face 'erc-nick-prefix-face) nick)))) (defun erc-format-my-nick () "Return the beginning of this user's message, correctly propertized." (if erc-show-my-nick ! (let* ((open "<") (close "> ") ! (nick (erc-current-nick)) ! (mode (erc-get-user-mode-prefix nick))) (concat (erc-propertize open 'face 'erc-default-face) + (erc-propertize mode 'face 'erc-my-nick-prefix-face) (erc-propertize nick 'face 'erc-my-nick-face) (erc-propertize close 'face 'erc-default-face))) (let ((prefix "> ")) *************** *** 4685,4691 **** (let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer erc-server-parameters))) ;; provide a sane default ! "(ov)@+")) types chars) (when (string-match "^(\\([^)]+\\))\\(.+\\)$" str) (setq types (match-string 1 str) --- 4727,4733 ---- (let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer erc-server-parameters))) ;; provide a sane default ! "(qaohv)~&@%+")) types chars) (when (string-match "^(\\([^)]+\\))\\(.+\\)$" str) (setq types (match-string 1 str) *************** *** 4705,4714 **** Update `erc-channel-users' according to NAMES-STRING. NAMES-STRING is a string listing some of the names on the channel." ! (let (prefix op-ch voice-ch names name op voice) (setq prefix (erc-parse-prefix)) ! (setq op-ch (cdr (assq ?o prefix)) ! voice-ch (cdr (assq ?v prefix))) ;; We need to delete "" because in XEmacs, (split-string "a ") ;; returns ("a" ""). (setq names (delete "" (split-string names-string))) --- 4747,4759 ---- Update `erc-channel-users' according to NAMES-STRING. NAMES-STRING is a string listing some of the names on the channel." ! (let (prefix voice-ch hop-ch op-ch adm-ch own-ch names name voice halfop op admin owner) (setq prefix (erc-parse-prefix)) ! (setq voice-ch (cdr (assq ?v prefix)) ! hop-ch (cdr (assq ?h prefix)) ! op-ch (cdr (assq ?o prefix)) ! adm-ch (cdr (assq ?a prefix)) ! own-ch (cdr (assq ?q prefix))) ;; We need to delete "" because in XEmacs, (split-string "a ") ;; returns ("a" ""). (setq names (delete "" (split-string names-string))) *************** *** 4718,4742 **** (if (rassq (elt item 0) prefix) (cond ((= (length item) 1) (setq updatep nil)) ((eq (elt item 0) op-ch) (setq name (substring item 1) op 'on ! voice 'off)) ! ((eq (elt item 0) voice-ch) (setq name (substring item 1) op 'off ! voice 'on)) (t (setq name (substring item 1) op 'off ! voice 'off))) (setq name item op 'off ! voice 'off)) (when updatep (puthash (erc-downcase name) t erc-channel-new-member-names) (erc-update-current-channel-member ! name name t op voice))))) (run-hooks 'erc-channel-members-changed-hook))) (defcustom erc-channel-members-changed-hook nil --- 4763,4820 ---- (if (rassq (elt item 0) prefix) (cond ((= (length item) 1) (setq updatep nil)) + ((eq (elt item 0) voice-ch) + (setq name (substring item 1) + op 'off + voice 'on + halfop 'off + admin 'off + owner 'off)) + ((eq (elt item 0) hop-ch) + (setq name (substring item 1) + op 'off + voice 'off + halfop 'on + admin 'off + owner 'off)) ((eq (elt item 0) op-ch) (setq name (substring item 1) op 'on ! voice 'off ! halfop 'off ! admin 'off ! owner 'off)) ! ((eq (elt item 0) adm-ch) ! (setq name (substring item 1) ! op 'off ! voice 'off ! halfop 'off ! admin 'on ! owner 'off)) ! ((eq (elt item 0) own-ch) (setq name (substring item 1) op 'off ! voice 'off ! halfop 'off ! admin 'off ! owner 'on)) (t (setq name (substring item 1) op 'off ! voice 'off ! halfop 'off ! admin 'off ! owner 'off))) (setq name item op 'off ! voice 'off ! halfop 'off ! admin 'off ! owner 'off)) (when updatep (puthash (erc-downcase name) t erc-channel-new-member-names) (erc-update-current-channel-member ! name name t voice halfop op admin owner))))) (run-hooks 'erc-channel-members-changed-hook))) (defcustom erc-channel-members-changed-hook nil *************** *** 4795,4810 **** changed)) (defun erc-update-current-channel-member ! (nick new-nick &optional add op voice host login full-name info update-message-time) "Update the stored user information for the user with nickname NICK. `erc-update-user' is called to handle changes to nickname, ! HOST, LOGIN, FULL-NAME, and INFO. If OP or VOICE are non-nil, ! they must be equal to either `on' or `off', in which case the ! operator or voice status of the user in the current channel is ! changed accordingly. If UPDATE-MESSAGE-TIME is non-nil, the ! last-message-time of the user in the current channel is set ! to (current-time). If ADD is non-nil, the user will be added with the specified information if it is not already present in the user or channel --- 4873,4887 ---- changed)) (defun erc-update-current-channel-member ! (nick new-nick &optional add voice halfop op admin owner host login full-name info update-message-time) "Update the stored user information for the user with nickname NICK. `erc-update-user' is called to handle changes to nickname, ! HOST, LOGIN, FULL-NAME, and INFO. If VOICE HALFOP OP ADMIN or OWNER ! are non-nil, they must be equal to either `on' or `off', in which ! case the status of the user in the current channel is changed accordingly. ! If UPDATE-MESSAGE-TIME is non-nil, the last-message-time of the user ! in the current channel is set to (current-time). If ADD is non-nil, the user will be added with the specified information if it is not already present in the user or channel *************** *** 4822,4827 **** --- 4899,4918 ---- (if cuser (progn (erc-log (format "update-member: user = %S, cuser = %S" user cuser)) + (when (and voice + (not (eq (erc-channel-user-voice cuser) voice))) + (setq changed t) + (setf (erc-channel-user-voice cuser) + (cond ((eq voice 'on) t) + ((eq voice 'off) nil) + (t voice)))) + (when (and halfop + (not (eq (erc-channel-user-halfop cuser) halfop))) + (setq changed t) + (setf (erc-channel-user-halfop cuser) + (cond ((eq halfop 'on) t) + ((eq halfop 'off) nil) + (t halfop)))) (when (and op (not (eq (erc-channel-user-op cuser) op))) (setq changed t) *************** *** 4829,4841 **** (cond ((eq op 'on) t) ((eq op 'off) nil) (t op)))) ! (when (and voice ! (not (eq (erc-channel-user-voice cuser) voice))) (setq changed t) ! (setf (erc-channel-user-voice cuser) ! (cond ((eq voice 'on) t) ! ((eq voice 'off) nil) ! (t voice)))) (when update-message-time (setf (erc-channel-user-last-message-time cuser) (current-time))) (setq user-changed --- 4920,4939 ---- (cond ((eq op 'on) t) ((eq op 'off) nil) (t op)))) ! (when (and admin ! (not (eq (erc-channel-user-admin cuser) admin))) (setq changed t) ! (setf (erc-channel-user-admin cuser) ! (cond ((eq admin 'on) t) ! ((eq admin 'off) nil) ! (t admin)))) ! (when (and owner ! (not (eq (erc-channel-user-owner cuser) owner))) ! (setq changed t) ! (setf (erc-channel-user-owner cuser) ! (cond ((eq owner 'on) t) ! ((eq owner 'off) nil) ! (t owner)))) (when update-message-time (setf (erc-channel-user-last-message-time cuser) (current-time))) (setq user-changed *************** *** 4856,4867 **** (cons (current-buffer) (erc-server-user-buffers user)))) (setq cuser (make-erc-channel-user - :op (cond ((eq op 'on) t) - ((eq op 'off) nil) - (t op)) :voice (cond ((eq voice 'on) t) ((eq voice 'off) nil) (t voice)) :last-message-time (if update-message-time (current-time)))) (puthash (erc-downcase nick) (cons user cuser) --- 4954,4974 ---- (cons (current-buffer) (erc-server-user-buffers user)))) (setq cuser (make-erc-channel-user :voice (cond ((eq voice 'on) t) ((eq voice 'off) nil) (t voice)) + :halfop (cond ((eq halfop 'on) t) + ((eq halfop 'off) nil) + (t halfop)) + :op (cond ((eq op 'on) t) + ((eq op 'off) nil) + (t op)) + :admin (cond ((eq admin 'on) t) + ((eq admin 'off) nil) + (t admin)) + :owner (cond ((eq owner 'on) t) + ((eq owner 'off) nil) + (t owner)) :last-message-time (if update-message-time (current-time)))) (puthash (erc-downcase nick) (cons user cuser) *************** *** 4872,4878 **** (or changed user-changed add))) (defun erc-update-channel-member (channel nick new-nick ! &optional add op voice host login full-name info update-message-time) "Update user and channel information for the user with nickname NICK in channel CHANNEL. --- 4979,4985 ---- (or changed user-changed add))) (defun erc-update-channel-member (channel nick new-nick ! &optional add voice halfop op admin owner host login full-name info update-message-time) "Update user and channel information for the user with nickname NICK in channel CHANNEL. *************** *** 4880,4886 **** See also: `erc-update-current-channel-member'." (erc-with-buffer (channel) ! (erc-update-current-channel-member nick new-nick add op voice host login full-name info update-message-time))) --- 4987,4993 ---- See also: `erc-update-current-channel-member'." (erc-with-buffer (channel) ! (erc-update-current-channel-member nick new-nick add voice halfop op admin owner host login full-name info update-message-time))) *************** *** 4979,4985 **** (while chars (cond ((string= (car chars) "+") (setq add-p t)) ((string= (car chars) "-") (setq add-p nil)) ! ((string-match "^[ovbOVB]" (car chars)) (setq arg-modes (cons (list (car chars) (if add-p 'on 'off) (if args (car args) nil)) --- 5086,5092 ---- (while chars (cond ((string= (car chars) "+") (setq add-p t)) ((string= (car chars) "-") (setq add-p nil)) ! ((string-match "^[qaovhbQAOVHB]" (car chars)) (setq arg-modes (cons (list (car chars) (if add-p 'on 'off) (if args (car args) nil)) *************** *** 5035,5045 **** (let ((mode (nth 0 (car arg-modes))) (onoff (nth 1 (car arg-modes))) (arg (nth 2 (car arg-modes)))) ! (cond ((string-match "^[oO]" mode) (erc-update-channel-member tgt arg arg nil onoff)) ! ((string-match "^[Vv]" mode) ! (erc-update-channel-member tgt arg arg nil nil ! onoff)) ((string-match "^[Ll]" mode) (erc-update-channel-limit tgt onoff arg)) ((string-match "^[Kk]" mode) --- 5142,5157 ---- (let ((mode (nth 0 (car arg-modes))) (onoff (nth 1 (car arg-modes))) (arg (nth 2 (car arg-modes)))) ! (cond ((string-match "^[Vv]" mode) (erc-update-channel-member tgt arg arg nil onoff)) ! ((string-match "^[hH]" mode) ! (erc-update-channel-member tgt arg arg nil nil onoff)) ! ((string-match "^[oO]" mode) ! (erc-update-channel-member tgt arg arg nil nil nil onoff)) ! ((string-match "^[aA]" mode) ! (erc-update-channel-member tgt arg arg nil nil nil nil onoff)) ! ((string-match "^[qQ]" mode) ! (erc-update-channel-member tgt arg arg nil nil nil nil nil onoff)) ((string-match "^[Ll]" mode) (erc-update-channel-limit tgt onoff arg)) ((string-match "^[Kk]" mode) *************** *** 5978,6003 **** (user (if channel-data (car channel-data) (erc-get-server-user word))) ! host login full-name nick op voice) (when user (setq nick (erc-server-user-nickname user) host (erc-server-user-host user) login (erc-server-user-login user) full-name (erc-server-user-full-name user)) (if cuser ! (setq op (erc-channel-user-op cuser) ! voice (erc-channel-user-voice cuser))) (if (called-interactively-p 'interactive) (message "%s is %s@%s%s%s" nick login host (if full-name (format " (%s)" full-name) "") ! (if (or op voice) (format " and is +%s%s on %s" - (if op "o" "") (if voice "v" "") (erc-default-target)) "")) ! user)))) (defun erc-away-time () "Return non-nil if the current ERC process is set away. --- 6090,6121 ---- (user (if channel-data (car channel-data) (erc-get-server-user word))) ! host login full-name nick voice halfop op admin owner) (when user (setq nick (erc-server-user-nickname user) host (erc-server-user-host user) login (erc-server-user-login user) full-name (erc-server-user-full-name user)) (if cuser ! (setq voice (erc-channel-user-voice cuser) ! halfop (erc-channel-user-halfop cuser) ! op (erc-channel-user-op cuser) ! admin (erc-channel-user-admin cuser) ! owner (erc-channel-user-owner cuser)))) (if (called-interactively-p 'interactive) (message "%s is %s@%s%s%s" nick login host (if full-name (format " (%s)" full-name) "") ! (if (or voice halfop op admin owner) (format " and is +%s%s on %s" (if voice "v" "") + (if halfop "h" "") + (if op "o" "") + (if admin "a" "") + (if owner "q" "") (erc-default-target)) "")) ! user))) (defun erc-away-time () "Return non-nil if the current ERC process is set away.