* lisp/erc/erc.el (erc-extract-command-from-line): Redo doc string.
* test/lisp/erc/erc-tests.el (erc--parse-isupport-value): Add case for
commonly seen escaped character ?=.
(erc-extract-command-from-line): New test.
; * test/lisp/erc/resources/erc-d/resources/basic.eld: Update.
; Don't send unnegotiated multi-prefixed userhost names.
; * test/lisp/erc/resources/erc-d/resources/dynamic-barnet.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/dynamic-foonet.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/dynamic.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/eof.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/fuzzy.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/incremental.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/linger.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/no-block.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/no-match.eld: Update.
; * test/lisp/erc/resources/erc-d/resources/unexpected.eld: Update.
(when (fboundp cmd) cmd)))
(defun erc-extract-command-from-line (line)
- "Extract command and args from the input LINE.
-If no command was given, return nil. If command matches, return a
-list of the form: (command args) where both elements are strings."
+ "Extract a \"slash command\" and its args from a prompt-input LINE.
+If LINE doesn't start with a slash command, return nil. If it
+does, meaning the pattern `erc-command-regexp' matches, return a
+list of the form (COMMAND ARGS), where COMMAND is either a symbol
+for a known handler function or `erc-cmd-default' if unknown.
+When COMMAND has the symbol property `do-not-parse-args', return
+a string in place of ARGS: that is, either LINE itself, when LINE
+consists of only whitespace, or LINE stripped of any trailing
+whitespace, including a final newline. When COMMAND lacks the
+symbol property `do-not-parse-args', return a possibly empty list
+of non-whitespace tokens. Do not perform any shell-style parsing
+of quoted or escaped substrings."
(when (string-match erc-command-regexp line)
(let* ((cmd (erc-command-symbol (match-string 1 line)))
;; note: return is nil, we apply this simply for side effects
(should (equal (erc--parse-isupport-value "\\x20\\x20\\x20") '(" ")))
(should (equal (erc--parse-isupport-value "\\x5Co/") '("\\o/")))
(should (equal (erc--parse-isupport-value "\\x7F,\\x19") '("\\x7F" "\\x19")))
+ (should (equal (erc--parse-isupport-value "a\\x3Db") '("a=b")))
(should (equal (erc--parse-isupport-value "a\\x2Cb,c") '("a,b" "c"))))
(ert-deftest erc--get-isupport-entry ()
(should-not (erc--check-prompt-input-for-excess-lines "" '("a" "b")))))
(should-not erc-ask-about-multiline-input)))
+(ert-deftest erc-extract-command-from-line ()
+ ;; FIXME when next modifying `erc-command-regexp's default value,
+ ;; move the single quote in the first group's character alternative
+ ;; to the front, i.e., [A-Za-z'] -> ['A-Za-z], so we can assert
+ ;; equivalence with this more readable `rx' form.
+ (rx bol
+ "/"
+ (group (+ (in "'A-Za-z")))
+ (group (| (: (+ (syntax whitespace)) (* nonl))
+ (* (syntax whitespace))))
+ eol)
+ (erc-mode) ; for `erc-mode-syntax-table'
+
+ ;; Non-command.
+ (should-not (erc-extract-command-from-line "FAKE\n"))
+ ;; Unknown command.
+ (should (equal (erc-extract-command-from-line "/FAKE\n")
+ '(erc-cmd-default "/FAKE\n")))
+
+ (ert-info ("With `do-not-parse-args'")
+ (should (equal (erc-extract-command-from-line "/MSG\n")
+ '(erc-cmd-MSG "\n")))
+ (should (equal (erc-extract-command-from-line "/MSG \n")
+ '(erc-cmd-MSG " \n")))
+ (should (equal (erc-extract-command-from-line "/MSG \n\n")
+ '(erc-cmd-MSG " \n\n")))
+ (should (equal (erc-extract-command-from-line "/MSG foo\n")
+ '(erc-cmd-MSG " foo")))
+ (should (equal (erc-extract-command-from-line "/MSG foo\n\n")
+ '(erc-cmd-MSG " foo")))
+ (should (equal (erc-extract-command-from-line "/MSG foo\n \n")
+ '(erc-cmd-MSG " foo")))
+ (should (equal (erc-extract-command-from-line "/MSG foo\n")
+ '(erc-cmd-MSG " foo"))))
+
+ (ert-info ("Without `do-not-parse-args'")
+ (should (equal (erc-extract-command-from-line "/HELP\n")
+ '(erc-cmd-HELP nil)))
+ (should (equal (erc-extract-command-from-line "/HELP \n")
+ '(erc-cmd-HELP nil)))
+ (should (equal (erc-extract-command-from-line "/HELP foo\n")
+ '(erc-cmd-HELP ("foo"))))
+ (should (equal (erc-extract-command-from-line "/HELP foo\n")
+ '(erc-cmd-HELP ("foo"))))
+ (should (equal (erc-extract-command-from-line "/HELP foo bar\n")
+ '(erc-cmd-HELP ("foo" "bar"))))))
+
;; The point of this test is to ensure output is handled identically
;; regardless of whether a command handler is summoned.
(0 ":irc.example.org 002 tester :Your host is irc.example.org")
(0 ":irc.example.org 003 tester :This server was created just now")
(0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
;; Just to mix thing's up (force handler to schedule timer)
(0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
(0 ":irc.example.org 221 tester +Zi")
(0 ":irc.example.org 306 tester :You have been marked as being away")
(0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
(0 ":irc.example.org 366 alice #chan :End of NAMES list"))
;; Some comment (to prevent regression)
(0. ":irc.barnet.org 221 tester +Zi")
(0. ":irc.barnet.org 306 tester :You have been marked as being away")
(0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
- (0 ":irc.barnet.org 353 joe = #chan :+joe!~joe@example.com @%+mike!~mike@example.org")
+ (0 ":irc.barnet.org 353 joe = #chan :+joe @mike")
(0 ":irc.barnet.org 366 joe #chan :End of NAMES list"))
((mode 3 "MODE #chan")
(0. ":irc.foonet.org 221 tester +Zi")
(0. ":irc.foonet.org 306 tester :You have been marked as being away")
(0 ":tester!~u@awyxgybtkx7uq.irc JOIN #chan")
- (0 ":irc.foonet.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.foonet.org 353 alice = #chan :+alice @bob")
(0 ":irc.foonet.org 366 alice #chan :End of NAMES list"))
((mode 3 "MODE #chan")
(0.0 ":" dom " 002 " nick " :Your host is " dom)
(0.0 ":" dom " 003 " nick " :This server was created just now")
(0.0 ":" dom " 004 " nick " " dom " BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0.0 ":" dom " 005 " nick " MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0.0 ":" dom " 005 " nick " MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0.0 ":" dom " 251 " nick " :There are 3 users and 0 invisible on 1 server(s)")
(0.0 ":" dom " 252 " nick " 0 :IRC Operators online")
(0.0 ":" dom " 253 " nick " 0 :unregistered connections")
(0.0 ":" dom " 306 " nick " :You have been marked as being away")
(0.0 ":" nick "!~" nick "@localhost JOIN #chan")
- (0.0 ":" dom " 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0.0 ":" dom " 353 alice = #chan :+alice @bob")
(0.0 ":" dom " 366 alice #chan :End of NAMES list"))
((mode 2.2 "MODE #chan")
(0 ":irc.example.org 002 tester :Your host is irc.example.org")
(0 ":irc.example.org 003 tester :This server was created just now")
(0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
;; Just to mix thing's up (force handler to schedule timer)
(0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
(0 ":irc.example.org 221 tester +Zi")
(0 ":irc.example.org 306 tester :You have been marked as being away")
(0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
(0 ":irc.example.org 366 alice #chan :End of NAMES list"))
((mode-chan 1.2 "MODE #chan")
((~join-foo 3.2 "JOIN #foo")
(0 "@time=" now " :tester!~tester@localhost JOIN #foo")
- (0 "@time=" now " :irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 353 alice = #foo :+alice @bob")
(0 "@time=" now " :irc.example.org 366 alice #foo :End of NAMES list"))
((~join-bar 1.2 "JOIN #bar")
(0 "@time=" now " :tester!~tester@localhost JOIN #bar")
- (0 "@time=" now " :irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 "@time=" now " :irc.example.org 353 alice = #bar :+alice @bob")
(0 "@time=" now " :irc.example.org 366 alice #bar :End of NAMES list"))
((~mode-foo 3.2 "MODE #foo")
(0.0 ":irc.foo.net 002 tester :Your host is irc.foo.net")
(0.0 ":irc.foo.net 003 tester :This server was created just now")
(0.0 ":irc.foo.net 004 tester irc.foo.net BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0.0 ":irc.foo.net 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0.0 ":irc.foo.net 005 tester MODES NETWORK=FooNet NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0.0 ":irc.foo.net 251 tester :There are 3 users and 0 invisible on 1 server(s)")
(0.0 ":irc.foo.net 252 tester 0 :IRC Operators online")
(0.0 ":irc.foo.net 253 tester 0 :unregistered connections")
((join 3 "JOIN #foo")
(0 ":tester!~tester@localhost JOIN #foo")
- (0 ":irc.foo.net 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.foo.net 353 alice = #foo :+alice @bob")
(0 ":irc.foo.net 366 alice #foo :End of NAMES list"))
((mode 3 "MODE #foo")
(0 ":irc.example.org 002 tester :Your host is irc.example.org")
(0 ":irc.example.org 003 tester :This server was created just now")
(0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
;; Just to mix thing's up (force handler to schedule timer)
(0.1 ":irc.example.org 252 tester 0 :IRC Operators online")
(0 ":irc.example.org 221 tester +Zi")
(0 ":irc.example.org 306 tester :You have been marked as being away")
(0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
(0 ":irc.example.org 366 alice #chan :End of NAMES list"))
((mode-chan 2 "MODE #chan")
(0.0 ":irc.org 002 tester :Your host is irc.org")
(0.0 ":irc.org 003 tester :This server was created just now")
(0.0 ":irc.org 004 tester irc.org BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0.0 ":irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0.0 ":irc.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0.0 ":irc.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
(0.0 ":irc.org 252 tester 0 :IRC Operators online")
(0.0 ":irc.org 253 tester 0 :unregistered connections")
((join-foo 1.2 "JOIN #foo")
(0 ":tester!~tester@localhost JOIN #foo")
- (0 ":irc.example.org 353 alice = #foo :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #foo :+alice @bob")
(0 ":irc.example.org 366 alice #foo :End of NAMES list"))
;; This would time out if the mode-foo's outgoing blocked (remove minus signs to see)
((~join-bar 1.5 "JOIN #bar")
(0 ":tester!~tester@localhost JOIN #bar")
- (0 ":irc.example.org 353 alice = #bar :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #bar :+alice @bob")
(0 ":irc.example.org 366 alice #bar :End of NAMES list"))
((mode-foo 1.2 "MODE #foo")
(0 ":irc.example.org 002 tester :Your host is irc.example.org")
(0 ":irc.example.org 003 tester :This server was created just now")
(0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
(0 ":irc.example.org 252 tester 0 :IRC Operators online")
(0 ":irc.example.org 253 tester 0 :unregistered connections")
((join 1.2 "JOIN #chan")
(0 ":tester!~tester@localhost JOIN #chan")
- (0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0 ":irc.example.org 353 alice = #chan :+alice @bob")
(0 ":irc.example.org 366 alice #chan :End of NAMES list"))
((mode-chan 0.2 "MODE #chan")
(0.0 ":irc.example.org 002 tester :Your host is irc.example.org")
(0.0 ":irc.example.org 003 tester :This server was created just now")
(0.0 ":irc.example.org 004 tester irc.example.org BERios CEIRabehiklmnoqstv Iabehkloqv")
- (0.0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+"
- " :are supported by this server")
+ (0.0 ":irc.example.org 005 tester MODES NETWORK=ExampleOrg NICKLEN=32 PREFIX=(qaohv)~&@%+ :are supported by this server")
(0.0 ":irc.example.org 251 tester :There are 3 users and 0 invisible on 1 server(s)")
(0.0 ":irc.example.org 252 tester 0 :IRC Operators online")
(0.0 ":irc.example.org 253 tester 0 :unregistered connections")
(0.0 ":irc.example.org 306 tester :You have been marked as being away")
(0.0 ":tester!~tester@localhost JOIN #chan")
- (0.0 ":irc.example.org 353 alice = #chan :+alice!~alice@example.com @%+bob!~bob@example.org")
+ (0.0 ":irc.example.org 353 alice = #chan :+alice @bob")
(0.0 ":irc.example.org 366 alice #chan :End of NAMES list")
(0.1 ":bob!~bob@example.org PRIVMSG #chan :hey"))