comparison lisp/erc/erc.el @ 84387:4ee03308c9b6

Sync ERC 5.3 (devel) from upstream
author Michael Olson <mwolson@gnu.org>
date Sat, 08 Sep 2007 03:07:09 +0000
parents fc314cf5c103
children 763be5e829a7
comparison
equal deleted inserted replaced
84386:869c721b5469 84387:4ee03308c9b6
64 ;;; History: 64 ;;; History:
65 ;; 65 ;;
66 66
67 ;;; Code: 67 ;;; Code:
68 68
69 (defconst erc-version-string "Version 5.2" 69 (defconst erc-version-string "Version 5.3 (devel)"
70 "ERC version. This is used by function `erc-version'.") 70 "ERC version. This is used by function `erc-version'.")
71 71
72 (eval-when-compile (require 'cl)) 72 (eval-when-compile (require 'cl))
73 (require 'font-lock) 73 (require 'font-lock)
74 (require 'pp) 74 (require 'pp)
834 See `erc-server-flood-margin' for other flood-related parameters.") 834 See `erc-server-flood-margin' for other flood-related parameters.")
835 835
836 ;; Script parameters 836 ;; Script parameters
837 837
838 (defcustom erc-startup-file-list 838 (defcustom erc-startup-file-list
839 '("~/.emacs.d/.ercrc.el" "~/.emacs.d/.ercrc" 839 (list (concat erc-user-emacs-directory ".ercrc.el")
840 "~/.ercrc.el" "~/.ercrc" ".ercrc.el" ".ercrc") 840 (concat erc-user-emacs-directory ".ercrc")
841 "~/.ercrc.el" "~/.ercrc" ".ercrc.el" ".ercrc")
841 "List of files to try for a startup script. 842 "List of files to try for a startup script.
842 The first existent and readable one will get executed. 843 The first existent and readable one will get executed.
843 844
844 If the filename ends with `.el' it is presumed to be an Emacs Lisp 845 If the filename ends with `.el' it is presumed to be an Emacs Lisp
845 script and it gets (load)ed. Otherwise it is treated as a bunch of 846 script and it gets (load)ed. Otherwise it is treated as a bunch of
1458 ;; activation 1459 ;; activation
1459 1460
1460 (defconst erc-default-server "irc.freenode.net" 1461 (defconst erc-default-server "irc.freenode.net"
1461 "IRC server to use if it cannot be detected otherwise.") 1462 "IRC server to use if it cannot be detected otherwise.")
1462 1463
1463 (defconst erc-default-port "6667" 1464 (defconst erc-default-port 6667
1464 "IRC port to use if it cannot be detected otherwise.") 1465 "IRC port to use if it cannot be detected otherwise.")
1465 1466
1466 (defcustom erc-join-buffer 'buffer 1467 (defcustom erc-join-buffer 'buffer
1467 "Determines how to display the newly created IRC buffer. 1468 "Determines how to display the newly created IRC buffer.
1468 'window - in another window, 1469 'window - in another window,
1486 (sexp :tag "Value")))) 1487 (sexp :tag "Value"))))
1487 1488
1488 (defcustom erc-frame-dedicated-flag nil 1489 (defcustom erc-frame-dedicated-flag nil
1489 "*Non-nil means the erc frames are dedicated to that buffer. 1490 "*Non-nil means the erc frames are dedicated to that buffer.
1490 This only has effect when `erc-join-buffer' is set to `frame'." 1491 This only has effect when `erc-join-buffer' is set to `frame'."
1492 :group 'erc-buffers
1493 :type 'boolean)
1494
1495 (defcustom erc-reuse-frames t
1496 "*Determines whether new frames are always created.
1497 Non-nil means that a new frame is not created to display an ERC
1498 buffer if there is already a window displaying it. This only has
1499 effect when `erc-join-buffer' is set to `frame'."
1491 :group 'erc-buffers 1500 :group 'erc-buffers
1492 :type 'boolean) 1501 :type 'boolean)
1493 1502
1494 (defun erc-channel-p (channel) 1503 (defun erc-channel-p (channel)
1495 "Return non-nil if CHANNEL seems to be an IRC channel name." 1504 "Return non-nil if CHANNEL seems to be an IRC channel name."
1886 ((eq erc-join-buffer 'window-noselect) 1895 ((eq erc-join-buffer 'window-noselect)
1887 (display-buffer buffer)) 1896 (display-buffer buffer))
1888 ((eq erc-join-buffer 'bury) 1897 ((eq erc-join-buffer 'bury)
1889 nil) 1898 nil)
1890 ((eq erc-join-buffer 'frame) 1899 ((eq erc-join-buffer 'frame)
1891 (funcall '(lambda (frame) 1900 (when (or (not erc-reuse-frames)
1901 (not (get-buffer-window buffer t)))
1902 ((lambda (frame)
1892 (raise-frame frame) 1903 (raise-frame frame)
1893 (select-frame frame)) 1904 (select-frame frame))
1894 (make-frame (or erc-frame-alist 1905 (make-frame (or erc-frame-alist
1895 default-frame-alist))) 1906 default-frame-alist)))
1896 (switch-to-buffer buffer) 1907 (switch-to-buffer buffer)
1897 (when erc-frame-dedicated-flag 1908 (when erc-frame-dedicated-flag
1898 (set-window-dedicated-p (selected-window) t))) 1909 (set-window-dedicated-p (selected-window) t))))
1899 (t 1910 (t
1900 (if (active-minibuffer-window) 1911 (if (active-minibuffer-window)
1901 (display-buffer buffer) 1912 (display-buffer buffer)
1902 (switch-to-buffer buffer))))) 1913 (switch-to-buffer buffer)))))
1903 1914
2153 2164
2154 (defun erc-open-ssl-stream (name buffer host port) 2165 (defun erc-open-ssl-stream (name buffer host port)
2155 "Open an SSL stream to an IRC server. 2166 "Open an SSL stream to an IRC server.
2156 The process will be given the name NAME, its target buffer will be 2167 The process will be given the name NAME, its target buffer will be
2157 BUFFER. HOST and PORT specify the connection target." 2168 BUFFER. HOST and PORT specify the connection target."
2158 (when (require 'tls) 2169 (when (condition-case nil
2159 (let ((proc (open-tls-stream name buffer host port))) 2170 (require 'ssl)
2171 (error (message "You don't have ssl.el. %s"
2172 "Try using `erc-tls' instead.")
2173 nil))
2174 (let ((proc (open-ssl-stream name buffer host port)))
2160 ;; Ugly hack, but it works for now. Problem is it is 2175 ;; Ugly hack, but it works for now. Problem is it is
2161 ;; very hard to detect when ssl is established, because s_client 2176 ;; very hard to detect when ssl is established, because s_client
2162 ;; doesn't give any CONNECTIONESTABLISHED kind of message, and 2177 ;; doesn't give any CONNECTIONESTABLISHED kind of message, and
2163 ;; most IRC servers send nothing and wait for you to identify. 2178 ;; most IRC servers send nothing and wait for you to identify.
2164 ;; Disabled when switching to tls.el -- jas 2179 (sit-for 5)
2165 ;(sit-for 5)
2166 proc))) 2180 proc)))
2181
2182 (defun erc-tls (&rest r)
2183 "Interactively select TLS connection parameters and run ERC.
2184 Arguments are the same as for `erc'."
2185 (interactive (erc-select-read-args))
2186 (let ((erc-server-connect-function 'erc-open-tls-stream))
2187 (apply 'erc r)))
2188
2189 (defun erc-open-tls-stream (name buffer host port)
2190 "Open an TLS stream to an IRC server.
2191 The process will be given the name NAME, its target buffer will be
2192 BUFFER. HOST and PORT specify the connection target."
2193 (when (condition-case nil
2194 (require 'tls)
2195 (error (message "You don't have tls.el. %s"
2196 "Try using `erc-ssl' instead.")
2197 nil))
2198 (open-tls-stream name buffer host port)))
2199
2200 ;;; Displaying error messages
2201
2202 (defun erc-error (&rest args)
2203 "Pass ARGS to `format', and display the result as an error message.
2204 If `debug-on-error' is set to non-nil, then throw a real error with this
2205 message instead, to make debugging easier."
2206 (if debug-on-error
2207 (apply #'error args)
2208 (apply #'message args)
2209 (beep)))
2167 2210
2168 ;;; Debugging the protocol 2211 ;;; Debugging the protocol
2169 2212
2170 (defvar erc-debug-irc-protocol nil 2213 (defvar erc-debug-irc-protocol nil
2171 "If non-nil, log all IRC protocol traffic to the buffer \"*erc-protocol*\". 2214 "If non-nil, log all IRC protocol traffic to the buffer \"*erc-protocol*\".
2454 (let ((arglist (format "%S" (erc-function-arglist fun)))) 2497 (let ((arglist (format "%S" (erc-function-arglist fun))))
2455 (if (string-match "^(\\(.*\\))$" arglist) 2498 (if (string-match "^(\\(.*\\))$" arglist)
2456 (match-string 1 arglist) 2499 (match-string 1 arglist)
2457 arglist))) 2500 arglist)))
2458 2501
2502 (defun erc-command-no-process-p (str)
2503 "Return non-nil if STR is an ERC command that can be run when the process
2504 is not alive, nil otherwise."
2505 (let ((fun (erc-extract-command-from-line str)))
2506 (and fun
2507 (symbolp (car fun))
2508 (get (car fun) 'process-not-needed))))
2509
2459 (defun erc-command-name (cmd) 2510 (defun erc-command-name (cmd)
2460 "For CMD being the function name of a ERC command, something like 2511 "For CMD being the function name of a ERC command, something like
2461 erc-cmd-FOO, this returns a string /FOO." 2512 erc-cmd-FOO, this returns a string /FOO."
2462 (let ((command-name (symbol-name cmd))) 2513 (let ((command-name (symbol-name cmd)))
2463 (if (string-match "^erc-cmd-\\(.*\\)$" command-name) 2514 (if (string-match "^erc-cmd-\\(.*\\)$" command-name)
2563 (current-buffer)) t) 2614 (current-buffer)) t)
2564 (t nil))) 2615 (t nil)))
2565 (defalias 'erc-cmd-VAR 'erc-cmd-SET) 2616 (defalias 'erc-cmd-VAR 'erc-cmd-SET)
2566 (defalias 'erc-cmd-VARIABLE 'erc-cmd-SET) 2617 (defalias 'erc-cmd-VARIABLE 'erc-cmd-SET)
2567 (put 'erc-cmd-SET 'do-not-parse-args t) 2618 (put 'erc-cmd-SET 'do-not-parse-args t)
2619 (put 'erc-cmd-SET 'process-not-needed t)
2568 2620
2569 (defun erc-cmd-default (line) 2621 (defun erc-cmd-default (line)
2570 "Fallback command. 2622 "Fallback command.
2571 2623
2572 Commands for which no erc-cmd-xxx exists, are tunnelled through 2624 Commands for which no erc-cmd-xxx exists, are tunnelled through
2621 2673
2622 (defun erc-cmd-CLEAR () 2674 (defun erc-cmd-CLEAR ()
2623 "Clear the window content." 2675 "Clear the window content."
2624 (recenter 0) 2676 (recenter 0)
2625 t) 2677 t)
2678 (put 'erc-cmd-CLEAR 'process-not-needed t)
2626 2679
2627 (defun erc-cmd-OPS () 2680 (defun erc-cmd-OPS ()
2628 "Show the ops in the current channel." 2681 "Show the ops in the current channel."
2629 (interactive) 2682 (interactive)
2630 (let ((ops nil)) 2683 (let ((ops nil))
2654 (erc-display-message 2707 (erc-display-message
2655 nil 'notice 'active 'country ?c co ?d tld) 2708 nil 'notice 'active 'country ?c co ?d tld)
2656 (erc-display-message 2709 (erc-display-message
2657 nil 'notice 'active 'country-unknown ?d tld)) 2710 nil 'notice 'active 'country-unknown ?d tld))
2658 t)) 2711 t))
2712 (put 'erc-cmd-COUNTRY 'process-not-needed t)
2659 2713
2660 (defun erc-cmd-AWAY (line) 2714 (defun erc-cmd-AWAY (line)
2661 "Mark the user as being away, the reason being indicated by LINE. 2715 "Mark the user as being away, the reason being indicated by LINE.
2662 If no reason is given, unset away status." 2716 If no reason is given, unset away status."
2663 (when (string-match "^\\s-*\\(.*\\)$" line) 2717 (when (string-match "^\\s-*\\(.*\\)$" line)
2734 (apropos "erc-cmd-") 2788 (apropos "erc-cmd-")
2735 (message "Type C-h m to get additional information about keybindings.") 2789 (message "Type C-h m to get additional information about keybindings.")
2736 t)) 2790 t))
2737 2791
2738 (defalias 'erc-cmd-H 'erc-cmd-HELP) 2792 (defalias 'erc-cmd-H 'erc-cmd-HELP)
2793 (put 'erc-cmd-HELP 'process-not-needed t)
2739 2794
2740 (defun erc-cmd-JOIN (channel &optional key) 2795 (defun erc-cmd-JOIN (channel &optional key)
2741 "Join the channel given in CHANNEL, optionally with KEY. 2796 "Join the channel given in CHANNEL, optionally with KEY.
2742 If CHANNEL is specified as \"-invite\", join the channel to which you 2797 If CHANNEL is specified as \"-invite\", join the channel to which you
2743 were most recently invited. See also `invitation'." 2798 were most recently invited. See also `invitation'."
2971 If LINE contains upper case characters (excluding those preceded by `\'), 3026 If LINE contains upper case characters (excluding those preceded by `\'),
2972 the matching is case-sensitive." 3027 the matching is case-sensitive."
2973 (occur line) 3028 (occur line)
2974 t) 3029 t)
2975 (put 'erc-cmd-LASTLOG 'do-not-parse-args t) 3030 (put 'erc-cmd-LASTLOG 'do-not-parse-args t)
3031 (put 'erc-cmd-LASTLOG 'process-not-needed t)
2976 3032
2977 (defun erc-send-message (line &optional force) 3033 (defun erc-send-message (line &optional force)
2978 "Send LINE to the current channel or user and display it. 3034 "Send LINE to the current channel or user and display it.
2979 3035
2980 See also `erc-message' and `erc-display-line'." 3036 See also `erc-message' and `erc-display-line'."
3193 3249
3194 (defalias 'erc-cmd-BYE 'erc-cmd-QUIT) 3250 (defalias 'erc-cmd-BYE 'erc-cmd-QUIT)
3195 (defalias 'erc-cmd-EXIT 'erc-cmd-QUIT) 3251 (defalias 'erc-cmd-EXIT 'erc-cmd-QUIT)
3196 (defalias 'erc-cmd-SIGNOFF 'erc-cmd-QUIT) 3252 (defalias 'erc-cmd-SIGNOFF 'erc-cmd-QUIT)
3197 (put 'erc-cmd-QUIT 'do-not-parse-args t) 3253 (put 'erc-cmd-QUIT 'do-not-parse-args t)
3254 (put 'erc-cmd-QUIT 'process-not-needed t)
3198 3255
3199 (defun erc-cmd-GQUIT (reason) 3256 (defun erc-cmd-GQUIT (reason)
3200 "Disconnect from all servers at once with the same quit REASON." 3257 "Disconnect from all servers at once with the same quit REASON."
3201 (erc-with-all-buffers-of-server nil #'erc-open-server-buffer-p 3258 (erc-with-all-buffers-of-server nil #'erc-open-server-buffer-p
3202 (erc-cmd-QUIT reason))) 3259 (erc-cmd-QUIT reason))
3260 (when erc-kill-queries-on-quit
3261 ;; if the query buffers have not been killed within 4 seconds,
3262 ;; kill them
3263 (run-at-time
3264 4 nil
3265 (lambda ()
3266 (dolist (buffer (erc-buffer-list (lambda (buf)
3267 (not (erc-server-buffer-p buf)))))
3268 (kill-buffer buffer)))))
3269 t)
3203 3270
3204 (defalias 'erc-cmd-GQ 'erc-cmd-GQUIT) 3271 (defalias 'erc-cmd-GQ 'erc-cmd-GQUIT)
3205 (put 'erc-cmd-GQUIT 'do-not-parse-args t) 3272 (put 'erc-cmd-GQUIT 'do-not-parse-args t)
3273 (put 'erc-cmd-GQUIT 'process-not-needed t)
3206 3274
3207 (defun erc-cmd-RECONNECT () 3275 (defun erc-cmd-RECONNECT ()
3208 "Try to reconnect to the current IRC server." 3276 "Try to reconnect to the current IRC server."
3209 (let ((buffer (or (erc-server-buffer) (current-buffer))) 3277 (let ((buffer (erc-server-buffer))
3210 (process nil)) 3278 (process nil))
3211 (with-current-buffer (if (bufferp buffer) buffer (current-buffer)) 3279 (unless (buffer-live-p buffer)
3280 (setq buffer (current-buffer)))
3281 (with-current-buffer buffer
3212 (setq erc-server-quitting nil) 3282 (setq erc-server-quitting nil)
3213 (setq erc-server-reconnecting t) 3283 (setq erc-server-reconnecting t)
3214 (setq erc-server-reconnect-count 0) 3284 (setq erc-server-reconnect-count 0)
3215 (setq process (get-buffer-process (erc-server-buffer))) 3285 (setq process (get-buffer-process (erc-server-buffer)))
3216 (if process 3286 (if process
3217 (delete-process process) 3287 (delete-process process)
3218 (erc-server-reconnect)) 3288 (erc-server-reconnect))
3219 (setq erc-server-reconnecting nil))) 3289 (setq erc-server-reconnecting nil)))
3220 t) 3290 t)
3291 (put 'erc-cmd-RECONNECT 'process-not-needed t)
3221 3292
3222 (defun erc-cmd-SERVER (server) 3293 (defun erc-cmd-SERVER (server)
3223 "Connect to SERVER, leaving existing connection intact." 3294 "Connect to SERVER, leaving existing connection intact."
3224 (erc-log (format "cmd: SERVER: %s" server)) 3295 (erc-log (format "cmd: SERVER: %s" server))
3225 (condition-case nil 3296 (condition-case nil
3226 (erc :server server :nick (erc-current-nick)) 3297 (erc :server server :nick (erc-current-nick))
3227 (error 3298 (error
3228 (message "Cannot find host %s." server) 3299 (erc-error "Cannot find host %s." server)))
3229 (beep)))
3230 t) 3300 t)
3301 (put 'erc-cmd-SERVER 'process-not-needed t)
3231 3302
3232 (eval-when-compile 3303 (eval-when-compile
3233 (defvar motif-version-string) 3304 (defvar motif-version-string)
3234 (defvar gtk-version-string)) 3305 (defvar gtk-version-string))
3235 3306
4409 (if (null (gethash nick erc-channel-new-member-names)) 4480 (if (null (gethash nick erc-channel-new-member-names))
4410 (erc-remove-channel-user nick))) 4481 (erc-remove-channel-user nick)))
4411 erc-channel-users) 4482 erc-channel-users)
4412 (setq erc-channel-new-member-names nil)) 4483 (setq erc-channel-new-member-names nil))
4413 4484
4485 (defun erc-parse-prefix ()
4486 "Return an alist of valid prefix character types and their representations.
4487 Example: (operator) o => @, (voiced) v => +."
4488 (let ((str (or (cdr (assoc "PREFIX" (erc-with-server-buffer
4489 erc-server-parameters)))
4490 ;; provide a sane default
4491 "(ov)@+"))
4492 types chars)
4493 (when (string-match "^(\\([^)]+\\))\\(.+\\)$" str)
4494 (setq types (match-string 1 str)
4495 chars (match-string 2 str))
4496 (let ((len (min (length types) (length chars)))
4497 (i 0)
4498 (alist nil))
4499 (while (< i len)
4500 (setq alist (cons (cons (elt types i) (elt chars i))
4501 alist))
4502 (setq i (1+ i)))
4503 alist))))
4504
4414 (defun erc-channel-receive-names (names-string) 4505 (defun erc-channel-receive-names (names-string)
4415 "This function is for internal use only. 4506 "This function is for internal use only.
4416 4507
4417 Update `erc-channel-users' according to NAMES-STRING. 4508 Update `erc-channel-users' according to NAMES-STRING.
4418 NAMES-STRING is a string listing some of the names on the 4509 NAMES-STRING is a string listing some of the names on the
4419 channel." 4510 channel."
4420 (let (names name op voice) 4511 (let (prefix op-ch voice-ch names name op voice)
4421 ;; We need to delete "" because in XEmacs, (split-string "a ") 4512 (setq prefix (erc-parse-prefix))
4422 ;; returns ("a" ""). 4513 (setq op-ch (cdr (assq ?o prefix))
4423 (setq names (delete "" (split-string names-string))) 4514 voice-ch (cdr (assq ?v prefix)))
4424 (let ((erc-channel-members-changed-hook nil)) 4515 ;; We need to delete "" because in XEmacs, (split-string "a ")
4425 (dolist (item names) 4516 ;; returns ("a" "").
4426 (cond ((string-match "^@\\(.*\\)$" item) 4517 (setq names (delete "" (split-string names-string)))
4427 (setq name (match-string 1 item) 4518 (let ((erc-channel-members-changed-hook nil))
4428 op 'on 4519 (dolist (item names)
4429 voice 'off)) 4520 (let ((updatep t)
4430 ((string-match "^+\\(.*\\)$" item) 4521 ch)
4431 (setq name (match-string 1 item) 4522 (if (rassq (elt item 0) prefix)
4432 op 'off 4523 (cond ((= (length item) 1)
4433 voice 'on)) 4524 (setq updatep nil))
4434 (t (setq name item 4525 ((eq (elt item 0) op-ch)
4435 op 'off 4526 (setq name (substring item 1)
4436 voice 'off))) 4527 op 'on
4437 (puthash (erc-downcase name) t 4528 voice 'off))
4438 erc-channel-new-member-names) 4529 ((eq (elt item 0) voice-ch)
4439 (erc-update-current-channel-member 4530 (setq name (substring item 1)
4440 name name t op voice))) 4531 op 'off
4532 voice 'on))
4533 (t (setq name (substring item 1)
4534 op 'off
4535 voice 'off)))
4536 (setq name item
4537 op 'off
4538 voice 'off))
4539 (when updatep
4540 (puthash (erc-downcase name) t
4541 erc-channel-new-member-names)
4542 (erc-update-current-channel-member
4543 name name t op voice)))))
4441 (run-hooks 'erc-channel-members-changed-hook))) 4544 (run-hooks 'erc-channel-members-changed-hook)))
4442 4545
4443 (defcustom erc-channel-members-changed-hook nil 4546 (defcustom erc-channel-members-changed-hook nil
4444 "*This hook is called every time the variable `channel-members' changes. 4547 "*This hook is called every time the variable `channel-members' changes.
4445 The buffer where the change happened is current while this hook is called." 4548 The buffer where the change happened is current while this hook is called."
4527 (when (and op 4630 (when (and op
4528 (not (eq (erc-channel-user-op cuser) op))) 4631 (not (eq (erc-channel-user-op cuser) op)))
4529 (setq changed t) 4632 (setq changed t)
4530 (setf (erc-channel-user-op cuser) 4633 (setf (erc-channel-user-op cuser)
4531 (cond ((eq op 'on) t) 4634 (cond ((eq op 'on) t)
4532 ((eq op 'off) nil) 4635 ((eq op 'off) nil)
4533 (t op)))) 4636 (t op))))
4534 (when (and voice 4637 (when (and voice
4535 (not (eq (erc-channel-user-voice cuser) voice))) 4638 (not (eq (erc-channel-user-voice cuser) voice)))
4536 (setq changed t) 4639 (setq changed t)
4537 (setf (erc-channel-user-voice cuser) 4640 (setf (erc-channel-user-voice cuser)
4538 (cond ((eq voice 'on) t) 4641 (cond ((eq voice 'on) t)
4539 ((eq voice 'off) nil) 4642 ((eq voice 'off) nil)
4540 (t voice)))) 4643 (t voice))))
4541 (when update-message-time 4644 (when update-message-time
4542 (setf (erc-channel-user-last-message-time cuser) (current-time))) 4645 (setf (erc-channel-user-last-message-time cuser) (current-time)))
4543 (setq user-changed 4646 (setq user-changed
4544 (erc-update-user user new-nick 4647 (erc-update-user user new-nick
4545 host login full-name info))) 4648 host login full-name info)))
4557 (setf (erc-server-user-buffers user) 4660 (setf (erc-server-user-buffers user)
4558 (cons (current-buffer) 4661 (cons (current-buffer)
4559 (erc-server-user-buffers user)))) 4662 (erc-server-user-buffers user))))
4560 (setq cuser (make-erc-channel-user 4663 (setq cuser (make-erc-channel-user
4561 :op (cond ((eq op 'on) t) 4664 :op (cond ((eq op 'on) t)
4562 ((eq op 'off) nil) 4665 ((eq op 'off) nil)
4563 (t op)) 4666 (t op))
4564 :voice (cond ((eq voice 'on) t) 4667 :voice (cond ((eq voice 'on) t)
4565 ((eq voice 'off) nil) 4668 ((eq voice 'off) nil)
4566 (t voice)) 4669 (t voice))
4567 :last-message-time 4670 :last-message-time
4568 (if update-message-time (current-time)))) 4671 (if update-message-time (current-time))))
4569 (puthash (erc-downcase nick) (cons user cuser) 4672 (puthash (erc-downcase nick) (cons user cuser)
4570 erc-channel-users) 4673 erc-channel-users)
4571 (setq changed t))) 4674 (setq changed t)))
4890 (defun erc-send-current-line () 4993 (defun erc-send-current-line ()
4891 "Parse current line and send it to IRC." 4994 "Parse current line and send it to IRC."
4892 (interactive) 4995 (interactive)
4893 (save-restriction 4996 (save-restriction
4894 (widen) 4997 (widen)
4895 (cond 4998 (if (< (point) (erc-beg-of-input-line))
4896 ((< (point) (erc-beg-of-input-line)) 4999 (erc-error "Point is not in the input area")
4897 (message "Point is not in the input area")
4898 (beep))
4899 ((not (erc-server-buffer-live-p))
4900 (message "ERC: No process running")
4901 (beep))
4902 (t
4903 (erc-set-active-buffer (current-buffer))
4904 (let ((inhibit-read-only t) 5000 (let ((inhibit-read-only t)
4905 (str (erc-user-input)) 5001 (str (erc-user-input))
4906 (old-buf (current-buffer))) 5002 (old-buf (current-buffer)))
4907 5003 (if (and (not (erc-server-buffer-live-p))
4908 ;; Kill the input and the prompt 5004 (not (erc-command-no-process-p str)))
4909 (delete-region (erc-beg-of-input-line) 5005 (erc-error "ERC: No process running")
4910 (erc-end-of-input-line)) 5006 (erc-set-active-buffer (current-buffer))
4911 5007
4912 (unwind-protect 5008 ;; Kill the input and the prompt
4913 (erc-send-input str) 5009 (delete-region (erc-beg-of-input-line)
4914 ;; Fix the buffer if the command didn't kill it 5010 (erc-end-of-input-line))
4915 (when (buffer-live-p old-buf) 5011
4916 (with-current-buffer old-buf 5012 (unwind-protect
4917 (save-restriction 5013 (erc-send-input str)
4918 (widen) 5014 ;; Fix the buffer if the command didn't kill it
4919 (goto-char (point-max)) 5015 (when (buffer-live-p old-buf)
4920 (set-marker (process-mark erc-server-process) (point)) 5016 (with-current-buffer old-buf
4921 (set-marker erc-insert-marker (point)) 5017 (save-restriction
4922 (let ((buffer-modified (buffer-modified-p))) 5018 (widen)
4923 (erc-display-prompt) 5019 (goto-char (point-max))
4924 (set-buffer-modified-p buffer-modified)))))) 5020 (when (processp erc-server-process)
4925 5021 (set-marker (process-mark erc-server-process) (point)))
4926 ;; Only when last hook has been run... 5022 (set-marker erc-insert-marker (point))
4927 (run-hook-with-args 'erc-send-completed-hook str)))))) 5023 (let ((buffer-modified (buffer-modified-p)))
5024 (erc-display-prompt)
5025 (set-buffer-modified-p buffer-modified))))))
5026
5027 ;; Only when last hook has been run...
5028 (run-hook-with-args 'erc-send-completed-hook str))))))
4928 5029
4929 (defun erc-user-input () 5030 (defun erc-user-input ()
4930 "Return the input of the user in the current buffer." 5031 "Return the input of the user in the current buffer."
4931 (buffer-substring 5032 (buffer-substring
4932 erc-input-marker 5033 erc-input-marker
4983 (let ((beg (point))) 5084 (let ((beg (point)))
4984 (insert line) 5085 (insert line)
4985 (erc-put-text-property beg (point) 5086 (erc-put-text-property beg (point)
4986 'face 'erc-command-indicator-face) 5087 'face 'erc-command-indicator-face)
4987 (insert "\n")) 5088 (insert "\n"))
4988 (set-marker (process-mark erc-server-process) (point)) 5089 (when (processp erc-server-process)
5090 (set-marker (process-mark erc-server-process) (point)))
4989 (set-marker erc-insert-marker (point)) 5091 (set-marker erc-insert-marker (point))
4990 (save-excursion 5092 (save-excursion
4991 (save-restriction 5093 (save-restriction
4992 (narrow-to-region insert-position (point)) 5094 (narrow-to-region insert-position (point))
4993 (run-hooks 'erc-send-modify-hook) 5095 (run-hooks 'erc-send-modify-hook)
5002 (let ((beg (point))) 5104 (let ((beg (point)))
5003 (insert line) 5105 (insert line)
5004 (erc-put-text-property beg (point) 5106 (erc-put-text-property beg (point)
5005 'face 'erc-input-face)) 5107 'face 'erc-input-face))
5006 (insert "\n") 5108 (insert "\n")
5007 (set-marker (process-mark erc-server-process) (point)) 5109 (when (processp erc-server-process)
5110 (set-marker (process-mark erc-server-process) (point)))
5008 (set-marker erc-insert-marker (point)) 5111 (set-marker erc-insert-marker (point))
5009 (save-excursion 5112 (save-excursion
5010 (save-restriction 5113 (save-restriction
5011 (narrow-to-region insert-position (point)) 5114 (narrow-to-region insert-position (point))
5012 (run-hooks 'erc-send-modify-hook) 5115 (run-hooks 'erc-send-modify-hook)