Merge branch 'emacs-29' of git.savannah.gnu.org:/srv/git/emacs into emacs-29

This commit is contained in:
Eli Zaretskii 2022-11-29 13:55:31 +02:00
commit 067c65578e
9 changed files with 272 additions and 93 deletions

View file

@ -392,10 +392,14 @@ modules are loaded.
There is a spiffy customize interface, which may be reached by typing There is a spiffy customize interface, which may be reached by typing
@kbd{M-x customize-option @key{RET} erc-modules @key{RET}}. @kbd{M-x customize-option @key{RET} erc-modules @key{RET}}.
When removing a module outside of the Custom ecosystem, you may wish When removing a module outside of the Custom ecosystem, you may wish
to ensure it's disabled by invoking its associated minor-mode toggle, to ensure it's disabled by invoking its associated minor-mode toggle
such as @kbd{M-x erc-spelling-mode @key{RET}}. Note that, these days, with a nonpositive prefix argument, for example, @kbd{C-u - M-x
calling @code{erc-update-modules} in an init file is typically erc-spelling-mode @key{RET}}. Additionally, if you plan on loading
unnecessary. third-party modules that perform atypical setup on activation, you may
need to arrange for calling @code{erc-update-modules} in your init
file. Examples of such setup might include registering an
@code{erc-before-connect} hook, advising @code{erc-open}, and
modifying @code{erc-modules} itself.
The following is a list of available modules. The following is a list of available modules.
@ -1051,17 +1055,10 @@ borrowing that parameter for its own uses, thus allowing you to call
@code{erc-tls} with @code{:password} set to your NickServ password. @code{erc-tls} with @code{:password} set to your NickServ password.
You can also set this to a nonemtpy string, and ERC will send that You can also set this to a nonemtpy string, and ERC will send that
when needed, no questions asked. If you instead give a non-@code{nil} when needed, no questions asked. Or, if you'd rather use auth-source,
symbol (other than @code{:password}), like @samp{Libera.Chat}, ERC set @code{erc-sasl-auth-source-function} to a function, and ERC will
will use it for the @code{:host} field in an auth-source query. perform an auth-source query instead. As last resort in all cases,
Actually, the same goes for when this option is @code{nil} but an ERC will prompt you for input.
explicit session ID is already on file (@pxref{Network Identifier}).
For all such queries, ERC specifies the resolved value of
@code{erc-sasl-user} for the @code{:user} (@code{:login}) param. Keep
in mind that none of this matters unless
@code{erc-sasl-auth-source-function} holds a function, and it's
@code{nil} by default. As a last resort, ERC will prompt you for
input.
Lastly, if your mechanism is @code{ecdsa-nist256p-challenge}, this Lastly, if your mechanism is @code{ecdsa-nist256p-challenge}, this
option should instead hold the file name of your key. option should instead hold the file name of your key.
@ -1071,7 +1068,23 @@ option should instead hold the file name of your key.
This is nearly identical to the other ERC @samp{auth-source} function This is nearly identical to the other ERC @samp{auth-source} function
options (@pxref{ERC auth-source functions}) except that the default options (@pxref{ERC auth-source functions}) except that the default
value here is @code{nil}, meaning you have to set it to something like value here is @code{nil}, meaning you have to set it to something like
@code{erc-auth-source-search} for queries to be performed. @code{erc-auth-source-search} for queries to be performed. For
convenience, this module provides the following as a possible value:
@defun erc-sasl-auth-source-password-as-host &rest plist
Setting @code{erc-sasl-auth-source-function} to this function tells
ERC to use @code{erc-sasl-password} for the @code{:host} field when
querying auth-source, even if its value is the default
@code{:password}, in which case ERC knows to ``resolve'' it to
@code{erc-session-password} and use that as long as it's
non-@code{nil}. Otherwise, ERC just defers to
@code{erc-auth-source-search} to determine the @code{:host}, along
with everything else.
@end defun
As long as this option specifies a function, ERC will pass it the
``resolved'' value of @code{erc-sasl-user} for the auth-source
@code{:user} param.
@end defopt @end defopt
@defopt erc-sasl-authzid @defopt erc-sasl-authzid
@ -1082,6 +1095,78 @@ such a thing, please contact your network operator. Otherwise, just
leave this set to @code{nil}. leave this set to @code{nil}.
@end defopt @end defopt
@subheading Examples
@itemize @bullet
@item
Defaults
@lisp
(erc-tls :server "irc.libera.chat" :port 6697
:nick "aph"
:user "APHacker"
:password "changeme")
@end lisp
Here, after adding @code{sasl} to @code{erc-modules} via the Customize
interface, you authenticate to Libera.Chat using the @samp{PLAIN}
mechanism and your NickServ credentials, @samp{APHacker} and
@samp{changeme}.
@item
External
@lisp
(setopt erc-sasl-mechanism 'external)
(erc-tls :server "irc.libera.chat" :port 6697 :nick "aph"
:client-certificate
'("/home/aph/my.key" "/home/aph/my.crt"))
@end lisp
You decide to switch things up and try out the @samp{EXTERNAL}
mechanism. You follow your network's instructions for telling
NickServ about your client-certificate's fingerprint, and you
authenticate successfully.
@item
Multiple networks
@example
# ~/.authinfo.gpg
machine irc.libera.chat key /home/aph/my.key cert /home/aph/my.crt
machine Example.Net login alyssa password sEcReT
machine Example.Net login aph-bot password sesame
@end example
@lisp
;; init.el
(defun my-erc-up (network)
(interactive "Snetwork: ")
(pcase network
('libera
(let ((erc-sasl-mechanism 'external))
(erc-tls :server "irc.libera.chat" :port 6697
:client-certificate t)))
('example
(let ((erc-sasl-auth-source-function
#'erc-sasl-auth-source-password-as-host))
(erc-tls :server "irc.example.net" :port 6697
:user "alyssa"
:password "Example.Net")))))
@end lisp
You've started storing your credentials with auth-source and have
decided to try SASL on another network as well. But there's a catch:
this network doesn't support @samp{EXTERNAL}. You use
@code{let}-binding to get around this and successfully authenticate to
both networks.
@end itemize
@subheading Troubleshooting @subheading Troubleshooting
@strong{Warning:} ERC's SASL offering is currently limited by a lack @strong{Warning:} ERC's SASL offering is currently limited by a lack

View file

@ -2926,7 +2926,7 @@ based on data provided by language servers using the Language Server
Protocol (LSP). Protocol (LSP).
+++ +++
** New commands 'image-crop' and 'image-cut. ** New commands 'image-crop' and 'image-cut'.
These commands allow interactively cropping/cutting the image at These commands allow interactively cropping/cutting the image at
point. The commands are bound to keys 'i c' and 'i x' (respectively) point. The commands are bound to keys 'i c' and 'i x' (respectively)
in the local keymap over images. They rely on external programs, by in the local keymap over images. They rely on external programs, by

View file

@ -71,9 +71,11 @@ be_perror (status_t code, char *arg)
} }
} }
else else
{ abort ();
abort ();
} fprintf (stderr, "Setting resources failed on the `src/Emacs' binary.\n"
"This may result in the installed `Emacs' binary not launching\n"
" from the tracker, but is inconsequential during packaging.\n");
} }
int int
@ -111,19 +113,19 @@ main (int argc, char **argv)
if (code != B_OK) if (code != B_OK)
{ {
be_perror (code, argv[2]); be_perror (code, argv[2]);
return EXIT_FAILURE; return 0;
} }
code = info.SetTo (&file); code = info.SetTo (&file);
if (code != B_OK) if (code != B_OK)
{ {
be_perror (code, argv[2]); be_perror (code, argv[2]);
return EXIT_FAILURE; return 0;
} }
code = info.SetAppFlags (B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY); code = info.SetAppFlags (B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY);
if (code != B_OK) if (code != B_OK)
{ {
be_perror (code, argv[2]); be_perror (code, argv[2]);
return EXIT_FAILURE; return 0;
} }
icon = BTranslationUtils::GetBitmapFile (argv[1], NULL); icon = BTranslationUtils::GetBitmapFile (argv[1], NULL);

View file

@ -77,15 +77,14 @@ version is used."
(defcustom erc-sasl-password :password (defcustom erc-sasl-password :password
"Optional account password to send when authenticating. "Optional account password to send when authenticating.
When the value is a string, ERC will use it unconditionally for When `erc-sasl-auth-source-function' is a function, ERC will
most mechanisms. Likewise with `:password', except ERC will attempt an auth-source query and prompt for input if it fails.
instead use the \"session password\" on file, which often Otherwise, when the value is a nonempty string, ERC will use it
originates from the entry-point commands `erc' or `erc-tls'. unconditionally for most mechanisms. Likewise with `:password',
Otherwise, when `erc-sasl-auth-source-function' is a function, except ERC will instead use the \"session password\" on file, if
ERC will attempt an auth-source query, possibly using a non-nil any, which often originates from the entry-point commands `erc'
symbol for the suggested `:host' parameter if set as this or `erc-tls'. As with auth-source, ERC will prompt for input as
option's value or passed as an `:id' to `erc-tls'. Failing that, a fallback.
ERC will prompt for input.
Note that, with `:password', ERC will forgo sending a traditional Note that, with `:password', ERC will forgo sending a traditional
server password via the IRC \"PASS\" command. Also, when server password via the IRC \"PASS\" command. Also, when
@ -95,15 +94,18 @@ option should hold the file name of the key."
(defcustom erc-sasl-auth-source-function nil (defcustom erc-sasl-auth-source-function nil
"Function to query auth-source for an SASL password. "Function to query auth-source for an SASL password.
Called with keyword params known to `auth-source-search', which If provided, this function should expect to be called with any
includes `erc-sasl-user' for the `:user' field and number of keyword params known to `auth-source-search', even
`erc-sasl-password' for the `:host' field, when the latter option though ERC itself only specifies `:user' paired with a
is a non-nil, non-keyword symbol. In return, ERC expects a \"resolved\" `erc-sasl-user' value. When calling this function,
string to send as the SASL password, or nil, to move on to the ERC binds all options defined in this library, such as
next approach, as described in the doc string for the option `erc-sasl-password', to their values from entry-point invocation.
`erc-sasl-password'. See info node `(erc) Connecting' for In return, ERC expects a string to send as the SASL password, or
details on ERC's auth-source integration." nil, in which case, ERC will prompt the for input. See info
:type '(choice (function-item erc-auth-source-search) node `(erc) Connecting' for details on ERC's auth-source
integration."
:type '(choice (function-item erc-sasl-auth-source-password-as-host)
(function-item erc-auth-source-search)
(const nil) (const nil)
function)) function))
@ -130,19 +132,35 @@ details on ERC's auth-source integration."
(:nick (erc-downcase (erc-current-nick))) (:nick (erc-downcase (erc-current-nick)))
(v v))) (v v)))
(defun erc-sasl-auth-source-password-as-host (&rest plist)
"Call `erc-auth-source-search' with `erc-sasl-password' as `:host'.
But only do so when it's a string or a non-nil symbol, unless
that symbol is `:password', in which case, use a non-nil
`erc-session-password' instead. Otherwise, just defer to
`erc-auth-source-search' to pick a suitable `:host'. Expect
PLIST to contain keyword params known to `auth-source-search'."
(when erc-sasl-password
(when-let ((host (if (eq :password erc-sasl-password)
(and (not (functionp erc-session-password))
erc-session-password)
erc-sasl-password)))
(setq plist `(,@plist :host ,(format "%s" host)))))
(apply #'erc-auth-source-search plist))
(defun erc-sasl--read-password (prompt) (defun erc-sasl--read-password (prompt)
"Return configured option or server password. "Return configured option or server password.
PROMPT is passed to `read-passwd' if necessary." If necessary, pass PROMPT to `read-passwd'."
(if-let (if-let ((found (pcase (alist-get 'password erc-sasl--options)
((found (pcase (alist-get 'password erc-sasl--options) ((guard (alist-get 'authfn erc-sasl--options))
(:password erc-session-password) (let-alist erc-sasl--options
((and (pred stringp) v) (unless (string-empty-p v) v)) (let ((erc-sasl-user .user)
((and (guard erc-sasl-auth-source-function) (erc-sasl-password .password)
v (let host (erc-sasl-mechanism .mechanism)
(or v (erc-networks--id-given erc-networks--id)))) (erc-sasl-authzid .authzid)
(apply erc-sasl-auth-source-function (erc-sasl-auth-source-function .authfn))
:user (erc-sasl--get-user) (funcall .authfn :user (erc-sasl--get-user)))))
(and host (list :host (symbol-name host)))))))) (:password erc-session-password)
((and (pred stringp) v) (unless (string-empty-p v) v)))))
(copy-sequence (erc--unfun found)) (copy-sequence (erc--unfun found))
(read-passwd prompt))) (read-passwd prompt)))
@ -293,6 +311,7 @@ PROMPT is passed to `read-passwd' if necessary."
`((user . ,erc-sasl-user) `((user . ,erc-sasl-user)
(password . ,erc-sasl-password) (password . ,erc-sasl-password)
(mechanism . ,erc-sasl-mechanism) (mechanism . ,erc-sasl-mechanism)
(authfn . ,erc-sasl-auth-source-function)
(authzid . ,erc-sasl-authzid))))) (authzid . ,erc-sasl-authzid)))))
(defun erc-sasl--mechanism-offered-p (offered) (defun erc-sasl--mechanism-offered-p (offered)

View file

@ -743,7 +743,8 @@ compilation and evaluation time conflicts."
["operator"] @font-lock-type-face ["operator"] @font-lock-type-face
(type_parameter_constraints_clause (type_parameter_constraints_clause
target: (identifier) @font-lock-type-face) target: (identifier) @font-lock-type-face)
(type_of_expression (identifier) @font-lock-type-face)) (type_of_expression (identifier) @font-lock-type-face)
(object_creation_expression (identifier) @font-lock-type-face))
:language 'c-sharp :language 'c-sharp
:feature 'definition :feature 'definition
:override t :override t
@ -789,11 +790,20 @@ compilation and evaluation time conflicts."
(invocation_expression (invocation_expression
(member_access_expression (identifier) @font-lock-function-name-face)) (member_access_expression (identifier) @font-lock-function-name-face))
(catch_declaration
((identifier) @font-lock-type-face))
(catch_declaration
((identifier) @font-lock-type-face
(identifier) @font-lock-variable-name-face))
(variable_declaration (identifier) @font-lock-type-face) (variable_declaration (identifier) @font-lock-type-face)
(variable_declarator (identifier) @font-lock-variable-name-face) (variable_declarator (identifier) @font-lock-variable-name-face)
(parameter type: (identifier) @font-lock-type-face) (parameter type: (identifier) @font-lock-type-face)
(parameter name: (identifier) @font-lock-variable-name-face)) (parameter name: (identifier) @font-lock-variable-name-face)
(binary_expression (identifier) @font-lock-variable-name-face)
(argument (identifier) @font-lock-variable-name-face))
:language 'c-sharp :language 'c-sharp
:feature 'expression :feature 'expression
'((conditional_expression (identifier) @font-lock-variable-name-face) '((conditional_expression (identifier) @font-lock-variable-name-face)

View file

@ -150,12 +150,20 @@
(method_definition (method_definition
name: (property_identifier) @font-lock-function-name-face) name: (property_identifier) @font-lock-function-name-face)
(required_parameter (identifier) @font-lock-variable-name-face)
(optional_parameter (identifier) @font-lock-variable-name-face)
(variable_declarator (variable_declarator
name: (identifier) @font-lock-variable-name-face) name: (identifier) @font-lock-variable-name-face)
(enum_declaration (identifier) @font-lock-type-face) (enum_declaration (identifier) @font-lock-type-face)
(extends_clause value: (identifier) @font-lock-type-face)
;; extends React.Component<T>
(extends_clause value: (member_expression
object: (identifier) @font-lock-type-face
property: (property_identifier) @font-lock-type-face))
(arrow_function (arrow_function
parameter: (identifier) @font-lock-variable-name-face) parameter: (identifier) @font-lock-variable-name-face)
@ -267,9 +275,7 @@
:language 'tsx :language 'tsx
:override t :override t
:feature 'property :feature 'property
`(((property_identifier) @font-lock-property-face) `((pair value: (identifier) @font-lock-variable-name-face)
(pair value: (identifier) @font-lock-variable-name-face)
((shorthand_property_identifier) @font-lock-property-face) ((shorthand_property_identifier) @font-lock-property-face)

View file

@ -1353,10 +1353,27 @@ for determining whether point is within a selector."
:language 'css :language 'css
'((string_value) @font-lock-string-face) '((string_value) @font-lock-string-face)
:feature 'keyword
:language 'css
'(["@media"
"@import"
"@charset"
"@namespace"
"@keyframes"] @font-lock-builtin-face
["and"
"or"
"not"
"only"
"selector"] @font-lock-keyword-face)
:feature 'variable :feature 'variable
:language 'css :language 'css
'((plain_value) @font-lock-variable-name-face) '((plain_value) @font-lock-variable-name-face)
:language 'css
:feature 'operator
`(["=" "~=" "^=" "|=" "*=" "$="] @font-lock-operator-face)
:feature 'selector :feature 'selector
:language 'css :language 'css
'((class_selector) @css-selector '((class_selector) @css-selector
@ -1377,7 +1394,18 @@ for determining whether point is within a selector."
:language 'css :language 'css
'((integer_value) @font-lock-number-face '((integer_value) @font-lock-number-face
(float_value) @font-lock-number-face (float_value) @font-lock-number-face
(unit) @font-lock-constant-face) (unit) @font-lock-constant-face
(important) @font-lock-builtin-face)
:feature 'query
:language 'css
'((keyword_query) @font-lock-property-face
(feature_name) @font-lock-property-face)
:feature 'bracket
:language 'css
'((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face)
:feature 'error :feature 'error
:language 'css :language 'css
@ -1808,9 +1836,9 @@ can also be used to fill comments.
(setq-local treesit-defun-type-regexp "rule_set") (setq-local treesit-defun-type-regexp "rule_set")
(setq-local treesit-font-lock-settings css--treesit-settings) (setq-local treesit-font-lock-settings css--treesit-settings)
(setq-local treesit-font-lock-feature-list (setq-local treesit-font-lock-feature-list
'((selector comment) '((selector comment query keyword)
(property constant string) (property constant string)
(error variable function))) (error variable function operator bracket)))
;; Tree-sitter-css, for whatever reason, cannot reliably return ;; Tree-sitter-css, for whatever reason, cannot reliably return
;; the captured nodes in a given range (it instead returns the ;; the captured nodes in a given range (it instead returns the
;; nodes preceding range). Before this is fixed in ;; nodes preceding range). Before this is fixed in

View file

@ -810,7 +810,10 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
with BUF_BEGV_BYTE and BUG_ZV_BYTE. When calling this function you with BUF_BEGV_BYTE and BUG_ZV_BYTE. When calling this function you
must make sure the current buffer's size in bytes is not larger than must make sure the current buffer's size in bytes is not larger than
UINT32_MAX. Basically, always call treesit_check_buffer_size before UINT32_MAX. Basically, always call treesit_check_buffer_size before
this function. */ this function.
If buffer range changed since last parse (visible_beg/end doesn't
match buffer visible beginning/end), set need_reparse to true. */
static void static void
treesit_sync_visible_region (Lisp_Object parser) treesit_sync_visible_region (Lisp_Object parser)
{ {
@ -834,6 +837,12 @@ treesit_sync_visible_region (Lisp_Object parser)
eassert (BUF_BEGV_BYTE (buffer) <= UINT32_MAX); eassert (BUF_BEGV_BYTE (buffer) <= UINT32_MAX);
eassert (BUF_ZV_BYTE (buffer) <= UINT32_MAX); eassert (BUF_ZV_BYTE (buffer) <= UINT32_MAX);
/* If buffer restriction changed and user requests for a node (hence
this function is called), we need to reparse. */
if (visible_beg != BUF_BEGV_BYTE (buffer)
|| visible_end != BUF_ZV_BYTE (buffer))
XTS_PARSER (parser)->need_reparse = true;
/* Before we parse or set ranges, catch up with the narrowing /* Before we parse or set ranges, catch up with the narrowing
situation. We change visible_beg and visible_end to match situation. We change visible_beg and visible_end to match
BUF_BEGV_BYTE and BUF_ZV_BYTE, and inform tree-sitter of the BUF_BEGV_BYTE and BUF_ZV_BYTE, and inform tree-sitter of the
@ -879,6 +888,8 @@ treesit_sync_visible_region (Lisp_Object parser)
} }
eassert (0 <= visible_beg); eassert (0 <= visible_beg);
eassert (visible_beg <= visible_end); eassert (visible_beg <= visible_end);
eassert (visible_beg == BUF_BEGV_BYTE (buffer));
eassert (visible_end == BUF_ZV_BYTE (buffer));
XTS_PARSER (parser)->visible_beg = visible_beg; XTS_PARSER (parser)->visible_beg = visible_beg;
XTS_PARSER (parser)->visible_end = visible_end; XTS_PARSER (parser)->visible_end = visible_end;
@ -922,16 +933,19 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree,
static void static void
treesit_ensure_parsed (Lisp_Object parser) treesit_ensure_parsed (Lisp_Object parser)
{ {
struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
/* Before we parse, catch up with the narrowing situation. */
treesit_check_buffer_size (buffer);
/* This function has to run before we check for need_reparse flag,
because it might set the flag to true. */
treesit_sync_visible_region (parser);
if (!XTS_PARSER (parser)->need_reparse) if (!XTS_PARSER (parser)->need_reparse)
return; return;
TSParser *treesit_parser = XTS_PARSER (parser)->parser; TSParser *treesit_parser = XTS_PARSER (parser)->parser;
TSTree *tree = XTS_PARSER (parser)->tree; TSTree *tree = XTS_PARSER (parser)->tree;
TSInput input = XTS_PARSER (parser)->input; TSInput input = XTS_PARSER (parser)->input;
struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
/* Before we parse, catch up with the narrowing situation. */
treesit_check_buffer_size (buffer);
treesit_sync_visible_region (parser);
TSTree *new_tree = ts_parser_parse (treesit_parser, tree, input); TSTree *new_tree = ts_parser_parse (treesit_parser, tree, input);
/* This should be very rare (impossible, really): it only happens /* This should be very rare (impossible, really): it only happens

View file

@ -42,21 +42,23 @@
(erc-sasl--options '((password . :password)))) (erc-sasl--options '((password . :password))))
(should (string= (erc-sasl--read-password nil) "foo")))) (should (string= (erc-sasl--read-password nil) "foo"))))
(ert-info ("Fallback to prompt skip auth-source") (ert-info ("Prompt when no authfn and :password resolves to nil")
(should-not erc-sasl-auth-source-function) (let ((erc-session-password nil)
(let ((erc-session-password "bar") (erc-sasl--options
(erc-networks--id (erc-networks--id-create nil))) '((password . :password) (user . :user) (authfn))))
(should (string= (ert-simulate-keys "bar\r" (should (string= (ert-simulate-keys "bar\r"
(erc-sasl--read-password "?")) (erc-sasl--read-password "?"))
"bar")))) "bar"))))
(ert-info ("Prompt when auth-source fails and `erc-sasl-password' null") (ert-info ("Prompt when auth-source fails and `erc-session-password' null")
(let ((erc-sasl--options '((password))) (should-not erc-session-password)
(erc-sasl-auth-source-function #'ignore)) (let ((erc-sasl--options '((password) (authfn . ignore))))
(should (string= (ert-simulate-keys "baz\r" (should (string= (ert-simulate-keys "baz\r"
(erc-sasl--read-password "pwd:")) (erc-sasl--read-password "pwd:"))
"baz"))))) "baz")))))
;; This mainly tests `erc-sasl-auth-source-password-as-host'.
(ert-deftest erc-sasl--read-password--auth-source () (ert-deftest erc-sasl--read-password--auth-source ()
(ert-with-temp-file netrc-file (ert-with-temp-file netrc-file
:text (string-join :text (string-join
@ -70,40 +72,53 @@
(erc-session-server "irc.gnu.org") (erc-session-server "irc.gnu.org")
(erc-session-port 6697) (erc-session-port 6697)
(erc-networks--id (erc-networks--id-create nil)) (erc-networks--id (erc-networks--id-create nil))
calls
(erc-sasl-auth-source-function
(lambda (&rest r)
(push r calls)
(apply #'erc--auth-source-search r)))
erc-server-announced-name ; too early erc-server-announced-name ; too early
auth-source-do-cache) auth-source-do-cache
;;
(fn #'erc-sasl-auth-source-password-as-host)
calls)
(advice-add 'erc-auth-source-search :before
(lambda (&rest r) (push r calls))
'((name . erc-sasl--read-password--auth-source)))
(ert-info ("Symbol as password specifies machine") (ert-info ("Symbol as password specifies machine")
(let ((erc-sasl--options '((user . "bob") (password . FSF.chat))) (let ((erc-sasl--options
(erc-networks--id (make-erc-networks--id))) `((user . "bob") (password . FSF.chat) (authfn . ,fn))))
(should (string= (erc-sasl--read-password nil) "sesame")) (should (string= (erc-sasl--read-password nil) "sesame"))
(should (equal (pop calls) '(:user "bob" :host "FSF.chat"))))) (should (equal (pop calls) '(:user "bob" :host "FSF.chat")))))
(ert-info ("ID for :host and `erc-session-username' for :user") ; *1 (ert-info (":password as password resolved to machine")
(let ((erc-session-username "bob") (let ((erc-session-password "FSF.chat")
(erc-sasl--options '((user . :user) (password))) (erc-sasl--options
(erc-networks--id (erc-networks--id-create 'GNU/chat))) `((user . "bob") (password . :password) (authfn . ,fn))))
(should (string= (erc-sasl--read-password nil) "spam")) (should (string= (erc-sasl--read-password nil) "sesame"))
(should (equal (pop calls) '(:user "bob" :host "GNU/chat"))))) (should (equal (pop calls) '(:user "bob" :host "FSF.chat")))))
(ert-info ("ID for :host and current nick for :user") ; *1 (ert-info (":user resolved to `erc-session-username'") ; *1
(let ((erc-server-current-nick "bob") (let ((erc-session-username "bob")
(erc-sasl--options '((user . :nick) (password))) (erc-sasl--options `((user . :user) (password) (authfn . ,fn)))
(erc-networks--id (erc-networks--id-create 'GNU/chat))) (erc-networks--id (erc-networks--id-create 'GNU/chat)))
(should (string= (erc-sasl--read-password nil) "spam")) (should (string= (erc-sasl--read-password nil) "spam"))
(should (equal (pop calls) '(:user "bob" :host "GNU/chat"))))) (should (equal (pop calls) '(:user "bob")))))
(ert-info (":user resolved to current nick") ; *1
(let ((erc-server-current-nick "bob")
(erc-sasl--options `((user . :nick) (password) (authfn . ,fn)))
(erc-networks--id (erc-networks--id-create 'GNU/chat)))
(should (string= (erc-sasl--read-password nil) "spam"))
(should (equal (pop calls) '(:user "bob")))))
(ert-info ("Symbol as password, entry lacks user field") (ert-info ("Symbol as password, entry lacks user field")
(let ((erc-server-current-nick "fake") (let ((erc-server-current-nick "fake")
(erc-sasl--options '((user . :nick) (password . MyHost))) (erc-sasl--options
`((user . :nick) (password . MyHost) (authfn . ,fn)))
(erc-networks--id (erc-networks--id-create 'GNU/chat))) (erc-networks--id (erc-networks--id-create 'GNU/chat)))
(should (string= (erc-sasl--read-password nil) "123")) (should (string= (erc-sasl--read-password nil) "123"))
(should (equal (pop calls) '(:user "fake" :host "MyHost")))))))) (should (equal (pop calls) '(:user "fake" :host "MyHost")))))
(advice-remove 'erc-auth-source-search
'erc-sasl--read-password--auth-source))))
(ert-deftest erc-sasl-create-client--plain () (ert-deftest erc-sasl-create-client--plain ()
(let* ((erc-session-password "password123") (let* ((erc-session-password "password123")