>From 1ef37c2aeff57b5d81a6ebd64a5a0d505203d923 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Wed, 13 Jul 2022 05:50:50 -0700 Subject: [PATCH 00/10] *** NOT A PATCH *** *** BLURB HERE *** F. Jason Park (10): Teach thing-at-point to recognize bracketed IPv6 URLs Accept bracketed IPv6 hosts in ERC Default to TLS port when calling erc-tls in lisp code Add optional server param to erc-networks--determine Improve new connections in erc-handle-irc-url [POC] Make erc-once-with-server-event more nimble [POC] Support one-off JOIN handlers in ERC [POC] Use erc--join-with-callback in URL handler [POC] Demo improved ol-irc integration [POC] * etc/emacs-irc.desktop: New file. etc/emacs-irc.desktop | 13 ++ lisp/erc/erc-backend.el | 8 + lisp/erc/erc-networks.el | 9 +- lisp/erc/erc.el | 268 ++++++++++++++++++++++++---- lisp/thingatpt.el | 2 +- test/lisp/erc/erc-networks-tests.el | 17 ++ test/lisp/erc/erc-tests.el | 136 ++++++++++++++ test/lisp/thingatpt-tests.el | 1 + 8 files changed, 415 insertions(+), 39 deletions(-) create mode 100644 etc/emacs-irc.desktop Interdiff: diff --git a/etc/emacs-irc.desktop b/etc/emacs-irc.desktop index ed13e918d2..ebdcda3a07 100644 --- a/etc/emacs-irc.desktop +++ b/etc/emacs-irc.desktop @@ -5,7 +5,6 @@ Keywords=ERC;extensible;chat;IRC;client; Categories=Network;Chat;IRCClient; Comment=GNU Emacs is an extensible, customizable text editor - ERC is a powerful, modular, and extensible IRC client for Emacs # FIXME update command line and name once autoloaded -# Also check if shell-quoting %u is needed, since it likely includes a # Exec=emacs -l erc -f erc--handle-ircs-url %u Icon=emacs MimeType=x-scheme-handler/irc;x-scheme-handler/ircs; diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index bc7a7d14dc..2ead0c9ba5 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -532,12 +532,20 @@ erc-open-network-stream (let ((p (plist-put parameters :nowait t))) (apply #'open-network-stream name buffer host service p))) +(defvar erc--server-connect-dumb-ipv6-regexp + ;; Likely gives false positives and false negatives + (rx bot "[" + (group (+ (or (any xdigit digit ":.") (: "%" (+ alnum))))) + "]" eot)) + (defun erc-server-connect (server port buffer &optional client-certificate) "Perform the connection and login using the specified SERVER and PORT. We will store server variables in the buffer given by BUFFER. CLIENT-CERTIFICATE may optionally be used to specify a TLS client certificate to use for authentication when connecting over TLS (see `erc-session-client-certificate' for more details)." + (when (string-match erc--server-connect-dumb-ipv6-regexp server) + (setq server (match-string 1 server))) (let ((msg (erc-format-message 'connect ?S server ?p port)) process (args `(,(format "erc-%s-%s" server port) nil ,server ,port))) (when client-certificate diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index efa88bfff5..7137a7b401 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2364,8 +2364,11 @@ erc-select-read-args (setq user-input (read-string "IRC server: " (erc-compute-server) 'erc-server-history-list)) - - (if (string-match "\\(.*\\):\\(.*\\)\\'" user-input) + (if (and (string-match (rx (or (: (* (not "[")) ":" (* any)) + (group (+ any))) + ":" (group (+ (not (any ":]")))) eot) + user-input) + (match-string 1 user-input)) (setq port (erc-string-to-port (match-string 2 user-input)) user-input (match-string 1 user-input)) (setq port @@ -7481,10 +7484,9 @@ erc-handle-irc-url If ERC is already connected to HOST:PORT, simply /join CHANNEL. Otherwise, connect to HOST:PORT as NICK and /join CHANNEL. -Note: calling this function with NICK and/or PASSWORD is -deprecated and results in a warning. Moreover, ERC no longer -attempts to establish new connections without human intervention, -although opting in may eventually be allowed." +Note that ERC no longer attempts to establish new connections +without human intervention, although opting in may eventually be +allowed." (when (eql port 0) (setq port nil)) (let* ((net (erc-networks--determine host)) (server-buffer @@ -7503,9 +7505,6 @@ erc-handle-irc-url (= (erc-normalize-port erc-session-port) port))))))))) key deferred) - (when (or nick password) - (display-warning 'erc (concat "Calling `erc-handle-irc-url' with a nick " - "or a password argument is deprecated."))) (unless server-buffer (unless connect-fn (user-error "Existing session for %s not found." host)) @@ -7518,7 +7517,7 @@ erc-handle-irc-url ;; These aren't percent-decoded by default (when (string-prefix-p "%" channel) (setq channel (url-unhex-string channel))) - (cl-multiple-value-setq (channel key) (split-string channel "?")) + (cl-multiple-value-setq (channel key) (split-string channel "[?]")) (if deferred ;; Alternatively, we could make this a defmethod, so when ;; autojoin is loaded, it can do its own thing. Also, as @@ -7532,37 +7531,44 @@ erc-handle-irc-url (with-current-buffer server-buffer (erc--join-with-callback channel key on-join)))))) -;; XXX ERASE ME -;; -;; The final spec was simplified from the 2003 Butcher draft and -;; doesn't allow an auth@ component or trailing ,flags or &options. -;; Because of this, we shouldn't just connect and risk exposing -;; whatever's returned by `user-login-name'. +;; XXX ERASE ME (possibly use as basis for new section in info doc) ;; ;; For now, as a demo, users must require erc and do something like: ;; ;; (add-to-list 'browse-url-default-handlers -;; '("\\`ircs?://" . erc--handle-ircs-url)) +;; '("\\`irc6?s?://" . erc--handle-ircs-url)) ;; ;; Libraries that optionally depend on browse-url, like eww, etc. need ;; an extra hand as well: ;; ;; (setq eww-use-browse-url -;; (concat eww-use-browse-url "\\|\\`ircs?:")) +;; (concat eww-use-browse-url "\\|\\`irc6?s?:")) ;; ;; Those that don't use browse-url get the same handler: ;; -;; (push '("\\bircs?://[a-z.@_+0-9%=?&/#-]+" -;; 0 t erc--handle-ircs-url 0) -;; gnus-button-alist) +;; (add-to-list 'gnus-button-alist +;; '("\\birc6?s?://[][a-z0-9.,@_:+%?&/#-]+" +;; 0 t erc--handle-ircs-url 0)) ;; ;; Finally, insert something like "ircs://testnet.ergo.chat/#test" ;; where appropriate and perform a suitable action. + +;; The two variables below are contenders for exporting as user +;; options. The rationale for separate functions here instead of, +;; say, a single option granting ERC permission to connect +;; automatically is that, since ERC doesn't lacks any concept of +;; configured server profiles, it has no idea what values to give for +;; connection parameters, like nick, user, etc. +;; +;; Also, the current spec was simplified from the 2003 Butcher draft +;; and doesn't explicitly allow for an auth[:password]@ component (or +;; trailing ,flags or &options, for that matter). Regardless, even +;; when provided, we shouldn't just connect and risk exposing +;; whatever's returned by `user-login-name', right? ;; ;; https://www.iana.org/assignments/uri-schemes ;; https://datatracker.ietf.org/doc/html/draft-butcher-irc-url#section-6 -;; Contenders for exporting as user options. (defvar erc--url-irc-connect-function nil) (defvar erc--url-ircs-connect-function nil) @@ -7586,7 +7592,7 @@ erc--handle-ircs-url (require 'url-parse) (unless (url-p url) (setq url (url-generic-parse-url url))) - (let* ((ircsp (string-match "ircs" (url-type url))) + (let* ((ircsp (string-suffix-p "s" (url-type url))) (fn (or (if ircsp erc--url-ircs-connect-function erc--url-irc-connect-function) @@ -7637,6 +7643,7 @@ erc--handle-url-org-follow-ircs ;; present. The following is only for demo purposes. (defun erc--org-init () + ;; TODO also add irc6 and irc6s (possibly nonstandard) (require 'ol-irc) (org-link-set-parameters "irc" diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el index b3dca5890f..5e597df6ff 100644 --- a/lisp/thingatpt.el +++ b/lisp/thingatpt.el @@ -430,7 +430,7 @@ thing-at-point-bounds-of-url-at-point ;; Otherwise, find the bounds within which a URI may exist. The ;; method is similar to `ffap-string-at-point'. Note that URIs ;; may contain parentheses but may not contain spaces (RFC3986). - (let* ((allowed-chars "--:=&?$+@-Z_[:alpha:]~#,%;*()!'") + (let* ((allowed-chars "--:=&?$+@-Z_[:alpha:]~#,%;*()!'[]") (skip-before "^[0-9a-zA-Z]") (skip-after ":;.,!?'") (pt (point)) diff --git a/test/lisp/thingatpt-tests.el b/test/lisp/thingatpt-tests.el index b6d0b1446a..b5f4ea8cdc 100644 --- a/test/lisp/thingatpt-tests.el +++ b/test/lisp/thingatpt-tests.el @@ -44,6 +44,7 @@ thing-at-point-test-data ;; Non alphanumeric characters can be found in URIs ("ftp://example.net/~foo!;#bar=baz&goo=bob" 3 url "ftp://example.net/~foo!;#bar=baz&goo=bob") ("bzr+ssh://user@example.net:5/a%20d,5" 34 url "bzr+ssh://user@example.net:5/a%20d,5") + ("http://[::1]:8000/foo" 10 url "http://[::1]:8000/foo") ;; markup ("Url: ..." 8 url "foo://1.example.com") ("Url: ..." 30 url "foo://2.example.com") -- 2.36.1