diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index e165adbb498..a8d1dd78235 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -392,10 +392,14 @@ modules are loaded. There is a spiffy customize interface, which may be reached by typing @kbd{M-x customize-option @key{RET} erc-modules @key{RET}}. When removing a module outside of the Custom ecosystem, you may wish -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, -calling @code{erc-update-modules} in an init file is typically -unnecessary. +to ensure it's disabled by invoking its associated minor-mode toggle +with a nonpositive prefix argument, for example, @kbd{C-u - M-x +erc-spelling-mode @key{RET}}. Additionally, if you plan on loading +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. @@ -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. 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} -symbol (other than @code{:password}), like @samp{Libera.Chat}, ERC -will use it for the @code{:host} field in an auth-source query. -Actually, the same goes for when this option is @code{nil} but an -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. +when needed, no questions asked. Or, if you'd rather use auth-source, +set @code{erc-sasl-auth-source-function} to a function, and ERC will +perform an auth-source query instead. As last resort in all cases, +ERC will prompt you for input. Lastly, if your mechanism is @code{ecdsa-nist256p-challenge}, this 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 options (@pxref{ERC auth-source functions}) except that the default 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 @defopt erc-sasl-authzid @@ -1082,6 +1095,78 @@ such a thing, please contact your network operator. Otherwise, just leave this set to @code{nil}. @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 @strong{Warning:} ERC's SASL offering is currently limited by a lack diff --git a/etc/NEWS b/etc/NEWS index 85fdf005e3d..a72b9615bd9 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2926,7 +2926,7 @@ based on data provided by language servers using the Language Server 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 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 diff --git a/lib-src/be_resources.cc b/lib-src/be_resources.cc index 414f91a192d..ece573a85a6 100644 --- a/lib-src/be_resources.cc +++ b/lib-src/be_resources.cc @@ -71,9 +71,11 @@ be_perror (status_t code, char *arg) } } 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 @@ -111,19 +113,19 @@ main (int argc, char **argv) if (code != B_OK) { be_perror (code, argv[2]); - return EXIT_FAILURE; + return 0; } code = info.SetTo (&file); if (code != B_OK) { be_perror (code, argv[2]); - return EXIT_FAILURE; + return 0; } code = info.SetAppFlags (B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY); if (code != B_OK) { be_perror (code, argv[2]); - return EXIT_FAILURE; + return 0; } icon = BTranslationUtils::GetBitmapFile (argv[1], NULL); diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el index 9084d873ce4..5b2c93988af 100644 --- a/lisp/erc/erc-sasl.el +++ b/lisp/erc/erc-sasl.el @@ -77,15 +77,14 @@ version is used." (defcustom erc-sasl-password :password "Optional account password to send when authenticating. -When the value is a string, ERC will use it unconditionally for -most mechanisms. Likewise with `:password', except ERC will -instead use the \"session password\" on file, which often -originates from the entry-point commands `erc' or `erc-tls'. -Otherwise, when `erc-sasl-auth-source-function' is a function, -ERC will attempt an auth-source query, possibly using a non-nil -symbol for the suggested `:host' parameter if set as this -option's value or passed as an `:id' to `erc-tls'. Failing that, -ERC will prompt for input. +When `erc-sasl-auth-source-function' is a function, ERC will +attempt an auth-source query and prompt for input if it fails. +Otherwise, when the value is a nonempty string, ERC will use it +unconditionally for most mechanisms. Likewise with `:password', +except ERC will instead use the \"session password\" on file, if +any, which often originates from the entry-point commands `erc' +or `erc-tls'. As with auth-source, ERC will prompt for input as +a fallback. Note that, with `:password', ERC will forgo sending a traditional 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 "Function to query auth-source for an SASL password. -Called with keyword params known to `auth-source-search', which -includes `erc-sasl-user' for the `:user' field and -`erc-sasl-password' for the `:host' field, when the latter option -is a non-nil, non-keyword symbol. In return, ERC expects a -string to send as the SASL password, or nil, to move on to the -next approach, as described in the doc string for the option -`erc-sasl-password'. See info node `(erc) Connecting' for -details on ERC's auth-source integration." - :type '(choice (function-item erc-auth-source-search) +If provided, this function should expect to be called with any +number of keyword params known to `auth-source-search', even +though ERC itself only specifies `:user' paired with a +\"resolved\" `erc-sasl-user' value. When calling this function, +ERC binds all options defined in this library, such as +`erc-sasl-password', to their values from entry-point invocation. +In return, ERC expects a string to send as the SASL password, or +nil, in which case, ERC will prompt the for input. See info +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) function)) @@ -130,19 +132,35 @@ details on ERC's auth-source integration." (:nick (erc-downcase (erc-current-nick))) (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) "Return configured option or server password. -PROMPT is passed to `read-passwd' if necessary." - (if-let - ((found (pcase (alist-get 'password erc-sasl--options) - (:password erc-session-password) - ((and (pred stringp) v) (unless (string-empty-p v) v)) - ((and (guard erc-sasl-auth-source-function) - v (let host - (or v (erc-networks--id-given erc-networks--id)))) - (apply erc-sasl-auth-source-function - :user (erc-sasl--get-user) - (and host (list :host (symbol-name host)))))))) +If necessary, pass PROMPT to `read-passwd'." + (if-let ((found (pcase (alist-get 'password erc-sasl--options) + ((guard (alist-get 'authfn erc-sasl--options)) + (let-alist erc-sasl--options + (let ((erc-sasl-user .user) + (erc-sasl-password .password) + (erc-sasl-mechanism .mechanism) + (erc-sasl-authzid .authzid) + (erc-sasl-auth-source-function .authfn)) + (funcall .authfn :user (erc-sasl--get-user))))) + (:password erc-session-password) + ((and (pred stringp) v) (unless (string-empty-p v) v))))) (copy-sequence (erc--unfun found)) (read-passwd prompt))) @@ -293,6 +311,7 @@ PROMPT is passed to `read-passwd' if necessary." `((user . ,erc-sasl-user) (password . ,erc-sasl-password) (mechanism . ,erc-sasl-mechanism) + (authfn . ,erc-sasl-auth-source-function) (authzid . ,erc-sasl-authzid))))) (defun erc-sasl--mechanism-offered-p (offered) diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 6712fcc57e2..3da3079f089 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -743,7 +743,8 @@ compilation and evaluation time conflicts." ["operator"] @font-lock-type-face (type_parameter_constraints_clause 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 :feature 'definition :override t @@ -789,11 +790,20 @@ compilation and evaluation time conflicts." (invocation_expression (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_declarator (identifier) @font-lock-variable-name-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 :feature 'expression '((conditional_expression (identifier) @font-lock-variable-name-face) diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index bf483a31d34..6c926a4e3e0 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -150,12 +150,20 @@ (method_definition 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 name: (identifier) @font-lock-variable-name-face) (enum_declaration (identifier) @font-lock-type-face) + (extends_clause value: (identifier) @font-lock-type-face) + ;; extends React.Component + (extends_clause value: (member_expression + object: (identifier) @font-lock-type-face + property: (property_identifier) @font-lock-type-face)) + (arrow_function parameter: (identifier) @font-lock-variable-name-face) @@ -267,9 +275,7 @@ :language 'tsx :override t :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) diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index 734252ee66f..b82886e3974 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -1353,10 +1353,27 @@ for determining whether point is within a selector." :language 'css '((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 :language 'css '((plain_value) @font-lock-variable-name-face) + :language 'css + :feature 'operator + `(["=" "~=" "^=" "|=" "*=" "$="] @font-lock-operator-face) + :feature 'selector :language 'css '((class_selector) @css-selector @@ -1377,7 +1394,18 @@ for determining whether point is within a selector." :language 'css '((integer_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 :language 'css @@ -1808,9 +1836,9 @@ can also be used to fill comments. (setq-local treesit-defun-type-regexp "rule_set") (setq-local treesit-font-lock-settings css--treesit-settings) (setq-local treesit-font-lock-feature-list - '((selector comment) + '((selector comment query keyword) (property constant string) - (error variable function))) + (error variable function operator bracket))) ;; Tree-sitter-css, for whatever reason, cannot reliably return ;; the captured nodes in a given range (it instead returns the ;; nodes preceding range). Before this is fixed in diff --git a/src/treesit.c b/src/treesit.c index 69272b8ad88..4b150059fac 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -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 must make sure the current buffer's size in bytes is not larger than 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 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_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 situation. We change visible_beg and visible_end to match 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 (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_end = visible_end; @@ -922,16 +933,19 @@ treesit_call_after_change_functions (TSTree *old_tree, TSTree *new_tree, static void 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) return; TSParser *treesit_parser = XTS_PARSER (parser)->parser; TSTree *tree = XTS_PARSER (parser)->tree; 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); /* This should be very rare (impossible, really): it only happens diff --git a/test/lisp/erc/erc-sasl-tests.el b/test/lisp/erc/erc-sasl-tests.el index 64593ca270c..0e5ea60e5f0 100644 --- a/test/lisp/erc/erc-sasl-tests.el +++ b/test/lisp/erc/erc-sasl-tests.el @@ -42,21 +42,23 @@ (erc-sasl--options '((password . :password)))) (should (string= (erc-sasl--read-password nil) "foo")))) - (ert-info ("Fallback to prompt skip auth-source") - (should-not erc-sasl-auth-source-function) - (let ((erc-session-password "bar") - (erc-networks--id (erc-networks--id-create nil))) + (ert-info ("Prompt when no authfn and :password resolves to nil") + (let ((erc-session-password nil) + (erc-sasl--options + '((password . :password) (user . :user) (authfn)))) (should (string= (ert-simulate-keys "bar\r" (erc-sasl--read-password "?")) "bar")))) - (ert-info ("Prompt when auth-source fails and `erc-sasl-password' null") - (let ((erc-sasl--options '((password))) - (erc-sasl-auth-source-function #'ignore)) + (ert-info ("Prompt when auth-source fails and `erc-session-password' null") + (should-not erc-session-password) + (let ((erc-sasl--options '((password) (authfn . ignore)))) (should (string= (ert-simulate-keys "baz\r" (erc-sasl--read-password "pwd:")) "baz"))))) +;; This mainly tests `erc-sasl-auth-source-password-as-host'. + (ert-deftest erc-sasl--read-password--auth-source () (ert-with-temp-file netrc-file :text (string-join @@ -70,40 +72,53 @@ (erc-session-server "irc.gnu.org") (erc-session-port 6697) (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 - 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") - (let ((erc-sasl--options '((user . "bob") (password . FSF.chat))) - (erc-networks--id (make-erc-networks--id))) + (let ((erc-sasl--options + `((user . "bob") (password . FSF.chat) (authfn . ,fn)))) (should (string= (erc-sasl--read-password nil) "sesame")) (should (equal (pop calls) '(:user "bob" :host "FSF.chat"))))) - (ert-info ("ID for :host and `erc-session-username' for :user") ; *1 - (let ((erc-session-username "bob") - (erc-sasl--options '((user . :user) (password))) - (erc-networks--id (erc-networks--id-create 'GNU/chat))) - (should (string= (erc-sasl--read-password nil) "spam")) - (should (equal (pop calls) '(:user "bob" :host "GNU/chat"))))) + (ert-info (":password as password resolved to machine") + (let ((erc-session-password "FSF.chat") + (erc-sasl--options + `((user . "bob") (password . :password) (authfn . ,fn)))) + (should (string= (erc-sasl--read-password nil) "sesame")) + (should (equal (pop calls) '(:user "bob" :host "FSF.chat"))))) - (ert-info ("ID for :host and current nick for :user") ; *1 - (let ((erc-server-current-nick "bob") - (erc-sasl--options '((user . :nick) (password))) + (ert-info (":user resolved to `erc-session-username'") ; *1 + (let ((erc-session-username "bob") + (erc-sasl--options `((user . :user) (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" :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") (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))) (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 () (let* ((erc-session-password "password123")