* bug#72992: 29.4; towards xoauth2 support in Emacs @ 2024-09-02 8:34 Xiyue Deng [not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org> ` (2 more replies) 0 siblings, 3 replies; 26+ messages in thread From: Xiyue Deng @ 2024-09-02 8:34 UTC (permalink / raw) To: 72992 [-- Attachment #1: Type: text/plain, Size: 72591 bytes --] Now that bug#72358 is done, as promised, I'm posting my plugin for auth-sources that enables oauth2 handling which you can find on Gitlab[1] (also attached). As the current approach tries to override some existing handling in auth-source, I would like to gather some comments on how to properly integrate this handling, and see if there is any benefit on providing this as a separate package for older Emacs versions. In the comment section of the package I put notes on how xoauth2 is enabled as well as existing restrictions in auth-source and how it workarounds them. I'll briefly explain below. Currently, auth-source search requires that the result include `:secret' most of the time, where when using xoauth2 it is actually the access-token. Actually, auth-source has existing support for xoauth2 authentication, though it assumes that the password value actually stores the access-token. Because xoauth2 also makes use of `secret'/`password', it makes it hard to determine whether to use password-based or xoauth2-based authentication, which is why my plugin asks users to set `auth' in auth-source to determine whether to use xoauth2. Another complication from this is that auth-source search requires the entry contains a `secret' most of the time, where it does not need to be set when using xoauth2. Therefore I workaround this by temporarily disables this check and try to retrieve access-token using oauth2 and set the result as password. Given the inconveniences of reusing password for access-token, I wonder whether we can add support for a separate `:access-token' key in the auth-source entry and use that instead of password when authenticating using xoauth2. This way, we can have both password and access-token in an auth-source entry and nnimap and smtpmail can use either one. More specifically: * When performing an auth-source search, if xoauth2 related fields are set (see the list of fields in the comments of my plugin), it will retrieve access-token using oauth2. * The search should change to check for either `secret'/`password' or `access-token' is available. * For `nnimap-login' and `smtpmail-try-auth-method', pass in both password and access-token, and for xoauth2 it should use access-token instead of password. If this is an acceptable approach, I'll try to draft a patch to implement this in Emacs. Otherwise, it may still worth implement the current approach directly in Emacs so as to avoid using hack like advice. Meanwhile, I wonder whether this may be worth release as a separate package so that users of older versions can use xoauth2 as well. I'd like to make it compatible with the agreed-upon approach to minimize any incompatibilities. Thanks for reading, and any comments are appreciated. [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin In GNU Emacs 29.4 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.38, cairo version 1.16.0) of 2024-07-02, modified by Debian built on debian-hx90 System Description: Debian GNU/Linux 12 (bookworm) Configured using: 'configure --build x86_64-linux-gnu --prefix=/usr --sharedstatedir=/var/lib --libexecdir=/usr/libexec --localstatedir=/var/lib --infodir=/usr/share/info --mandir=/usr/share/man --with-libsystemd --with-pop=yes --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/29.4/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/29.4/site-lisp:/usr/share/emacs/site-lisp --with-sound=alsa --without-gconf --with-mailutils --with-native-compilation --build x86_64-linux-gnu --prefix=/usr --sharedstatedir=/var/lib --libexecdir=/usr/libexec --localstatedir=/var/lib --infodir=/usr/share/info --mandir=/usr/share/man --with-libsystemd --with-pop=yes --enable-locallisppath=/etc/emacs:/usr/local/share/emacs/29.4/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/29.4/site-lisp:/usr/share/emacs/site-lisp --with-sound=alsa --without-gconf --with-mailutils --with-native-compilation --with-cairo --with-x=yes --with-x-toolkit=gtk3 --with-toolkit-scroll-bars 'CFLAGS=-g -O2 -ffile-prefix-map=/build/emacs-UNWIcy/emacs-29.4+1=. -fstack-protector-strong -Wformat -Werror=format-security -Wall' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2' LDFLAGS=-Wl,-z,relro' Configured features: ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ JPEG JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 M17N_FLT MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP X11 XDBE XIM XINPUT2 XPM GTK3 ZLIB Important settings: value of $LANG: en_US.UTF-8 locale-coding-system: utf-8-unix Major mode: Lisp Interaction Minor modes in effect: global-git-commit-mode: t magit-auto-revert-mode: t shell-dirtrack-mode: t mu4e-modeline-mode: t windmove-mode: t rcirc-track-minor-mode: t server-mode: t subword-mode: t bug-reference-prog-mode: t whitespace-mode: t yas-minor-mode: t xclip-mode: t global-treesit-auto-mode: t treemacs-project-follow-mode: t treemacs-follow-mode: t treemacs-git-mode: t treemacs-fringe-indicator-mode: t corfu-terminal-mode: t corfu-popupinfo-mode: t corfu-echo-mode: t global-corfu-mode: t corfu-mode: t activities-tabs-mode: t activities-mode: t fido-vertical-mode: t icomplete-vertical-mode: t icomplete-mode: t fido-mode: t override-global-mode: t global-display-line-numbers-mode: t display-line-numbers-mode: t global-auto-revert-mode: t tooltip-mode: t global-eldoc-mode: t eldoc-mode: t show-paren-mode: t electric-indent-mode: t mouse-wheel-mode: t tool-bar-mode: t tab-bar-mode: t file-name-shadow-mode: t global-font-lock-mode: t font-lock-mode: t blink-cursor-mode: t column-number-mode: t line-number-mode: t transient-mark-mode: t auto-composition-mode: t auto-encryption-mode: t auto-compression-mode: t Load-path shadows: /usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-autoloads hides /usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/debian-autoloads /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-section hides /usr/share/emacs/site-lisp/elpa/magit-section-3.3.0/magit-section /usr/share/emacs/site-lisp/elpa/ace-window-0.10.0/ace-window-autoloads hides /usr/share/emacs/site-lisp/elpa-src/ace-window-0.10.0/ace-window-autoloads /usr/share/emacs/site-lisp/elpa/ace-window-0.10.0/ace-window-pkg hides /usr/share/emacs/site-lisp/elpa-src/ace-window-0.10.0/ace-window-pkg /usr/share/emacs/site-lisp/elpa/ace-window-0.10.0/ace-window hides /usr/share/emacs/site-lisp/elpa-src/ace-window-0.10.0/ace-window /usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-autoloads hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-autoloads /usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-pkg hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-pkg /usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-list hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-list /usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities /usr/share/emacs/site-lisp/elpa/activities-0.7.1/activities-tabs hides /usr/share/emacs/site-lisp/elpa-src/activities-0.7.1/activities-tabs /usr/share/emacs/site-lisp/elpa/apache-mode-2.2.0/apache-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/apache-mode-2.2.0/apache-mode-autoloads /usr/share/emacs/site-lisp/elpa/apache-mode-2.2.0/apache-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/apache-mode-2.2.0/apache-mode-pkg /usr/share/emacs/site-lisp/elpa/apache-mode-2.2.0/apache-mode hides /usr/share/emacs/site-lisp/elpa-src/apache-mode-2.2.0/apache-mode /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-info hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-info /usr/share/emacs/site-lisp/elpa/auctex-13.3/latex-flymake hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/latex-flymake /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-site hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-site /usr/share/emacs/site-lisp/elpa/auctex-13.3/texmathp hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/texmathp /usr/share/emacs/site-lisp/elpa/auctex-13.3/toolbar-x hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/toolbar-x /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-style hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-style /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-font hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-font /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-jp hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-jp /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-mik hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-mik /usr/share/emacs/site-lisp/elpa/auctex-13.3/plain-tex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/plain-tex /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-fold hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-fold /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-ispell hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-ispell /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-bar hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-bar /usr/share/emacs/site-lisp/elpa/auctex-13.3/preview-latex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/preview-latex /usr/share/emacs/site-lisp/elpa/auctex-13.3/bib-cite hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/bib-cite /usr/share/emacs/site-lisp/elpa/auctex-13.3/preview hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/preview /usr/share/emacs/site-lisp/elpa/auctex-13.3/context-nl hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/context-nl /usr/share/emacs/site-lisp/elpa/auctex-13.3/auto-loads hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auto-loads /usr/share/emacs/site-lisp/elpa/auctex-13.3/multi-prompt hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/multi-prompt /usr/share/emacs/site-lisp/elpa/auctex-13.3/context-en hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/context-en /usr/share/emacs/site-lisp/elpa/auctex-13.3/lpath hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/lpath /usr/share/emacs/site-lisp/elpa/auctex-13.3/auctex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auctex /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex /usr/share/emacs/site-lisp/elpa/auctex-13.3/auctex-autoloads hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auctex-autoloads /usr/share/emacs/site-lisp/elpa/auctex-13.3/font-latex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/font-latex /usr/share/emacs/site-lisp/elpa/auctex-13.3/auctex-pkg hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/auctex-pkg /usr/share/emacs/site-lisp/elpa/auctex-13.3/context hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/context /usr/share/emacs/site-lisp/elpa/auctex-13.3/latex hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/latex /usr/share/emacs/site-lisp/elpa/auctex-13.3/tex-wizard hides /usr/share/emacs/site-lisp/elpa-src/auctex-13.3/tex-wizard /usr/share/emacs/site-lisp/elpa/avy-0.5.0/avy hides /usr/share/emacs/site-lisp/elpa-src/avy-0.5.0/avy /usr/share/emacs/site-lisp/elpa/avy-0.5.0/avy-autoloads hides /usr/share/emacs/site-lisp/elpa-src/avy-0.5.0/avy-autoloads /usr/share/emacs/site-lisp/elpa/avy-0.5.0/avy-pkg hides /usr/share/emacs/site-lisp/elpa-src/avy-0.5.0/avy-pkg /usr/share/emacs/site-lisp/elpa/bazel-0/bazel-autoloads hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/bazel-autoloads /usr/share/emacs/site-lisp/elpa/bazel-0/bazel hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/bazel /usr/share/emacs/site-lisp/elpa/bazel-0/test hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/test /usr/share/emacs/site-lisp/elpa/bazel-0/bazel-pkg hides /usr/share/emacs/site-lisp/elpa-src/bazel-0/bazel-pkg /usr/share/emacs/site-lisp/elpa/bison-mode-0.3/bison-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/bison-mode-0.3/bison-mode-pkg /usr/share/emacs/site-lisp/elpa/bison-mode-0.3/bison-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/bison-mode-0.3/bison-mode-autoloads /usr/share/emacs/site-lisp/elpa/bison-mode-0.3/bison-mode hides /usr/share/emacs/site-lisp/elpa-src/bison-mode-0.3/bison-mode /usr/share/emacs/site-lisp/elpa/boxquote-2.3/boxquote hides /usr/share/emacs/site-lisp/elpa-src/boxquote-2.3/boxquote /usr/share/emacs/site-lisp/elpa/boxquote-2.3/boxquote-autoloads hides /usr/share/emacs/site-lisp/elpa-src/boxquote-2.3/boxquote-autoloads /usr/share/emacs/site-lisp/elpa/boxquote-2.3/boxquote-pkg hides /usr/share/emacs/site-lisp/elpa-src/boxquote-2.3/boxquote-pkg /usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup-pkg hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup-pkg /usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup /usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup-autoloads hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup-autoloads /usr/share/emacs/site-lisp/elpa/buttercup-1.26/buttercup-compat hides /usr/share/emacs/site-lisp/elpa-src/buttercup-1.26/buttercup-compat /usr/share/emacs/site-lisp/elpa/cfrs-1.6.0/cfrs-pkg hides /usr/share/emacs/site-lisp/elpa-src/cfrs-1.6.0/cfrs-pkg /usr/share/emacs/site-lisp/elpa/cfrs-1.6.0/cfrs hides /usr/share/emacs/site-lisp/elpa-src/cfrs-1.6.0/cfrs /usr/share/emacs/site-lisp/elpa/cfrs-1.6.0/cfrs-autoloads hides /usr/share/emacs/site-lisp/elpa-src/cfrs-1.6.0/cfrs-autoloads /usr/share/emacs/site-lisp/elpa/clojure-mode-5.19.0/clojure-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-5.19.0/clojure-mode-pkg /usr/share/emacs/site-lisp/elpa/clojure-mode-5.19.0/clojure-mode hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-5.19.0/clojure-mode /usr/share/emacs/site-lisp/elpa/clojure-mode-5.19.0/clojure-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-5.19.0/clojure-mode-autoloads /usr/share/emacs/site-lisp/elpa/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-pkg hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-pkg /usr/share/emacs/site-lisp/elpa/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-autoloads hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking-autoloads /usr/share/emacs/site-lisp/elpa/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking hides /usr/share/emacs/site-lisp/elpa-src/clojure-mode-extra-font-locking-3.0.0/clojure-mode-extra-font-locking /usr/share/emacs/site-lisp/elpa/cmake-mode-3.29.0/cmake-mode hides /usr/share/emacs/site-lisp/elpa-src/cmake-mode-3.29.0/cmake-mode /usr/share/emacs/site-lisp/elpa/cmake-mode-3.29.0/cmake-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/cmake-mode-3.29.0/cmake-mode-autoloads /usr/share/emacs/site-lisp/elpa/cmake-mode-3.29.0/cmake-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/cmake-mode-3.29.0/cmake-mode-pkg /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-dabbrev hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-dabbrev /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-capf hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-capf /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-yasnippet hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-yasnippet /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-ispell hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-ispell /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-etags hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-etags /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-template hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-template /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-abbrev hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-abbrev /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-files hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-files /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-css hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-css /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-tests hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-tests /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-dabbrev-code hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-dabbrev-code /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-pkg hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-pkg /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-oddmuse hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-oddmuse /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-bbdb hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-bbdb /usr/share/emacs/site-lisp/elpa/company-0.10.2/company hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-clang hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-clang /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-nxml hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-nxml /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-gtags hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-gtags /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-tempo hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-tempo /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-autoloads hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-autoloads /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-cmake hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-cmake /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-tng hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-tng /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-elisp hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-elisp /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-semantic hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-semantic /usr/share/emacs/site-lisp/elpa/company-0.10.2/company-keywords hides /usr/share/emacs/site-lisp/elpa-src/company-0.10.2/company-keywords /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-26 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-26 /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-28 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-28 /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-macs hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-macs /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-autoloads hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-autoloads /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-pkg hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-pkg /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-25 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-25 /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-30 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-30 /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-29 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-29 /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat-27 hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat-27 /usr/share/emacs/site-lisp/elpa/compat-30.0.0.0/compat hides /usr/share/emacs/site-lisp/elpa-src/compat-30.0.0.0/compat /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-quick hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-quick /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-info hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-info /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-history hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-history /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-popupinfo hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-popupinfo /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-indexed hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-indexed /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-pkg hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-pkg /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-echo hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-echo /usr/share/emacs/site-lisp/elpa/corfu-1.5/corfu-autoloads hides /usr/share/emacs/site-lisp/elpa-src/corfu-1.5/corfu-autoloads /usr/share/emacs/site-lisp/elpa/corfu-terminal-0.7/corfu-terminal-autoloads hides /usr/share/emacs/site-lisp/elpa-src/corfu-terminal-0.7/corfu-terminal-autoloads /usr/share/emacs/site-lisp/elpa/corfu-terminal-0.7/corfu-terminal-pkg hides /usr/share/emacs/site-lisp/elpa-src/corfu-terminal-0.7/corfu-terminal-pkg /usr/share/emacs/site-lisp/elpa/corfu-terminal-0.7/corfu-terminal hides /usr/share/emacs/site-lisp/elpa-src/corfu-terminal-0.7/corfu-terminal /usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode-autoloads /usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode /usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode-tests hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode-tests /usr/share/emacs/site-lisp/elpa/csv-mode-1.23/csv-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/csv-mode-1.23/csv-mode-pkg /usr/share/emacs/site-lisp/elpa/dart-mode-1.0.7/dart-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dart-mode-1.0.7/dart-mode-autoloads /usr/share/emacs/site-lisp/elpa/dart-mode-1.0.7/dart-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/dart-mode-1.0.7/dart-mode-pkg /usr/share/emacs/site-lisp/elpa/dart-mode-1.0.7/dart-mode hides /usr/share/emacs/site-lisp/elpa-src/dart-mode-1.0.7/dart-mode /usr/share/emacs/site-lisp/elpa/dash-2.19.1/dash hides /usr/share/emacs/site-lisp/elpa-src/dash-2.19.1/dash /usr/share/emacs/site-lisp/elpa/dash-2.19.1/dash-pkg hides /usr/share/emacs/site-lisp/elpa-src/dash-2.19.1/dash-pkg /usr/share/emacs/site-lisp/elpa/dash-2.19.1/dash-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dash-2.19.1/dash-autoloads /usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-el-autoloads hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-el-autoloads /usr/share/emacs/site-lisp/elpa/debian-el-37.16/apt-sources hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/apt-sources /usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-bug hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-bug /usr/share/emacs/site-lisp/elpa/debian-el-37.16/apt-utils hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/apt-utils /usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-el-pkg hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-el-pkg /usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-autoloads hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-autoloads /usr/share/emacs/site-lisp/elpa/debian-el-37.16/gnus-BTS hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/gnus-BTS /usr/share/emacs/site-lisp/elpa/debian-el-37.16/deb-view hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/deb-view /usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-el hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/debian-el /usr/share/emacs/site-lisp/elpa/debian-el-37.16/preseed hides /usr/share/emacs/site-lisp/elpa-src/debian-el-37.16/preseed /usr/share/emacs/site-lisp/elpa/debpaste-0.1.5/debpaste hides /usr/share/emacs/site-lisp/elpa-src/debpaste-0.1.5/debpaste /usr/share/emacs/site-lisp/elpa/debpaste-0.1.5/debpaste-pkg hides /usr/share/emacs/site-lisp/elpa-src/debpaste-0.1.5/debpaste-pkg /usr/share/emacs/site-lisp/elpa/debpaste-0.1.5/debpaste-autoloads hides /usr/share/emacs/site-lisp/elpa-src/debpaste-0.1.5/debpaste-autoloads /usr/share/emacs/site-lisp/elpa/devscripts-40/devscripts hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/devscripts /usr/share/emacs/site-lisp/elpa/devscripts-40/devscripts-autoloads hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/devscripts-autoloads /usr/share/emacs/site-lisp/elpa/devscripts-40/pbuilder-mode hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/pbuilder-mode /usr/share/emacs/site-lisp/elpa/devscripts-40/devscripts-pkg hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/devscripts-pkg /usr/share/emacs/site-lisp/elpa/devscripts-40/pbuilder-log-view-mode hides /usr/share/emacs/site-lisp/elpa-src/devscripts-40/pbuilder-log-view-mode /usr/share/emacs/site-lisp/elpa/dockerfile-mode-1.7/dockerfile-mode hides /usr/share/emacs/site-lisp/elpa-src/dockerfile-mode-1.7/dockerfile-mode /usr/share/emacs/site-lisp/elpa/dockerfile-mode-1.7/dockerfile-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dockerfile-mode-1.7/dockerfile-mode-autoloads /usr/share/emacs/site-lisp/elpa/dockerfile-mode-1.7/dockerfile-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/dockerfile-mode-1.7/dockerfile-mode-pkg /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-bts-control hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-bts-control /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-changelog-mode hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-changelog-mode /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-autopkgtest-control-mode hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-autopkgtest-control-mode /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/dpkg-dev-el-autoloads hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/dpkg-dev-el-autoloads /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/dpkg-dev-el-pkg hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/dpkg-dev-el-pkg /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/dpkg-dev-el hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/dpkg-dev-el /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-control-mode hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-control-mode /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/debian-copyright hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/debian-copyright /usr/share/emacs/site-lisp/elpa/dpkg-dev-el-37.16/readme-debian hides /usr/share/emacs/site-lisp/elpa-src/dpkg-dev-el-37.16/readme-debian /usr/share/emacs/site-lisp/elpa/exec-path-from-shell-2.1/exec-path-from-shell hides /usr/share/emacs/site-lisp/elpa-src/exec-path-from-shell-2.1/exec-path-from-shell /usr/share/emacs/site-lisp/elpa/exec-path-from-shell-2.1/exec-path-from-shell-autoloads hides /usr/share/emacs/site-lisp/elpa-src/exec-path-from-shell-2.1/exec-path-from-shell-autoloads /usr/share/emacs/site-lisp/elpa/exec-path-from-shell-2.1/exec-path-from-shell-pkg hides /usr/share/emacs/site-lisp/elpa-src/exec-path-from-shell-2.1/exec-path-from-shell-pkg /usr/share/emacs/site-lisp/elpa/format-all-0.6.0/format-all hides /usr/share/emacs/site-lisp/elpa-src/format-all-0.6.0/format-all /usr/share/emacs/site-lisp/elpa/format-all-0.6.0/format-all-pkg hides /usr/share/emacs/site-lisp/elpa-src/format-all-0.6.0/format-all-pkg /usr/share/emacs/site-lisp/elpa/format-all-0.6.0/format-all-autoloads hides /usr/share/emacs/site-lisp/elpa-src/format-all-0.6.0/format-all-autoloads /usr/share/emacs/site-lisp/elpa/git-commit-3.3.0/git-commit hides /usr/share/emacs/site-lisp/elpa-src/git-commit-3.3.0/git-commit /usr/share/emacs/site-lisp/elpa/git-commit-3.3.0/git-commit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/git-commit-3.3.0/git-commit-autoloads /usr/share/emacs/site-lisp/elpa/git-commit-3.3.0/git-commit-pkg hides /usr/share/emacs/site-lisp/elpa-src/git-commit-3.3.0/git-commit-pkg /usr/share/emacs/site-lisp/elpa/git-modes-1.4.2/git-modes hides /usr/share/emacs/site-lisp/elpa-src/git-modes-1.4.2/git-modes /usr/share/emacs/site-lisp/elpa/git-modes-1.4.2/git-modes-pkg hides /usr/share/emacs/site-lisp/elpa-src/git-modes-1.4.2/git-modes-pkg /usr/share/emacs/site-lisp/elpa/git-modes-1.4.2/git-modes-autoloads hides /usr/share/emacs/site-lisp/elpa-src/git-modes-1.4.2/git-modes-autoloads /usr/share/emacs/site-lisp/elpa/gitattributes-mode-1.4.2/gitattributes-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/gitattributes-mode-1.4.2/gitattributes-mode-pkg /usr/share/emacs/site-lisp/elpa/gitattributes-mode-1.4.2/gitattributes-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gitattributes-mode-1.4.2/gitattributes-mode-autoloads /usr/share/emacs/site-lisp/elpa/gitattributes-mode-1.4.2/gitattributes-mode hides /usr/share/emacs/site-lisp/elpa-src/gitattributes-mode-1.4.2/gitattributes-mode /usr/share/emacs/site-lisp/elpa/gitconfig-mode-1.4.2/gitconfig-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gitconfig-mode-1.4.2/gitconfig-mode-autoloads /usr/share/emacs/site-lisp/elpa/gitconfig-mode-1.4.2/gitconfig-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/gitconfig-mode-1.4.2/gitconfig-mode-pkg /usr/share/emacs/site-lisp/elpa/gitconfig-mode-1.4.2/gitconfig-mode hides /usr/share/emacs/site-lisp/elpa-src/gitconfig-mode-1.4.2/gitconfig-mode /usr/share/emacs/site-lisp/elpa/gitignore-mode-1.4.2/gitignore-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/gitignore-mode-1.4.2/gitignore-mode-pkg /usr/share/emacs/site-lisp/elpa/gitignore-mode-1.4.2/gitignore-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gitignore-mode-1.4.2/gitignore-mode-autoloads /usr/share/emacs/site-lisp/elpa/gitignore-mode-1.4.2/gitignore-mode hides /usr/share/emacs/site-lisp/elpa-src/gitignore-mode-1.4.2/gitignore-mode /usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot /usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-autoloads /usr/share/emacs/site-lisp/elpa/debian-el-37.16/debian-autoloads hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/debian-autoloads /usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-pkg hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-pkg /usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-context hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-context /usr/share/emacs/site-lisp/elpa/gnuplot-0.8.1/gnuplot-gui hides /usr/share/emacs/site-lisp/elpa-src/gnuplot-0.8.1/gnuplot-gui /usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-mode hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-mode /usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-guru hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-guru /usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-mode-pkg /usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-mode-autoloads /usr/share/emacs/site-lisp/elpa/go-mode-1.6.0/go-rename hides /usr/share/emacs/site-lisp/elpa-src/go-mode-1.6.0/go-rename /usr/share/emacs/site-lisp/elpa/graphviz-dot-mode-0.4.2/graphviz-dot-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/graphviz-dot-mode-0.4.2/graphviz-dot-mode-autoloads /usr/share/emacs/site-lisp/elpa/graphviz-dot-mode-0.4.2/graphviz-dot-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/graphviz-dot-mode-0.4.2/graphviz-dot-mode-pkg /usr/share/emacs/site-lisp/elpa/graphviz-dot-mode-0.4.2/graphviz-dot-mode hides /usr/share/emacs/site-lisp/elpa-src/graphviz-dot-mode-0.4.2/graphviz-dot-mode /usr/share/emacs/site-lisp/elpa/ht-2.3/ht-pkg hides /usr/share/emacs/site-lisp/elpa-src/ht-2.3/ht-pkg /usr/share/emacs/site-lisp/elpa/ht-2.3/ht-autoloads hides /usr/share/emacs/site-lisp/elpa-src/ht-2.3/ht-autoloads /usr/share/emacs/site-lisp/elpa/ht-2.3/ht hides /usr/share/emacs/site-lisp/elpa-src/ht-2.3/ht /usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-ox hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-ox /usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-autoloads hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-autoloads /usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-pkg hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-pkg /usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra-examples hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra-examples /usr/share/emacs/site-lisp/elpa/hydra-0.15.0/hydra hides /usr/share/emacs/site-lisp/elpa-src/hydra-0.15.0/hydra /usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv /usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv-autoloads hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv-autoloads /usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv-pkg hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv-pkg /usr/share/emacs/site-lisp/elpa/inheritenv-0.2/inheritenv-tests hides /usr/share/emacs/site-lisp/elpa-src/inheritenv-0.2/inheritenv-tests /usr/share/emacs/site-lisp/elpa/language-id-0.20/language-id hides /usr/share/emacs/site-lisp/elpa-src/language-id-0.20/language-id /usr/share/emacs/site-lisp/elpa/language-id-0.20/language-id-pkg hides /usr/share/emacs/site-lisp/elpa-src/language-id-0.20/language-id-pkg /usr/share/emacs/site-lisp/elpa/language-id-0.20/language-id-autoloads hides /usr/share/emacs/site-lisp/elpa-src/language-id-0.20/language-id-autoloads /usr/share/emacs/site-lisp/elpa/lintian-0.1/lintian-pkg hides /usr/share/emacs/site-lisp/elpa-src/lintian-0.1/lintian-pkg /usr/share/emacs/site-lisp/elpa/lintian-0.1/lintian-autoloads hides /usr/share/emacs/site-lisp/elpa-src/lintian-0.1/lintian-autoloads /usr/share/emacs/site-lisp/elpa/lintian-0.1/lintian hides /usr/share/emacs/site-lisp/elpa-src/lintian-0.1/lintian /usr/share/emacs/site-lisp/elpa/lua-mode-20221027/lua-mode hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/lua-mode /usr/share/emacs/site-lisp/elpa/lua-mode-20221027/lua-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/lua-mode-autoloads /usr/share/emacs/site-lisp/elpa/lua-mode-20221027/init-tryout hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/init-tryout /usr/share/emacs/site-lisp/elpa/lua-mode-20221027/lua-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/lua-mode-20221027/lua-mode-pkg /usr/share/emacs/site-lisp/elpa/lv-0.15.0/lv-autoloads hides /usr/share/emacs/site-lisp/elpa-src/lv-0.15.0/lv-autoloads /usr/share/emacs/site-lisp/elpa/lv-0.15.0/lv hides /usr/share/emacs/site-lisp/elpa-src/lv-0.15.0/lv /usr/share/emacs/site-lisp/elpa/lv-0.15.0/lv-pkg hides /usr/share/emacs/site-lisp/elpa-src/lv-0.15.0/lv-pkg /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-remote hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-remote /usr/share/emacs/site-lisp/elpa/magit-3.3.0/git-rebase hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/git-rebase /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-bisect hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-bisect /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-margin hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-margin /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-merge hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-merge /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-section hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-section /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-patch hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-patch /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-commit hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-commit /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-autoloads /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-files hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-files /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-stash hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-stash /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-bookmark hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-bookmark /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-submodule hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-submodule /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-apply hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-apply /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-repos hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-repos /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-core hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-core /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-subtree hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-subtree /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-autorevert hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-autorevert /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-gitignore hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-gitignore /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-transient hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-transient /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-extras hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-extras /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-git hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-git /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-notes hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-notes /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-reflog hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-reflog /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-mode hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-mode /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-push hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-push /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-tag hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-tag /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-process hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-process /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-ediff hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-ediff /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-imenu hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-imenu /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-diff hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-diff /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-clone hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-clone /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-log hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-log /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-utils hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-utils /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-wip hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-wip /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-branch hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-branch /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-pull hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-pull /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-reset hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-reset /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-sequence hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-sequence /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-status hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-status /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-refs hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-refs /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-obsolete hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-obsolete /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-fetch hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-fetch /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-worktree hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-worktree /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-blame hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-blame /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-pkg hides /usr/share/emacs/site-lisp/elpa-src/magit-3.3.0/magit-pkg /usr/share/emacs/site-lisp/elpa/magit-section-3.3.0/magit-section-autoloads hides /usr/share/emacs/site-lisp/elpa-src/magit-section-3.3.0/magit-section-autoloads /usr/share/emacs/site-lisp/elpa/magit-3.3.0/magit-section hides /usr/share/emacs/site-lisp/elpa-src/magit-section-3.3.0/magit-section /usr/share/emacs/site-lisp/elpa/magit-section-3.3.0/magit-section-pkg hides /usr/share/emacs/site-lisp/elpa-src/magit-section-3.3.0/magit-section-pkg /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-cgen hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-cgen /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-scan hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-scan /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-publish hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-publish /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-complete hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-complete /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-syntax hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-syntax /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/tlc hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/tlc /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-netshell hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-netshell /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/semantic-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/semantic-matlab /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/mlint hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/mlint /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/company-matlab-shell hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/company-matlab-shell /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-shell-gud hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-shell-gud /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/mlgud hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/mlgud /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/srecode-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/srecode-matlab /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-compat hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-compat /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-mode-pkg /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-maint hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-maint /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/cedet-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/cedet-matlab /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-topic hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-topic /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/linemark hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/linemark /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-shell hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-shell /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/semanticdb-matlab hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/semanticdb-matlab /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-load hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-load /usr/share/emacs/site-lisp/elpa/matlab-mode-4.0/matlab-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/matlab-mode-4.0/matlab-mode-autoloads /usr/share/emacs/site-lisp/elpa/meson-mode-0.2/meson-mode hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/meson-mode /usr/share/emacs/site-lisp/elpa/meson-mode-0.2/utils hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/utils /usr/share/emacs/site-lisp/elpa/meson-mode-0.2/meson-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/meson-mode-autoloads /usr/share/emacs/site-lisp/elpa/meson-mode-0.2/meson-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/meson-mode-0.2/meson-mode-pkg /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-draft hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-draft /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-modeline hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-modeline /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-view hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-view /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-message hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-message /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-helpers hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-helpers /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-pkg hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-pkg /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-bookmarks hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-bookmarks /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-thread hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-thread /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-mime-parts hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-mime-parts /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-server hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-server /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-query-items hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-query-items /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-contrib hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-contrib /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-window hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-window /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-config hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-config /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-autoloads hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-autoloads /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-icalendar hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-icalendar /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-mark hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-mark /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-headers hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-headers /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-org hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-org /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-contacts hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-contacts /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-speedbar hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-speedbar /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-obsolete hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-obsolete /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-vars hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-vars /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-actions hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-actions /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-main hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-main /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-search hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-search /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-notification hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-notification /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-context hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-context /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-compose hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-compose /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-lists hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-lists /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-folders hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-folders /usr/share/emacs/site-lisp/elpa/mu4e-1.12.6/mu4e-update hides /usr/share/emacs/site-lisp/elpa-src/mu4e-1.12.6/mu4e-update /usr/share/emacs/site-lisp/elpa/nginx-mode-1.1.9/nginx-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/nginx-mode-1.1.9/nginx-mode-autoloads /usr/share/emacs/site-lisp/elpa/nginx-mode-1.1.9/nginx-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/nginx-mode-1.1.9/nginx-mode-pkg /usr/share/emacs/site-lisp/elpa/nginx-mode-1.1.9/nginx-mode hides /usr/share/emacs/site-lisp/elpa-src/nginx-mode-1.1.9/nginx-mode /usr/share/emacs/site-lisp/elpa/paredit-26/paredit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/paredit-26/paredit-autoloads /usr/share/emacs/site-lisp/elpa/paredit-26/paredit-pkg hides /usr/share/emacs/site-lisp/elpa-src/paredit-26/paredit-pkg /usr/share/emacs/site-lisp/elpa/paredit-26/paredit hides /usr/share/emacs/site-lisp/elpa-src/paredit-26/paredit /usr/share/emacs/site-lisp/elpa/persist-0.6.1/persist hides /usr/share/emacs/site-lisp/elpa-src/persist-0.6.1/persist /usr/share/emacs/site-lisp/elpa/persist-0.6.1/persist-pkg hides /usr/share/emacs/site-lisp/elpa-src/persist-0.6.1/persist-pkg /usr/share/emacs/site-lisp/elpa/persist-0.6.1/persist-autoloads hides /usr/share/emacs/site-lisp/elpa-src/persist-0.6.1/persist-autoloads /usr/share/emacs/site-lisp/elpa/pfuture-1.9/pfuture hides /usr/share/emacs/site-lisp/elpa-src/pfuture-1.9/pfuture /usr/share/emacs/site-lisp/elpa/pfuture-1.9/pfuture-autoloads hides /usr/share/emacs/site-lisp/elpa-src/pfuture-1.9/pfuture-autoloads /usr/share/emacs/site-lisp/elpa/pfuture-1.9/pfuture-pkg hides /usr/share/emacs/site-lisp/elpa-src/pfuture-1.9/pfuture-pkg /usr/share/emacs/site-lisp/elpa/po-mode-0.21/po-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/po-mode-0.21/po-mode-pkg /usr/share/emacs/site-lisp/elpa/po-mode-0.21/po-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/po-mode-0.21/po-mode-autoloads /usr/share/emacs/site-lisp/elpa/po-mode-0.21/po-mode hides /usr/share/emacs/site-lisp/elpa-src/po-mode-0.21/po-mode /usr/share/emacs/site-lisp/elpa/popon-0.13/popon hides /usr/share/emacs/site-lisp/elpa-src/popon-0.13/popon /usr/share/emacs/site-lisp/elpa/popon-0.13/popon-autoloads hides /usr/share/emacs/site-lisp/elpa-src/popon-0.13/popon-autoloads /usr/share/emacs/site-lisp/elpa/popon-0.13/popon-pkg hides /usr/share/emacs/site-lisp/elpa-src/popon-0.13/popon-pkg /usr/share/emacs/site-lisp/elpa/posframe-1.1.7/posframe-pkg hides /usr/share/emacs/site-lisp/elpa-src/posframe-1.1.7/posframe-pkg /usr/share/emacs/site-lisp/elpa/posframe-1.1.7/posframe-autoloads hides /usr/share/emacs/site-lisp/elpa-src/posframe-1.1.7/posframe-autoloads /usr/share/emacs/site-lisp/elpa/posframe-1.1.7/posframe hides /usr/share/emacs/site-lisp/elpa-src/posframe-1.1.7/posframe /usr/share/emacs/site-lisp/elpa/projectile-2.8.0/projectile-pkg hides /usr/share/emacs/site-lisp/elpa-src/projectile-2.8.0/projectile-pkg /usr/share/emacs/site-lisp/elpa/projectile-2.8.0/projectile-autoloads hides /usr/share/emacs/site-lisp/elpa-src/projectile-2.8.0/projectile-autoloads /usr/share/emacs/site-lisp/elpa/projectile-2.8.0/projectile hides /usr/share/emacs/site-lisp/elpa-src/projectile-2.8.0/projectile /usr/share/emacs/site-lisp/elpa/py-isort-2016.1/py-isort hides /usr/share/emacs/site-lisp/elpa-src/py-isort-2016.1/py-isort /usr/share/emacs/site-lisp/elpa/py-isort-2016.1/py-isort-autoloads hides /usr/share/emacs/site-lisp/elpa-src/py-isort-2016.1/py-isort-autoloads /usr/share/emacs/site-lisp/elpa/py-isort-2016.1/py-isort-pkg hides /usr/share/emacs/site-lisp/elpa-src/py-isort-2016.1/py-isort-pkg /usr/share/emacs/site-lisp/elpa/pyvenv-1.21/pyvenv hides /usr/share/emacs/site-lisp/elpa-src/pyvenv-1.21/pyvenv /usr/share/emacs/site-lisp/elpa/pyvenv-1.21/pyvenv-pkg hides /usr/share/emacs/site-lisp/elpa-src/pyvenv-1.21/pyvenv-pkg /usr/share/emacs/site-lisp/elpa/pyvenv-1.21/pyvenv-autoloads hides /usr/share/emacs/site-lisp/elpa-src/pyvenv-1.21/pyvenv-autoloads /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-common hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-common /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-tests hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-tests /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-treesitter hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-treesitter /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-cargo hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-cargo /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-autoloads /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-utils hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-utils /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-rustfmt hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-rustfmt /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-playpen hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-playpen /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-prog-mode hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-prog-mode /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-mode-pkg /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-cargo-tests hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-cargo-tests /usr/share/emacs/site-lisp/elpa/rust-mode-1.0.6/rust-compile hides /usr/share/emacs/site-lisp/elpa-src/rust-mode-1.0.6/rust-compile /usr/share/emacs/site-lisp/elpa/s-1.12.0/s-autoloads hides /usr/share/emacs/site-lisp/elpa-src/s-1.12.0/s-autoloads /usr/share/emacs/site-lisp/elpa/s-1.12.0/s-pkg hides /usr/share/emacs/site-lisp/elpa-src/s-1.12.0/s-pkg /usr/share/emacs/site-lisp/elpa/s-1.12.0/s hides /usr/share/emacs/site-lisp/elpa-src/s-1.12.0/s /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-map hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-map /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-indent hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-indent /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-syntax hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-syntax /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-lib hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-lib /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-pkg /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-prettify-symbols hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-prettify-symbols /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-compile hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-compile /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-organise hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-organise /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-autoloads /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-paragraph hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-paragraph /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-imenu hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-imenu /usr/share/emacs/site-lisp/elpa/scala-mode-1.1.0/scala-mode-fontlock hides /usr/share/emacs/site-lisp/elpa-src/scala-mode-1.1.0/scala-mode-fontlock /usr/share/emacs/site-lisp/elpa/seq-2.24/seq-24 hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-24 /usr/share/emacs/site-lisp/elpa/seq-2.24/seq-autoloads hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-autoloads /usr/share/emacs/site-lisp/elpa/seq-2.24/seq hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq /usr/share/emacs/site-lisp/elpa/seq-2.24/seq-pkg hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-pkg /usr/share/emacs/site-lisp/elpa/seq-2.24/seq-25 hides /usr/share/emacs/site-lisp/elpa-src/seq-2.24/seq-25 /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-project-follow-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-project-follow-mode /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-dom hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-dom /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-follow-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-follow-mode /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-logging hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-logging /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-autoloads hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-autoloads /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-compatibility hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-compatibility /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-async hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-async /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-themes hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-themes /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-mouse-interface hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-mouse-interface /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-tag-follow-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-tag-follow-mode /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-bookmarks hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-bookmarks /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-fringe-indicator hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-fringe-indicator /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-filewatch-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-filewatch-mode /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-interface hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-interface /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-tags hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-tags /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-visuals hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-visuals /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-core-utils hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-core-utils /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-peek-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-peek-mode /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-annotations hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-annotations /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-icons hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-icons /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-persistence hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-persistence /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-diagnostics hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-diagnostics /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-scope hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-scope /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-extensions hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-extensions /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-rendering hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-rendering /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-customization hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-customization /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-file-management hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-file-management /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-faces hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-faces /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-macros hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-macros /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-git-commit-diff-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-git-commit-diff-mode /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-treelib hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-treelib /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-hydras hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-hydras /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-pkg hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-pkg /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-header-line hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-header-line /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-icons-dired hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-icons-dired /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-workspaces hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-workspaces /usr/share/emacs/site-lisp/elpa/treemacs-3.1/treemacs-mode hides /usr/share/emacs/site-lisp/elpa-src/treemacs-3.1/treemacs-mode /usr/share/emacs/site-lisp/elpa/treemacs-magit-3.1/treemacs-magit hides /usr/share/emacs/site-lisp/elpa-src/treemacs-magit-3.1/treemacs-magit /usr/share/emacs/site-lisp/elpa/treemacs-magit-3.1/treemacs-magit-pkg hides /usr/share/emacs/site-lisp/elpa-src/treemacs-magit-3.1/treemacs-magit-pkg /usr/share/emacs/site-lisp/elpa/treemacs-magit-3.1/treemacs-magit-autoloads hides /usr/share/emacs/site-lisp/elpa-src/treemacs-magit-3.1/treemacs-magit-autoloads /usr/share/emacs/site-lisp/elpa/treemacs-projectile-3.1/treemacs-projectile-pkg hides /usr/share/emacs/site-lisp/elpa-src/treemacs-projectile-3.1/treemacs-projectile-pkg /usr/share/emacs/site-lisp/elpa/treemacs-projectile-3.1/treemacs-projectile-autoloads hides /usr/share/emacs/site-lisp/elpa-src/treemacs-projectile-3.1/treemacs-projectile-autoloads /usr/share/emacs/site-lisp/elpa/treemacs-projectile-3.1/treemacs-projectile hides /usr/share/emacs/site-lisp/elpa-src/treemacs-projectile-3.1/treemacs-projectile /usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm-load-path hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm-load-path /usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm /usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm-pkg hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm-pkg /usr/share/emacs/site-lisp/elpa/vterm-0.0.2/vterm-autoloads hides /usr/share/emacs/site-lisp/elpa-src/vterm-0.0.2/vterm-autoloads /usr/share/emacs/site-lisp/elpa/web-mode-17.3.13/web-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/web-mode-17.3.13/web-mode-pkg /usr/share/emacs/site-lisp/elpa/web-mode-17.3.13/web-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/web-mode-17.3.13/web-mode-autoloads /usr/share/emacs/site-lisp/elpa/web-mode-17.3.13/web-mode hides /usr/share/emacs/site-lisp/elpa-src/web-mode-17.3.13/web-mode /usr/share/emacs/site-lisp/elpa/with-editor-3.3.2/with-editor-pkg hides /usr/share/emacs/site-lisp/elpa-src/with-editor-3.3.2/with-editor-pkg /usr/share/emacs/site-lisp/elpa/with-editor-3.3.2/with-editor-autoloads hides /usr/share/emacs/site-lisp/elpa-src/with-editor-3.3.2/with-editor-autoloads /usr/share/emacs/site-lisp/elpa/with-editor-3.3.2/with-editor hides /usr/share/emacs/site-lisp/elpa-src/with-editor-3.3.2/with-editor /usr/share/emacs/site-lisp/elpa/xml-rpc-1.6.17/xml-rpc hides /usr/share/emacs/site-lisp/elpa-src/xml-rpc-1.6.17/xml-rpc /usr/share/emacs/site-lisp/elpa/xml-rpc-1.6.17/xml-rpc-pkg hides /usr/share/emacs/site-lisp/elpa-src/xml-rpc-1.6.17/xml-rpc-pkg /usr/share/emacs/site-lisp/elpa/xml-rpc-1.6.17/xml-rpc-autoloads hides /usr/share/emacs/site-lisp/elpa-src/xml-rpc-1.6.17/xml-rpc-autoloads /usr/share/emacs/site-lisp/elpa/yaml-mode-0.0.16/yaml-mode-pkg hides /usr/share/emacs/site-lisp/elpa-src/yaml-mode-0.0.16/yaml-mode-pkg /usr/share/emacs/site-lisp/elpa/yaml-mode-0.0.16/yaml-mode hides /usr/share/emacs/site-lisp/elpa-src/yaml-mode-0.0.16/yaml-mode /usr/share/emacs/site-lisp/elpa/yaml-mode-0.0.16/yaml-mode-autoloads hides /usr/share/emacs/site-lisp/elpa-src/yaml-mode-0.0.16/yaml-mode-autoloads /usr/share/emacs/site-lisp/elpa/yasnippet-0.14.1/yasnippet-autoloads hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-0.14.1/yasnippet-autoloads /usr/share/emacs/site-lisp/elpa/yasnippet-0.14.1/yasnippet-pkg hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-0.14.1/yasnippet-pkg /usr/share/emacs/site-lisp/elpa/yasnippet-0.14.1/yasnippet hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-0.14.1/yasnippet /usr/share/emacs/site-lisp/elpa/yasnippet-snippets-20220713/yasnippet-snippets hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-snippets-20220713/yasnippet-snippets /usr/share/emacs/site-lisp/elpa/yasnippet-snippets-20220713/yasnippet-snippets-pkg hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-snippets-20220713/yasnippet-snippets-pkg /usr/share/emacs/site-lisp/elpa/yasnippet-snippets-20220713/yasnippet-snippets-autoloads hides /usr/share/emacs/site-lisp/elpa-src/yasnippet-snippets-20220713/yasnippet-snippets-autoloads /usr/share/emacs/site-lisp/elpa/zenburn-theme-2.8.0/zenburn-theme hides /usr/share/emacs/site-lisp/elpa-src/zenburn-theme-2.8.0/zenburn-theme /usr/share/emacs/site-lisp/elpa/zenburn-theme-2.8.0/zenburn-theme-pkg hides /usr/share/emacs/site-lisp/elpa-src/zenburn-theme-2.8.0/zenburn-theme-pkg /usr/share/emacs/site-lisp/elpa/zenburn-theme-2.8.0/zenburn-theme-autoloads hides /usr/share/emacs/site-lisp/elpa-src/zenburn-theme-2.8.0/zenburn-theme-autoloads /usr/share/emacs/site-lisp/elpa/seq-2.24/seq hides /usr/share/emacs/29.4/lisp/emacs-lisp/seq Features: (shadow emacsbug url-queue magit-extras magit-bookmark magit-submodule magit-obsolete magit-blame magit-stash magit-reflog magit-bisect magit-push magit-pull magit-fetch magit-clone magit-remote magit-commit magit-sequence magit-notes magit-worktree magit-tag magit-merge magit-branch magit-reset magit-files magit-refs magit-status magit magit-repos magit-apply magit-wip magit-log which-func imenu magit-diff smerge-mode diff git-commit log-edit add-log magit-core magit-autorevert magit-margin magit-transient magit-process with-editor shell magit-mode transient magit-git magit-section etags fileloop generator xref shr-color help-fns radix-tree cl-print debug backtrace magit-utils crm dired-aux mailalias po face-remap matlab matlab-scan matlab-syntax matlab-compat qp mm-archive sort gnus-cite mail-extr textsec uni-scripts idna-mapping ucs-normalize uni-confusable textsec-check gnus-async gnus-bcklg gnus-ml gnus-topic cursor-sensor utf-7 url-cache nnfolder gnus-demon nnml ezgnus gnus-delay gnus-draft gnus-agent gnus-srvr gnus-score score-mode nnvirtual nntp gnus-cache nndraft nnmh mu4e mu4e-org org ob ob-tangle ob-ref ob-lob ob-table ob-exp org-macro org-src ob-comint org-pcomplete pcomplete org-list org-footnote org-faces org-entities noutline outline ob-emacs-lisp ob-core ob-eval org-cycle org-table ol org-fold org-fold-core org-keys oc org-loaddefs find-func org-version org-compat org-macs format-spec mu4e-notification notifications mu4e-main mu4e-view mu4e-mime-parts cal-menu calendar cal-loaddefs mu4e-headers mu4e-thread mu4e-actions mu4e-compose mu4e-draft gnus-msg gnus-art mm-uu mml2015 mm-view mml-smime smime dig gnus-sum gnus-group gnus-undo gnus-start gnus-dbus dbus gnus-cloud nnimap nnmail mail-source utf7 nnoo gnus-spec gnus-int gnus-range gnus-win gnus nnheader range mu4e-search mu4e-lists mu4e-bookmarks mu4e-mark mu4e-message shr pixel-fill kinsoku url-file svg xml dom flow-fill mu4e-contacts mu4e-update mu4e-folders mu4e-context mu4e-query-items mu4e-server mu4e-modeline mu4e-vars mu4e-helpers mu4e-config mu4e-window ido message yank-media rfc822 mml mml-sec gnus-util mm-decode mm-bodies mm-encode mailabbrev gmm-utils mailheader mu4e-obsolete mule-util jka-compr windmove flyspell ispell gnutls network-stream epa-file epa derived rcirc parse-time iso8601 time-date term/xterm xterm comp comp-cstr server cap-words superword subword vc-hg vc-git diff-mode vc-bzr vc-src vc-sccs vc-svn vc-cvs vc-rcs log-view pcvs-util vc vc-dispatcher bug-reference disp-table whitespace yasnippet-snippets yasnippet cus-edit cus-start wid-edit init mu4e-debian-hx90 zenburn-theme xclip treesit-auto treesit treemacs-project-follow-mode treemacs-follow-mode treemacs-rendering treemacs-annotations treemacs-async treemacs-visuals treemacs-fringe-indicator pulse color treemacs-workspaces treemacs-dom treemacs-icons treemacs-themes treemacs-scope treemacs-core-utils treemacs-logging treemacs-customization pfuture inline ht s hl-line dash keychain-environment exec-path-from-shell corfu-terminal popon corfu-popupinfo corfu-echo corfu compat compat-30 activities-tabs activities persist bookmark pp edmacro kmacro auth-source-xoauth2-plugin smtpmail sendmail mail-utils oauth2 url-http url-auth mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr url-gw nsm puny plstore epg rfc6068 epg-config advice icomplete cus-load flymake-proc flymake project compile text-property-search comint ansi-osc ansi-color ring warnings icons thingatpt cl-extra help-mode use-package use-package-ensure use-package-delight use-package-diminish use-package-bind-key bind-key easy-mmode use-package-core display-line-numbers autorevert filenotify keychain-environment-autoloads treesit-auto-autoloads xclip-autoloads rx info debian-el dired dired-loaddefs finder-inf package browse-url url url-proxy url-privacy url-expand url-methods url-history url-cookie generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu timer select scroll-bar mouse jit-lock font-lock syntax font-core term/tty-colors frame minibuffer nadvice seq simple cl-generic indonesian philippine cham georgian utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek romanian slovak czech european ethiopic indian cyrillic chinese composite emoji-zwj charscript charprop case-table epa-hook jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs theme-loaddefs faces cus-face macroexp files window text-properties overlay sha1 md5 base64 format env code-pages mule custom widget keymap hashtable-print-readable backquote threads dbusbind inotify lcms2 dynamic-setting system-font-setting font-render-setting cairo move-toolbar gtk x-toolkit xinput2 x multi-tty make-network-process native-compile emacs) Memory information: ((conses 16 1284383 173587) (symbols 48 38751 38) (strings 32 161682 13995) (string-bytes 1 5119905) (vectors 16 102981) (vector-slots 8 2547120 157205) (floats 8 1011 1550) (intervals 56 48502 7145) (buffers 984 76)) -- Xiyue Deng [-- Attachment #2: auth-source-xoauth2-plugin.el --] [-- Type: application/emacs-lisp, Size: 6506 bytes --] ^ permalink raw reply [flat|nested] 26+ messages in thread
[parent not found: <handler.72992.B.172532159013230.ack@debbugs.gnu.org>]
* bug#72992: 29.4; towards xoauth2 support in Emacs [not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org> @ 2024-09-11 0:27 ` Xiyue Deng 2024-09-17 17:33 ` Xiyue Deng 0 siblings, 1 reply; 26+ messages in thread From: Xiyue Deng @ 2024-09-11 0:27 UTC (permalink / raw) To: 72992 Friendly ping for feedback. -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-11 0:27 ` Xiyue Deng @ 2024-09-17 17:33 ` Xiyue Deng 0 siblings, 0 replies; 26+ messages in thread From: Xiyue Deng @ 2024-09-17 17:33 UTC (permalink / raw) To: 72992, Philip Kaludercic Xiyue Deng <manphiz@gmail.com> writes: > Friendly ping for feedback. > -- > Xiyue Deng Another friendly ping. Also CCing Philip who kindly provided feedback for the previous bug. -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-02 8:34 bug#72992: 29.4; towards xoauth2 support in Emacs Xiyue Deng [not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org> @ 2024-09-17 19:12 ` Philip Kaludercic 2024-09-18 6:24 ` Xiyue Deng 2024-09-17 21:33 ` Stefan Kangas 2 siblings, 1 reply; 26+ messages in thread From: Philip Kaludercic @ 2024-09-17 19:12 UTC (permalink / raw) To: Xiyue Deng; +Cc: 72992 Xiyue Deng <manphiz@gmail.com> writes: > Now that bug#72358 is done, as promised, I'm posting my plugin for > auth-sources that enables oauth2 handling which you can find on > Gitlab[1] (also attached). Once again I just want to be sure: When you say "plugin", you mean package, right? You are proposing to add this to GNU ELPA? [...] > > Thanks for reading, and any comments are appreciated. I'll be honest, I have no idea about OAuth, so my comments are just related to Elisp for now. Hope that's OK! > [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin > ;; Copyright (C) 2024 Xiyue Deng <manphiz@gmail.com> > > ;; Author: Xiyue Deng <manphiz@gmail.com> > ;; Version: 0.1-git > ;; Package-Requires: ((emacs "28.1") (oauth2 "0.17")) > > ;; This file is not part of GNU Emacs. > > ;; GNU Emacs is free software: you can redistribute it and/or modify > ;; it under the terms of the GNU General Public License as published by > ;; the Free Software Foundation, either version 3 of the License, or > ;; (at your option) any later version. > > ;; GNU Emacs is distributed in the hope that it will be useful, > ;; but WITHOUT ANY WARRANTY; without even the implied warranty of > ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > ;; GNU General Public License for more details. > > ;; You should have received a copy of the GNU General Public License > ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. > > ;;; Commentary: > > ;; This package enables support for xoauth2 authentication with > ;; auth-source. To set up, please put this file in the `load-path' of > ;; Emacs, and add the following lines in your Emacs configuration: > > ;; (require 'auth-source-xoauth2-plugin) > ;; (auth-source-xoauth2-plugin-enable) > > ;; or with use-package: > > ;; (use-package auth-source-xoauth2-plugin > ;; :config > ;; (auth-source-xoauth2-plugin-enable)) > > ;; After enabling, smtpmail should be supported. To enable this in Gnus > ;; nnimap, you should also set `(nnimap-authenticator xoauth2)' in the > ;; corresponding account settings in `gnus-secondary-select-methods' > > ;; auth-source uses the `secret' field in auth-source file as password > ;; for authentication, including xoauth2. To decide which > ;; authentication method to use (e.g. plain password vs xoauth2), it > ;; inspects the `auth' field from the auth-source entry, and if the > ;; value is `xaouth2', it will try to gather data and get the access > ;; token for use of xoauth2 authentication; otherwise, it will fallback > ;; to the default authentication method. > > ;; When xoauth2 authentication is enabled, it will try to get the > ;; following data from the auth-source entry: `auth-url', `token-url', > ;; `scope', `client-id', `client-secret', `redirect-uri', and optionally > ;; `state'. These information will be used by oauth2 to retrieve the > ;; access-token. This package uses an advice to switch the auth-source > ;; search result from the `password' to the `access-token' it got, which > ;; in turn will be used to construct the xoauth2 authentication string, > ;; currently in nnimap-login and smtpmail-try-auth-method. To really > ;; enable xoauth2 in smtpmail, it will add 'xoauth2 to > ;; 'smtpmail-auth-supported (if it is not already in the list) using > ;; `add-to-list' so that xoauth2 is tried first. > > ;; Note that currently the auth-source requires the searched entry must > ;; have `secret' field set in the entry, which is not necessary when > ;; using xoauth2. Therefore in the advice it temporarily disables > ;; checking for `:secret' if set and perform the search, and check the > ;; result before returning. > > ;;; Code: > > (require 'auth-source) > (require 'cl-lib) > (require 'oauth2) > (require 'smtpmail) > > (defun auth-source-xoauth2-plugin--search-backends (orig-fun &rest args) > "Perform auth-source-search and set password as access-token when requested. > The substitution only happens if one sets `auth' to `xoauth2' in > your auth-source-entry. It is expected that `token_url', > `client_id', `client_secret', and `refresh_token' are properly > set along `host', `user', and `port' (note the snake_case)." > (auth-source-do-trivia "Advising auth-source-search") > (let (check-secret) > (when (memq :secret (nth 5 args)) > (auth-source-do-trivia > "Required fields include :secret. As we are requesting access token to replace the secret, we'll temporary remove :secret from the require list and check that it's properly set to a valid access token later.") > (setf (nth 5 args) (remove :secret (nth 5 args))) > (setq check-secret t)) > (let ((orig-res (apply orig-fun args)) > res) > (dolist (auth-data orig-res) > (auth-source-do-trivia "Matched auth data: %s" (pp-to-string auth-data)) Is "trivia" the right debug level for all the messages in this function? I feel like some of them should at least be "debug". > (let ((auth (plist-get auth-data :auth))) > (when (and auth > (stringp auth) > (string= auth "xoauth2")) You can simplify the check by just doing (equal auth "xoauth2"), as this implies all of the above (if it is `equal' to a string, it must be a string and hence also non-nil). > (auth-source-do-debug > ":auth set to `xoauth2'. Will get access token.") > (let ((auth-url (plist-get auth-data :auth-url)) > (token-url (plist-get auth-data :token-url)) > (scope (plist-get auth-data :scope)) > (client-id (plist-get auth-data :client-id)) > (client-secret (plist-get auth-data :client-secret)) > (redirect-uri (plist-get auth-data :redirect-uri)) > (state (plist-get auth-data :state))) I feel like this could be simplified with a map-let expression. (map-let (:auth-url :token-url ...) auth-data ...) You should be able to require 'map at compile time, so that the expansions don't occur an overhead during run-time. > (auth-source-do-trivia "Using oauth2 to auth and store token...") > (let ((token (oauth2-auth-and-store > auth-url token-url scope client-id client-secret > redirect-uri state))) > (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token)) > (auth-source-do-trivia "Refreshing token...") > (oauth2-refresh-access token) > (auth-source-do-trivia "oauth2 token after refresh: %s" > (pp-to-string token)) > (let ((access-token (oauth2-token-access-token token))) > (auth-source-do-trivia > "Updating :secret with access-token: %s" access-token) > (plist-put auth-data :secret access-token)))))) The documentation for plist-put warns: The new plist is returned; use ‘(setq x (plist-put x prop val))’ to be sure to use the new value. The PLIST is modified by side effects. Alternatively, you should also be able to do: (setf (plist-get auth-data :secret) access-token) > > (unless (and check-secret > (not (plist-get auth-data :secret))) > (auth-source-do-trivia "Updating auth-source-search results.") > (add-to-list 'res auth-data t))) This should definitely be a `push', as `res' is lexically scoped (see docstring for `add-to-list'). > res))) > > ;;;###autoload > (defun auth-source-xoauth2-plugin-enable () > "Enable auth-source-xoauth2-plugin." > (unless (memq 'xoauth2 smtpmail-auth-supported) > (add-to-list 'smtpmail-auth-supported 'xoauth2)) In functions, it would be more conventional to use push. Especially because `add-to-list' checks for duplicates, which you have already done. > > (advice-add 'auth-source-search-backends :around There's no reason not to sharp-quote the function here as well? > #'auth-source-xoauth2-plugin--search-backends)) I would recommend turning this into a global minor mode instead, so that it is easy to disable, if a user just wants to try it out. > > (provide 'auth-source-xoauth2-plugin) > > ;;; auth-source-xoauth2-plugin.el ends here -- Philip Kaludercic on siskin ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-17 19:12 ` Philip Kaludercic @ 2024-09-18 6:24 ` Xiyue Deng 2024-09-18 14:11 ` Philip Kaludercic 0 siblings, 1 reply; 26+ messages in thread From: Xiyue Deng @ 2024-09-18 6:24 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 72992 Philip Kaludercic <philipk@posteo.net> writes: > Xiyue Deng <manphiz@gmail.com> writes: > >> Now that bug#72358 is done, as promised, I'm posting my plugin for >> auth-sources that enables oauth2 handling which you can find on >> Gitlab[1] (also attached). > > Once again I just want to be sure: When you say "plugin", you mean > package, right? Yes, though it's not really an independent package but a "plugin" for auth-source, a.k.a. a hack (the advice) to make auth-source to work with xoauth2. > You are proposing to add this to GNU ELPA? > Actually I would like to see which of my proposed changes to auth-source is acceptable and update auth-source in core accordingly. I think Stefan's reply gave some suggestions in this regard and I'll follow-up in a reply there. Meanwhile, it may still worth adding this package to ELPA to support older Emacs versions if desired. > [...] > >> >> Thanks for reading, and any comments are appreciated. > > I'll be honest, I have no idea about OAuth, so my comments are just > related to Elisp for now. Hope that's OK! > Your comments are greatly helpful and much appreciated! Please see my replies below. >> [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin > >> ;; Copyright (C) 2024 Xiyue Deng <manphiz@gmail.com> >> >> ;; Author: Xiyue Deng <manphiz@gmail.com> >> ;; Version: 0.1-git >> ;; Package-Requires: ((emacs "28.1") (oauth2 "0.17")) >> >> ;; This file is not part of GNU Emacs. >> >> ;; GNU Emacs is free software: you can redistribute it and/or modify >> ;; it under the terms of the GNU General Public License as published by >> ;; the Free Software Foundation, either version 3 of the License, or >> ;; (at your option) any later version. >> >> ;; GNU Emacs is distributed in the hope that it will be useful, >> ;; but WITHOUT ANY WARRANTY; without even the implied warranty of >> ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> ;; GNU General Public License for more details. >> >> ;; You should have received a copy of the GNU General Public License >> ;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. >> >> ;;; Commentary: >> >> ;; This package enables support for xoauth2 authentication with >> ;; auth-source. To set up, please put this file in the `load-path' of >> ;; Emacs, and add the following lines in your Emacs configuration: >> >> ;; (require 'auth-source-xoauth2-plugin) >> ;; (auth-source-xoauth2-plugin-enable) >> >> ;; or with use-package: >> >> ;; (use-package auth-source-xoauth2-plugin >> ;; :config >> ;; (auth-source-xoauth2-plugin-enable)) >> >> ;; After enabling, smtpmail should be supported. To enable this in Gnus >> ;; nnimap, you should also set `(nnimap-authenticator xoauth2)' in the >> ;; corresponding account settings in `gnus-secondary-select-methods' >> >> ;; auth-source uses the `secret' field in auth-source file as password >> ;; for authentication, including xoauth2. To decide which >> ;; authentication method to use (e.g. plain password vs xoauth2), it >> ;; inspects the `auth' field from the auth-source entry, and if the >> ;; value is `xaouth2', it will try to gather data and get the access >> ;; token for use of xoauth2 authentication; otherwise, it will fallback >> ;; to the default authentication method. >> >> ;; When xoauth2 authentication is enabled, it will try to get the >> ;; following data from the auth-source entry: `auth-url', `token-url', >> ;; `scope', `client-id', `client-secret', `redirect-uri', and optionally >> ;; `state'. These information will be used by oauth2 to retrieve the >> ;; access-token. This package uses an advice to switch the auth-source >> ;; search result from the `password' to the `access-token' it got, which >> ;; in turn will be used to construct the xoauth2 authentication string, >> ;; currently in nnimap-login and smtpmail-try-auth-method. To really >> ;; enable xoauth2 in smtpmail, it will add 'xoauth2 to >> ;; 'smtpmail-auth-supported (if it is not already in the list) using >> ;; `add-to-list' so that xoauth2 is tried first. >> >> ;; Note that currently the auth-source requires the searched entry must >> ;; have `secret' field set in the entry, which is not necessary when >> ;; using xoauth2. Therefore in the advice it temporarily disables >> ;; checking for `:secret' if set and perform the search, and check the >> ;; result before returning. >> >> ;;; Code: >> >> (require 'auth-source) >> (require 'cl-lib) >> (require 'oauth2) >> (require 'smtpmail) >> >> (defun auth-source-xoauth2-plugin--search-backends (orig-fun &rest args) >> "Perform auth-source-search and set password as access-token when requested. >> The substitution only happens if one sets `auth' to `xoauth2' in >> your auth-source-entry. It is expected that `token_url', >> `client_id', `client_secret', and `refresh_token' are properly >> set along `host', `user', and `port' (note the snake_case)." >> (auth-source-do-trivia "Advising auth-source-search") >> (let (check-secret) >> (when (memq :secret (nth 5 args)) >> (auth-source-do-trivia >> "Required fields include :secret. As we are requesting access token to replace the secret, we'll temporary remove :secret from the require list and check that it's properly set to a valid access token later.") >> (setf (nth 5 args) (remove :secret (nth 5 args))) >> (setq check-secret t)) >> (let ((orig-res (apply orig-fun args)) >> res) >> (dolist (auth-data orig-res) >> (auth-source-do-trivia "Matched auth data: %s" (pp-to-string auth-data)) > > Is "trivia" the right debug level for all the messages in this function? > I feel like some of them should at least be "debug". > Indeed. I have changed logs without token to be "debug"-level. >> (let ((auth (plist-get auth-data :auth))) >> (when (and auth >> (stringp auth) >> (string= auth "xoauth2")) > > You can simplify the check by just doing (equal auth "xoauth2"), as this > implies all of the above (if it is `equal' to a string, it must be a > string and hence also non-nil). > Done. Nice tip! Coming from strong-typed languages I always want to do type-checks first in fear of any aborting error :) >> (auth-source-do-debug >> ":auth set to `xoauth2'. Will get access token.") >> (let ((auth-url (plist-get auth-data :auth-url)) >> (token-url (plist-get auth-data :token-url)) >> (scope (plist-get auth-data :scope)) >> (client-id (plist-get auth-data :client-id)) >> (client-secret (plist-get auth-data :client-secret)) >> (redirect-uri (plist-get auth-data :redirect-uri)) >> (state (plist-get auth-data :state))) > > I feel like this could be simplified with a map-let expression. > > (map-let (:auth-url :token-url ...) auth-data > ...) > > You should be able to require 'map at compile time, so that the > expansions don't occur an overhead during run-time. > Another nice TIL! >> (auth-source-do-trivia "Using oauth2 to auth and store token...") >> (let ((token (oauth2-auth-and-store >> auth-url token-url scope client-id client-secret >> redirect-uri state))) >> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token)) >> (auth-source-do-trivia "Refreshing token...") >> (oauth2-refresh-access token) >> (auth-source-do-trivia "oauth2 token after refresh: %s" >> (pp-to-string token)) >> (let ((access-token (oauth2-token-access-token token))) >> (auth-source-do-trivia >> "Updating :secret with access-token: %s" access-token) >> (plist-put auth-data :secret access-token)))))) > > The documentation for plist-put warns: > > The new plist is returned; > use ‘(setq x (plist-put x prop val))’ to be sure to use the new value. > The PLIST is modified by side effects. > > Alternatively, you should also be able to do: > > (setf (plist-get auth-data :secret) access-token) > Ah didn't know this as I learned the usage of plist-put from searching. Changed to your `setq' version. Though I'd also expect that the side effect is not going away anytime soon either ;) >> >> (unless (and check-secret >> (not (plist-get auth-data :secret))) >> (auth-source-do-trivia "Updating auth-source-search results.") >> (add-to-list 'res auth-data t))) > > This should definitely be a `push', as `res' is lexically scoped (see > docstring for `add-to-list'). > Indeed. Guess I got lucky here that it behaves the same. >> res))) >> >> ;;;###autoload >> (defun auth-source-xoauth2-plugin-enable () >> "Enable auth-source-xoauth2-plugin." >> (unless (memq 'xoauth2 smtpmail-auth-supported) >> (add-to-list 'smtpmail-auth-supported 'xoauth2)) > > In functions, it would be more conventional to use push. Especially > because `add-to-list' checks for duplicates, which you have already > done. > Ack. >> >> (advice-add 'auth-source-search-backends :around > > There's no reason not to sharp-quote the function here as well? > Indeed. Added. >> #'auth-source-xoauth2-plugin--search-backends)) > > I would recommend turning this into a global minor mode instead, so that > it is easy to disable, if a user just wants to try it out. > This is an interesting suggestion and sounds like a good idea. Though as a matter of fact the oauth2 support in auth-source in Emacs core actually doesn't work without those hack as of now, so I don't think it's of interest to support turning off. But of course it would be great if auth-source can be changed to support all this out-of-the-box. Will continue the discussion in my reply to Stefan. I have updated the source code on GitLab[1] based on your review. Please check it out. Thanks very much! >> >> (provide 'auth-source-xoauth2-plugin) >> >> ;;; auth-source-xoauth2-plugin.el ends here > > -- > Philip Kaludercic on siskin -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-18 6:24 ` Xiyue Deng @ 2024-09-18 14:11 ` Philip Kaludercic 2024-09-22 7:06 ` Xiyue Deng 0 siblings, 1 reply; 26+ messages in thread From: Philip Kaludercic @ 2024-09-18 14:11 UTC (permalink / raw) To: Xiyue Deng; +Cc: 72992 Xiyue Deng <manphiz@gmail.com> writes: > Philip Kaludercic <philipk@posteo.net> writes: > >> Xiyue Deng <manphiz@gmail.com> writes: >> >>> Now that bug#72358 is done, as promised, I'm posting my plugin for >>> auth-sources that enables oauth2 handling which you can find on >>> Gitlab[1] (also attached). >> >> Once again I just want to be sure: When you say "plugin", you mean >> package, right? > > Yes, though it's not really an independent package but a "plugin" for > auth-source, a.k.a. a hack (the advice) to make auth-source to work with > xoauth2. Just to clarify: When I say package, I mean something to add to ELPA. >> You are proposing to add this to GNU ELPA? > > Actually I would like to see which of my proposed changes to auth-source > is acceptable and update auth-source in core accordingly. Sure it's acceptable, but in that case it would better to submit a patch modifying. auth-source.el > I think > Stefan's reply gave some suggestions in this regard and I'll follow-up > in a reply there. I just want to second Stefan's point that some clarification as to what xoauth2 is. > Meanwhile, it may still worth adding this package > to ELPA to support older Emacs versions if desired. In that case it might be better not to merge your changes into auth-source.el directly, as that would make it more difficult to automatically pull your changes out of the core to ELPA. An alternative is that ELPA mirrors your repository, and then we manually synchronise the changes into the core, whenever there is a new release. [...] >>> (let ((auth (plist-get auth-data :auth))) >>> (when (and auth >>> (stringp auth) >>> (string= auth "xoauth2")) >> >> You can simplify the check by just doing (equal auth "xoauth2"), as this >> implies all of the above (if it is `equal' to a string, it must be a >> string and hence also non-nil). >> > > Done. Nice tip! Coming from strong-typed languages I always want to do > type-checks first in fear of any aborting error :) If you want strong typing, then string= is the right thing to use, because if you want to assume that auth is always a string, then an error will be signalled. That being said, if auth has the type "Maybe String", then checking the values explicitly or implicitly using equal is the right approach. [...] >>> (auth-source-do-trivia "Using oauth2 to auth and store token...") >>> (let ((token (oauth2-auth-and-store >>> auth-url token-url scope client-id client-secret >>> redirect-uri state))) >>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token)) >>> (auth-source-do-trivia "Refreshing token...") >>> (oauth2-refresh-access token) >>> (auth-source-do-trivia "oauth2 token after refresh: %s" >>> (pp-to-string token)) >>> (let ((access-token (oauth2-token-access-token token))) >>> (auth-source-do-trivia >>> "Updating :secret with access-token: %s" access-token) >>> (plist-put auth-data :secret access-token)))))) >> >> The documentation for plist-put warns: >> >> The new plist is returned; >> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value. >> The PLIST is modified by side effects. >> >> Alternatively, you should also be able to do: >> >> (setf (plist-get auth-data :secret) access-token) >> > > Ah didn't know this as I learned the usage of plist-put from searching. > Changed to your `setq' version. Though I'd also expect that the side > effect is not going away anytime soon either ;) I am not sure what you mean? The crux of the issue is demonstrated here: (let (plist) (list (plist-put plist :foo 1) plist)) ;; ((:foo 1) nil) I.e. the plist was not modified, because there was no cons-cell to modify. [...] >>> #'auth-source-xoauth2-plugin--search-backends)) >> >> I would recommend turning this into a global minor mode instead, so that >> it is easy to disable, if a user just wants to try it out. >> > > This is an interesting suggestion and sounds like a good idea. Though > as a matter of fact the oauth2 support in auth-source in Emacs core > actually doesn't work without those hack as of now, so I don't think > it's of interest to support turning off. I regard it as a matter of good style to allow the user to disable anything then can enable, if anything then just to allow better experimentation. > But of course it would be > great if auth-source can be changed to support all this out-of-the-box. > Will continue the discussion in my reply to Stefan. Ack. > I have updated the source code on GitLab[1] based on your review. > Please check it out. Thanks very much! For anyone following the thread, it seem the footnote was missing: [1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el Watch out, in (unless (memq 'xoauth2 smtpmail-auth-supported) (push 'smtpmail-auth-supported 'xoauth2)) the push expression is malformed, as 'xoauth2 is not a place. I'm guessing that you want to write (... (push 'xoauth2 smtpmail-auth-supported)) Also, checkdoc complains about `auth-source-xoauth2-plugin--search-backends's docstring. I'd try to address the issues it mentions. The (and auth (equal auth "xoauth2")) can be further simplified to just (equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil. >>> >>> (provide 'auth-source-xoauth2-plugin) >>> >>> ;;; auth-source-xoauth2-plugin.el ends here >> >> -- >> Philip Kaludercic on siskin -- Philip Kaludercic on siskin ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-18 14:11 ` Philip Kaludercic @ 2024-09-22 7:06 ` Xiyue Deng 2024-09-22 9:34 ` Philip Kaludercic 0 siblings, 1 reply; 26+ messages in thread From: Xiyue Deng @ 2024-09-22 7:06 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 72992 Hi Philip, Philip Kaludercic <philipk@posteo.net> writes: > Xiyue Deng <manphiz@gmail.com> writes: > >> Philip Kaludercic <philipk@posteo.net> writes: >> >>> Xiyue Deng <manphiz@gmail.com> writes: >>> >>>> Now that bug#72358 is done, as promised, I'm posting my plugin for >>>> auth-sources that enables oauth2 handling which you can find on >>>> Gitlab[1] (also attached). >>> >>> Once again I just want to be sure: When you say "plugin", you mean >>> package, right? >> >> Yes, though it's not really an independent package but a "plugin" for >> auth-source, a.k.a. a hack (the advice) to make auth-source to work with >> xoauth2. > > Just to clarify: When I say package, I mean something to add to ELPA. > Ah in that regard yes. >>> You are proposing to add this to GNU ELPA? >> >> Actually I would like to see which of my proposed changes to auth-source >> is acceptable and update auth-source in core accordingly. > > Sure it's acceptable, but in that case it would better to submit a patch > modifying. auth-source.el > >> I think >> Stefan's reply gave some suggestions in this regard and I'll follow-up >> in a reply there. > > I just want to second Stefan's point that some clarification as to what > xoauth2 is. > Updated the comments section with this info. >> Meanwhile, it may still worth adding this package >> to ELPA to support older Emacs versions if desired. > > In that case it might be better not to merge your changes into > auth-source.el directly, as that would make it more difficult to > automatically pull your changes out of the core to ELPA. > > An alternative is that ELPA mirrors your repository, and then we > manually synchronise the changes into the core, whenever there is a new > release. > I was thinking making it only for Emacs <30 if the auth-source side changes are upstreamed for 31. Similar to "docker-tramp" which is only for EMacs <28. > > [...] > >>>> (let ((auth (plist-get auth-data :auth))) >>>> (when (and auth >>>> (stringp auth) >>>> (string= auth "xoauth2")) >>> >>> You can simplify the check by just doing (equal auth "xoauth2"), as this >>> implies all of the above (if it is `equal' to a string, it must be a >>> string and hence also non-nil). >>> >> >> Done. Nice tip! Coming from strong-typed languages I always want to do >> type-checks first in fear of any aborting error :) > > If you want strong typing, then string= is the right thing to use, > because if you want to assume that auth is always a string, then an > error will be signalled. That being said, if auth has the type "Maybe > String", then checking the values explicitly or implicitly using equal > is the right approach. > Ack. Thanks for the tip! > > [...] > >>>> (auth-source-do-trivia "Using oauth2 to auth and store token...") >>>> (let ((token (oauth2-auth-and-store >>>> auth-url token-url scope client-id client-secret >>>> redirect-uri state))) >>>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token)) >>>> (auth-source-do-trivia "Refreshing token...") >>>> (oauth2-refresh-access token) >>>> (auth-source-do-trivia "oauth2 token after refresh: %s" >>>> (pp-to-string token)) >>>> (let ((access-token (oauth2-token-access-token token))) >>>> (auth-source-do-trivia >>>> "Updating :secret with access-token: %s" access-token) >>>> (plist-put auth-data :secret access-token)))))) >>> >>> The documentation for plist-put warns: >>> >>> The new plist is returned; >>> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value. >>> The PLIST is modified by side effects. >>> >>> Alternatively, you should also be able to do: >>> >>> (setf (plist-get auth-data :secret) access-token) >>> >> >> Ah didn't know this as I learned the usage of plist-put from searching. >> Changed to your `setq' version. Though I'd also expect that the side >> effect is not going away anytime soon either ;) > > I am not sure what you mean? The crux of the issue is demonstrated > here: > > (let (plist) > (list (plist-put plist :foo 1) plist)) > ;; ((:foo 1) nil) > > I.e. the plist was not modified, because there was no cons-cell to > modify. > I see. Thanks for the explanation. Looks like the side effect worked for me because auth-data already had data in it. > > [...] > >>>> #'auth-source-xoauth2-plugin--search-backends)) >>> >>> I would recommend turning this into a global minor mode instead, so that >>> it is easy to disable, if a user just wants to try it out. >>> >> >> This is an interesting suggestion and sounds like a good idea. Though >> as a matter of fact the oauth2 support in auth-source in Emacs core >> actually doesn't work without those hack as of now, so I don't think >> it's of interest to support turning off. > > I regard it as a matter of good style to allow the user to disable > anything then can enable, if anything then just to allow better > experimentation. > You actually convinced me. Making it a minor mode also enables a user to disable it temporarily if it causes any issues. It took me a while to convert it. Please help take another look. >> But of course it would be >> great if auth-source can be changed to support all this out-of-the-box. >> Will continue the discussion in my reply to Stefan. > > Ack. > >> I have updated the source code on GitLab[1] based on your review. >> Please check it out. Thanks very much! > > For anyone following the thread, it seem the footnote was missing: > > [1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el > > Watch out, in > > (unless (memq 'xoauth2 smtpmail-auth-supported) > (push 'smtpmail-auth-supported 'xoauth2)) > > the push expression is malformed, as 'xoauth2 is not a place. I'm > guessing that you want to write > > (... (push 'xoauth2 smtpmail-auth-supported)) > Thanks! Fixed. > Also, checkdoc complains about > `auth-source-xoauth2-plugin--search-backends's docstring. I'd try to > address the issues it mentions. > Also fixed. Thanks! > The (and auth (equal auth "xoauth2")) can be further simplified to just > (equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil. > Ack and simplified. The GitLab repo[1] is updated accordingly. PTAL. TIA! >>>> >>>> (provide 'auth-source-xoauth2-plugin) >>>> >>>> ;;; auth-source-xoauth2-plugin.el ends here >>> >>> -- >>> Philip Kaludercic on siskin > > -- > Philip Kaludercic on siskin [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-22 7:06 ` Xiyue Deng @ 2024-09-22 9:34 ` Philip Kaludercic 2024-09-22 22:00 ` Xiyue Deng 0 siblings, 1 reply; 26+ messages in thread From: Philip Kaludercic @ 2024-09-22 9:34 UTC (permalink / raw) To: Xiyue Deng; +Cc: 72992 [-- Attachment #1: Type: text/plain, Size: 7600 bytes --] Xiyue Deng <manphiz@gmail.com> writes: > Hi Philip, > > Philip Kaludercic <philipk@posteo.net> writes: > >> Xiyue Deng <manphiz@gmail.com> writes: >> >>> Philip Kaludercic <philipk@posteo.net> writes: >>> >>>> Xiyue Deng <manphiz@gmail.com> writes: >>>> >>>>> Now that bug#72358 is done, as promised, I'm posting my plugin for >>>>> auth-sources that enables oauth2 handling which you can find on >>>>> Gitlab[1] (also attached). >>>> >>>> Once again I just want to be sure: When you say "plugin", you mean >>>> package, right? >>> >>> Yes, though it's not really an independent package but a "plugin" for >>> auth-source, a.k.a. a hack (the advice) to make auth-source to work with >>> xoauth2. >> >> Just to clarify: When I say package, I mean something to add to ELPA. >> > > Ah in that regard yes. > >>>> You are proposing to add this to GNU ELPA? >>> >>> Actually I would like to see which of my proposed changes to auth-source >>> is acceptable and update auth-source in core accordingly. >> >> Sure it's acceptable, but in that case it would better to submit a patch >> modifying. auth-source.el >> >>> I think >>> Stefan's reply gave some suggestions in this regard and I'll follow-up >>> in a reply there. >> >> I just want to second Stefan's point that some clarification as to what >> xoauth2 is. >> > > Updated the comments section with this info. Great, that explains it well! >>> Meanwhile, it may still worth adding this package >>> to ELPA to support older Emacs versions if desired. >> >> In that case it might be better not to merge your changes into >> auth-source.el directly, as that would make it more difficult to >> automatically pull your changes out of the core to ELPA. >> >> An alternative is that ELPA mirrors your repository, and then we >> manually synchronise the changes into the core, whenever there is a new >> release. >> > > I was thinking making it only for Emacs <30 if the auth-source side > changes are upstreamed for 31. Similar to "docker-tramp" which is only > for EMacs <28. The issue here is that tramp is developed outside of Emacs and synchronised manually back into the core/automatically on ELPA, while auth-source is currently only in the core and not distributed on ELPA. If this remains a separate file, we could easily add it to ELPA, but I don't know what the preference is there. >> >> [...] >> >>>>> (let ((auth (plist-get auth-data :auth))) >>>>> (when (and auth >>>>> (stringp auth) >>>>> (string= auth "xoauth2")) >>>> >>>> You can simplify the check by just doing (equal auth "xoauth2"), as this >>>> implies all of the above (if it is `equal' to a string, it must be a >>>> string and hence also non-nil). >>>> >>> >>> Done. Nice tip! Coming from strong-typed languages I always want to do >>> type-checks first in fear of any aborting error :) >> >> If you want strong typing, then string= is the right thing to use, >> because if you want to assume that auth is always a string, then an >> error will be signalled. That being said, if auth has the type "Maybe >> String", then checking the values explicitly or implicitly using equal >> is the right approach. >> > > Ack. Thanks for the tip! > >> >> [...] >> >>>>> (auth-source-do-trivia "Using oauth2 to auth and store token...") >>>>> (let ((token (oauth2-auth-and-store >>>>> auth-url token-url scope client-id client-secret >>>>> redirect-uri state))) >>>>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token)) >>>>> (auth-source-do-trivia "Refreshing token...") >>>>> (oauth2-refresh-access token) >>>>> (auth-source-do-trivia "oauth2 token after refresh: %s" >>>>> (pp-to-string token)) >>>>> (let ((access-token (oauth2-token-access-token token))) >>>>> (auth-source-do-trivia >>>>> "Updating :secret with access-token: %s" access-token) >>>>> (plist-put auth-data :secret access-token)))))) >>>> >>>> The documentation for plist-put warns: >>>> >>>> The new plist is returned; >>>> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value. >>>> The PLIST is modified by side effects. >>>> >>>> Alternatively, you should also be able to do: >>>> >>>> (setf (plist-get auth-data :secret) access-token) >>>> >>> >>> Ah didn't know this as I learned the usage of plist-put from searching. >>> Changed to your `setq' version. Though I'd also expect that the side >>> effect is not going away anytime soon either ;) >> >> I am not sure what you mean? The crux of the issue is demonstrated >> here: >> >> (let (plist) >> (list (plist-put plist :foo 1) plist)) >> ;; ((:foo 1) nil) >> >> I.e. the plist was not modified, because there was no cons-cell to >> modify. >> > > I see. Thanks for the explanation. Looks like the side effect worked > for me because auth-data already had data in it. Probably, but that's not the kind of thing I want to rely on. >> >> [...] >> >>>>> #'auth-source-xoauth2-plugin--search-backends)) >>>> >>>> I would recommend turning this into a global minor mode instead, so that >>>> it is easy to disable, if a user just wants to try it out. >>>> >>> >>> This is an interesting suggestion and sounds like a good idea. Though >>> as a matter of fact the oauth2 support in auth-source in Emacs core >>> actually doesn't work without those hack as of now, so I don't think >>> it's of interest to support turning off. >> >> I regard it as a matter of good style to allow the user to disable >> anything then can enable, if anything then just to allow better >> experimentation. >> > > You actually convinced me. Making it a minor mode also enables a user > to disable it temporarily if it causes any issues. It took me a while > to convert it. Please help take another look. Looks good. >>> But of course it would be >>> great if auth-source can be changed to support all this out-of-the-box. >>> Will continue the discussion in my reply to Stefan. >> >> Ack. >> >>> I have updated the source code on GitLab[1] based on your review. >>> Please check it out. Thanks very much! >> >> For anyone following the thread, it seem the footnote was missing: >> >> [1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el >> >> Watch out, in >> >> (unless (memq 'xoauth2 smtpmail-auth-supported) >> (push 'smtpmail-auth-supported 'xoauth2)) >> >> the push expression is malformed, as 'xoauth2 is not a place. I'm >> guessing that you want to write >> >> (... (push 'xoauth2 smtpmail-auth-supported)) >> > > Thanks! Fixed. > >> Also, checkdoc complains about >> `auth-source-xoauth2-plugin--search-backends's docstring. I'd try to >> address the issues it mentions. >> > > Also fixed. Thanks! > >> The (and auth (equal auth "xoauth2")) can be further simplified to just >> (equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil. >> > > Ack and simplified. > > The GitLab repo[1] is updated accordingly. PTAL. TIA! Looks good, just a few "soft" comments I can find: [-- Attachment #2: Type: text/plain, Size: 2746 bytes --] diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el index cdcc9e7..caf5baf 100644 --- a/auth-source-xoauth2-plugin.el +++ b/auth-source-xoauth2-plugin.el @@ -41,7 +41,7 @@ ;; or with use-package: ;; (use-package auth-source-xoauth2-plugin -;; :config +;; :custom ;; (auth-source-xoauth2-plugin-mode t)) ;; After enabling, smtpmail should be supported. To enable this in Gnus @@ -107,13 +107,13 @@ expected that `token_url', `client_id', `client_secret', and (when (equal auth "xoauth2") (auth-source-do-debug ":auth set to `xoauth2'. Will get access token.") - (map-let ((:auth-url auth-url) - (:token-url token-url) - (:scope scope) - (:client-id client-id) - (:client-secret client-secret) - (:redirect-uri redirect-uri) - (:state state)) + (map-let (:auth-url ;You can simplify the `map-let' + :token-url ;expression if they keys match + :scope ;the bindings like they do here. + :client-id ;Perhaps you can use the additional + :client-secret ;space to document what the keys + :redirect-uri ;are for? + :state) auth-data (auth-source-do-debug "Using oauth2 to auth and store token...") (let ((token (oauth2-auth-and-store @@ -138,8 +138,7 @@ expected that `token_url', `client_id', `client_secret', and res))) (defvar auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil - "Used for tracking whether xoauth2 in smtpmail-auth-supported is -set by us.") + "Non-nil means `smtpmail-auth-supported' was set by us.") (defun auth-source-xoauth2-plugin--enable () "Enable auth-source-xoauth2-plugin." @@ -154,17 +153,17 @@ set by us.") "Disable auth-source-xoauth2-plugin." (when (and auth-source-xoauth2-plugin--enabled-xoauth2-by-us (memq 'xoauth2 smtpmail-auth-supported)) - (delete 'xoauth2 smtpmail-auth-supported) + (setq smtpmail-auth-supported (delq 'xoauth2 smtpmail-auth-supported)) (setq auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil)) (advice-remove #'auth-source-search-backends #'auth-source-xoauth2-plugin--search-backends)) +;;;###autoload (define-minor-mode auth-source-xoauth2-plugin-mode "Toggle auth-source-xoauth2-plugin-mode. Enable auth-source-xoauth2-plugin-mode to use xoauth2 authentications for emails." - :lighter nil :global t (if auth-source-xoauth2-plugin-mode (auth-source-xoauth2-plugin--enable) [-- Attachment #3: Type: text/plain, Size: 296 bytes --] > >>>>> >>>>> (provide 'auth-source-xoauth2-plugin) >>>>> >>>>> ;;; auth-source-xoauth2-plugin.el ends here >>>> >>>> -- >>>> Philip Kaludercic on siskin >> >> -- >> Philip Kaludercic on siskin > > [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin -- Philip Kaludercic on siskin ^ permalink raw reply related [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-22 9:34 ` Philip Kaludercic @ 2024-09-22 22:00 ` Xiyue Deng 2024-09-23 6:17 ` Philip Kaludercic 0 siblings, 1 reply; 26+ messages in thread From: Xiyue Deng @ 2024-09-22 22:00 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 72992 Philip Kaludercic <philipk@posteo.net> writes: > Xiyue Deng <manphiz@gmail.com> writes: > >> Hi Philip, >> >> Philip Kaludercic <philipk@posteo.net> writes: >> >>> Xiyue Deng <manphiz@gmail.com> writes: >>> >>>> Philip Kaludercic <philipk@posteo.net> writes: >>>> >>>>> Xiyue Deng <manphiz@gmail.com> writes: >>>>> >>>>>> Now that bug#72358 is done, as promised, I'm posting my plugin for >>>>>> auth-sources that enables oauth2 handling which you can find on >>>>>> Gitlab[1] (also attached). >>>>> >>>>> Once again I just want to be sure: When you say "plugin", you mean >>>>> package, right? >>>> >>>> Yes, though it's not really an independent package but a "plugin" for >>>> auth-source, a.k.a. a hack (the advice) to make auth-source to work with >>>> xoauth2. >>> >>> Just to clarify: When I say package, I mean something to add to ELPA. >>> >> >> Ah in that regard yes. >> >>>>> You are proposing to add this to GNU ELPA? >>>> >>>> Actually I would like to see which of my proposed changes to auth-source >>>> is acceptable and update auth-source in core accordingly. >>> >>> Sure it's acceptable, but in that case it would better to submit a patch >>> modifying. auth-source.el >>> >>>> I think >>>> Stefan's reply gave some suggestions in this regard and I'll follow-up >>>> in a reply there. >>> >>> I just want to second Stefan's point that some clarification as to what >>> xoauth2 is. >>> >> >> Updated the comments section with this info. > > Great, that explains it well! > >>>> Meanwhile, it may still worth adding this package >>>> to ELPA to support older Emacs versions if desired. >>> >>> In that case it might be better not to merge your changes into >>> auth-source.el directly, as that would make it more difficult to >>> automatically pull your changes out of the core to ELPA. >>> >>> An alternative is that ELPA mirrors your repository, and then we >>> manually synchronise the changes into the core, whenever there is a new >>> release. >>> >> >> I was thinking making it only for Emacs <30 if the auth-source side >> changes are upstreamed for 31. Similar to "docker-tramp" which is only >> for EMacs <28. > > The issue here is that tramp is developed outside of Emacs and > synchronised manually back into the core/automatically on ELPA, while > auth-source is currently only in the core and not distributed on ELPA. > If this remains a separate file, we could easily add it to ELPA, but I > don't know what the preference is there. > >>> >>> [...] >>> >>>>>> (let ((auth (plist-get auth-data :auth))) >>>>>> (when (and auth >>>>>> (stringp auth) >>>>>> (string= auth "xoauth2")) >>>>> >>>>> You can simplify the check by just doing (equal auth "xoauth2"), as this >>>>> implies all of the above (if it is `equal' to a string, it must be a >>>>> string and hence also non-nil). >>>>> >>>> >>>> Done. Nice tip! Coming from strong-typed languages I always want to do >>>> type-checks first in fear of any aborting error :) >>> >>> If you want strong typing, then string= is the right thing to use, >>> because if you want to assume that auth is always a string, then an >>> error will be signalled. That being said, if auth has the type "Maybe >>> String", then checking the values explicitly or implicitly using equal >>> is the right approach. >>> >> >> Ack. Thanks for the tip! >> >>> >>> [...] >>> >>>>>> (auth-source-do-trivia "Using oauth2 to auth and store token...") >>>>>> (let ((token (oauth2-auth-and-store >>>>>> auth-url token-url scope client-id client-secret >>>>>> redirect-uri state))) >>>>>> (auth-source-do-trivia "oauth2 token: %s" (pp-to-string token)) >>>>>> (auth-source-do-trivia "Refreshing token...") >>>>>> (oauth2-refresh-access token) >>>>>> (auth-source-do-trivia "oauth2 token after refresh: %s" >>>>>> (pp-to-string token)) >>>>>> (let ((access-token (oauth2-token-access-token token))) >>>>>> (auth-source-do-trivia >>>>>> "Updating :secret with access-token: %s" access-token) >>>>>> (plist-put auth-data :secret access-token)))))) >>>>> >>>>> The documentation for plist-put warns: >>>>> >>>>> The new plist is returned; >>>>> use ‘(setq x (plist-put x prop val))’ to be sure to use the new value. >>>>> The PLIST is modified by side effects. >>>>> >>>>> Alternatively, you should also be able to do: >>>>> >>>>> (setf (plist-get auth-data :secret) access-token) >>>>> >>>> >>>> Ah didn't know this as I learned the usage of plist-put from searching. >>>> Changed to your `setq' version. Though I'd also expect that the side >>>> effect is not going away anytime soon either ;) >>> >>> I am not sure what you mean? The crux of the issue is demonstrated >>> here: >>> >>> (let (plist) >>> (list (plist-put plist :foo 1) plist)) >>> ;; ((:foo 1) nil) >>> >>> I.e. the plist was not modified, because there was no cons-cell to >>> modify. >>> >> >> I see. Thanks for the explanation. Looks like the side effect worked >> for me because auth-data already had data in it. > > Probably, but that's not the kind of thing I want to rely on. > Ack. >>> >>> [...] >>> >>>>>> #'auth-source-xoauth2-plugin--search-backends)) >>>>> >>>>> I would recommend turning this into a global minor mode instead, so that >>>>> it is easy to disable, if a user just wants to try it out. >>>>> >>>> >>>> This is an interesting suggestion and sounds like a good idea. Though >>>> as a matter of fact the oauth2 support in auth-source in Emacs core >>>> actually doesn't work without those hack as of now, so I don't think >>>> it's of interest to support turning off. >>> >>> I regard it as a matter of good style to allow the user to disable >>> anything then can enable, if anything then just to allow better >>> experimentation. >>> >> >> You actually convinced me. Making it a minor mode also enables a user >> to disable it temporarily if it causes any issues. It took me a while >> to convert it. Please help take another look. > > Looks good. > >>>> But of course it would be >>>> great if auth-source can be changed to support all this out-of-the-box. >>>> Will continue the discussion in my reply to Stefan. >>> >>> Ack. >>> >>>> I have updated the source code on GitLab[1] based on your review. >>>> Please check it out. Thanks very much! >>> >>> For anyone following the thread, it seem the footnote was missing: >>> >>> [1]https://gitlab.com/xiyueden/auth-source-xoauth2-plugin/-/blob/main/auth-source-xoauth2-plugin.el >>> >>> Watch out, in >>> >>> (unless (memq 'xoauth2 smtpmail-auth-supported) >>> (push 'smtpmail-auth-supported 'xoauth2)) >>> >>> the push expression is malformed, as 'xoauth2 is not a place. I'm >>> guessing that you want to write >>> >>> (... (push 'xoauth2 smtpmail-auth-supported)) >>> >> >> Thanks! Fixed. >> >>> Also, checkdoc complains about >>> `auth-source-xoauth2-plugin--search-backends's docstring. I'd try to >>> address the issues it mentions. >>> >> >> Also fixed. Thanks! >> >>> The (and auth (equal auth "xoauth2")) can be further simplified to just >>> (equal auth "xauth2"), as if auth is equal to "xauth2" is cannot be nil. >>> >> >> Ack and simplified. >> >> The GitLab repo[1] is updated accordingly. PTAL. TIA! > > Looks good, just a few "soft" comments I can find: > > diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el > index cdcc9e7..caf5baf 100644 > --- a/auth-source-xoauth2-plugin.el > +++ b/auth-source-xoauth2-plugin.el > @@ -41,7 +41,7 @@ > ;; or with use-package: > > ;; (use-package auth-source-xoauth2-plugin > -;; :config > +;; :custom > ;; (auth-source-xoauth2-plugin-mode t)) > Quick question: I wonder whether customizing the minor mode variable is preferred over toggling through the minor mode function? (I assume both will run the minor mode body.) > ;; After enabling, smtpmail should be supported. To enable this in Gnus > @@ -107,13 +107,13 @@ expected that `token_url', `client_id', `client_secret', and > (when (equal auth "xoauth2") > (auth-source-do-debug > ":auth set to `xoauth2'. Will get access token.") > - (map-let ((:auth-url auth-url) > - (:token-url token-url) > - (:scope scope) > - (:client-id client-id) > - (:client-secret client-secret) > - (:redirect-uri redirect-uri) > - (:state state)) > + (map-let (:auth-url ;You can simplify the `map-let' > + :token-url ;expression if they keys match > + :scope ;the bindings like they do here. > + :client-id ;Perhaps you can use the additional > + :client-secret ;space to document what the keys > + :redirect-uri ;are for? > + :state) > auth-data > (auth-source-do-debug "Using oauth2 to auth and store token...") > (let ((token (oauth2-auth-and-store > @@ -138,8 +138,7 @@ expected that `token_url', `client_id', `client_secret', and > res))) > > (defvar auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil > - "Used for tracking whether xoauth2 in smtpmail-auth-supported is > -set by us.") > + "Non-nil means `smtpmail-auth-supported' was set by us.") > > (defun auth-source-xoauth2-plugin--enable () > "Enable auth-source-xoauth2-plugin." > @@ -154,17 +153,17 @@ set by us.") > "Disable auth-source-xoauth2-plugin." > (when (and auth-source-xoauth2-plugin--enabled-xoauth2-by-us > (memq 'xoauth2 smtpmail-auth-supported)) > - (delete 'xoauth2 smtpmail-auth-supported) > + (setq smtpmail-auth-supported (delq 'xoauth2 smtpmail-auth-supported)) > (setq auth-source-xoauth2-plugin--enabled-xoauth2-by-us nil)) > > (advice-remove #'auth-source-search-backends > #'auth-source-xoauth2-plugin--search-backends)) > > +;;;###autoload > (define-minor-mode auth-source-xoauth2-plugin-mode > "Toggle auth-source-xoauth2-plugin-mode. > Enable auth-source-xoauth2-plugin-mode to use xoauth2 > authentications for emails." > - :lighter nil > :global t > (if auth-source-xoauth2-plugin-mode > (auth-source-xoauth2-plugin--enable) > >> >>>>>> >>>>>> (provide 'auth-source-xoauth2-plugin) >>>>>> >>>>>> ;;; auth-source-xoauth2-plugin.el ends here >>>>> >>>>> -- >>>>> Philip Kaludercic on siskin >>> >>> -- >>> Philip Kaludercic on siskin >> >> [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin > > -- > Philip Kaludercic on siskin -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-22 22:00 ` Xiyue Deng @ 2024-09-23 6:17 ` Philip Kaludercic 2024-09-23 6:39 ` Xiyue Deng 0 siblings, 1 reply; 26+ messages in thread From: Philip Kaludercic @ 2024-09-23 6:17 UTC (permalink / raw) To: Xiyue Deng; +Cc: 72992 Xiyue Deng <manphiz@gmail.com> writes: [...] >> diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el >> index cdcc9e7..caf5baf 100644 >> --- a/auth-source-xoauth2-plugin.el >> +++ b/auth-source-xoauth2-plugin.el >> @@ -41,7 +41,7 @@ >> ;; or with use-package: >> >> ;; (use-package auth-source-xoauth2-plugin >> -;; :config >> +;; :custom >> ;; (auth-source-xoauth2-plugin-mode t)) >> > > Quick question: I wonder whether customizing the minor mode variable is > preferred over toggling through the minor mode function? (I assume both > will run the minor mode body.) You are right, it doesn't matter. I changed this when adding the autoload cookie, and somehow I had convinced myself that this would only work as a user option, which of course is not the case. [...] -- Philip Kaludercic on siskin ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-23 6:17 ` Philip Kaludercic @ 2024-09-23 6:39 ` Xiyue Deng 0 siblings, 0 replies; 26+ messages in thread From: Xiyue Deng @ 2024-09-23 6:39 UTC (permalink / raw) To: Philip Kaludercic; +Cc: 72992 Philip Kaludercic <philipk@posteo.net> writes: > Xiyue Deng <manphiz@gmail.com> writes: > > > [...] > >>> diff --git a/auth-source-xoauth2-plugin.el b/auth-source-xoauth2-plugin.el >>> index cdcc9e7..caf5baf 100644 >>> --- a/auth-source-xoauth2-plugin.el >>> +++ b/auth-source-xoauth2-plugin.el >>> @@ -41,7 +41,7 @@ >>> ;; or with use-package: >>> >>> ;; (use-package auth-source-xoauth2-plugin >>> -;; :config >>> +;; :custom >>> ;; (auth-source-xoauth2-plugin-mode t)) >>> >> >> Quick question: I wonder whether customizing the minor mode variable is >> preferred over toggling through the minor mode function? (I assume both >> will run the minor mode body.) > > You are right, it doesn't matter. I changed this when adding the > autoload cookie, and somehow I had convinced myself that this would only > work as a user option, which of course is not the case. Thanks for confirming! I have incorporated your suggestions and pushed to my repo. Thanks again for your review! > > [...] > > > -- > Philip Kaludercic on siskin -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-02 8:34 bug#72992: 29.4; towards xoauth2 support in Emacs Xiyue Deng [not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org> 2024-09-17 19:12 ` Philip Kaludercic @ 2024-09-17 21:33 ` Stefan Kangas 2024-09-18 19:43 ` Xiyue Deng 2 siblings, 1 reply; 26+ messages in thread From: Stefan Kangas @ 2024-09-17 21:33 UTC (permalink / raw) To: Xiyue Deng, 72992; +Cc: Ted Zlatanov Xiyue Deng <manphiz@gmail.com> writes: > Now that bug#72358 is done, as promised, I'm posting my plugin for > auth-sources that enables oauth2 handling which you can find on > Gitlab[1] (also attached). As the current approach tries to override > some existing handling in auth-source, I would like to gather some > comments on how to properly integrate this handling, and see if there is > any benefit on providing this as a separate package for older Emacs > versions. > > In the comment section of the package I put notes on how xoauth2 is > enabled as well as existing restrictions in auth-source and how it > workarounds them. I'll briefly explain below. I think it would be good if you could add to your package some general explanation of what xoauth2 is, and what are its use cases both in a general sense, and specifically together with the auth-source package. Don't assume that people already know what xoauth2 is, how it is different from oauth2, which services use it, etc. Explain it. I would add such general information to the beginning of the "Commentary" section. Nothing long is needed, just a general introduction and perhaps links for where to read more. Some examples of when it would be used, preferably with example code for some use cases, would also go a long way. > Currently, auth-source search requires that the result include `:secret' > most of the time, where when using xoauth2 it is actually the > access-token. Actually, auth-source has existing support for xoauth2 > authentication, though it assumes that the password value actually > stores the access-token. Where can we find this "existing support"? Do you mean the 'auth-source-xoauth2' package on GNU ELPA? > Because xoauth2 also makes use of > `secret'/`password', it makes it hard to determine whether to use > password-based or xoauth2-based authentication, which is why my plugin > asks users to set `auth' in auth-source to determine whether to use > xoauth2. Another complication from this is that auth-source search > requires the entry contains a `secret' most of the time, where it does > not need to be set when using xoauth2. Therefore I workaround this by > temporarily disables this check and try to retrieve access-token using > oauth2 and set the result as password. > > Given the inconveniences of reusing password for access-token, I wonder > whether we can add support for a separate `:access-token' key in the > auth-source entry and use that instead of password when authenticating > using xoauth2. This way, we can have both password and access-token in > an auth-source entry and nnimap and smtpmail can use either one. More > specifically: > > * When performing an auth-source search, if xoauth2 related fields are > set (see the list of fields in the comments of my plugin), it will > retrieve access-token using oauth2. > > * The search should change to check for either `secret'/`password' or > `access-token' is available. > > * For `nnimap-login' and `smtpmail-try-auth-method', pass in both > password and access-token, and for xoauth2 it should use access-token > instead of password. > > If this is an acceptable approach, I'll try to draft a patch to > implement this in Emacs. Otherwise, it may still worth implement the > current approach directly in Emacs so as to avoid using hack like > advice. I'm not very familiar with auth-source.el, but on a general level the above makes sense to me. I've also Cc:ed Ted Zlatanov, the author of auth-source.el > Meanwhile, I wonder whether this may be worth release as a separate > package so that users of older versions can use xoauth2 as well. I'd > like to make it compatible with the agreed-upon approach to minimize any > incompatibilities. > > Thanks for reading, and any comments are appreciated. Are you proposing to include this in Emacs core, on GNU ELPA, or something else? Thanks. > [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-17 21:33 ` Stefan Kangas @ 2024-09-18 19:43 ` Xiyue Deng 2024-09-19 5:13 ` Andrew Cohen 0 siblings, 1 reply; 26+ messages in thread From: Xiyue Deng @ 2024-09-18 19:43 UTC (permalink / raw) To: Stefan Kangas, 72992; +Cc: Ted Zlatanov, Philip Kaludercic Hi Stefan, Stefan Kangas <stefankangas@gmail.com> writes: > Xiyue Deng <manphiz@gmail.com> writes: > >> Now that bug#72358 is done, as promised, I'm posting my plugin for >> auth-sources that enables oauth2 handling which you can find on >> Gitlab[1] (also attached). As the current approach tries to override >> some existing handling in auth-source, I would like to gather some >> comments on how to properly integrate this handling, and see if there is >> any benefit on providing this as a separate package for older Emacs >> versions. >> >> In the comment section of the package I put notes on how xoauth2 is >> enabled as well as existing restrictions in auth-source and how it >> workarounds them. I'll briefly explain below. > > I think it would be good if you could add to your package some general > explanation of what xoauth2 is, and what are its use cases both in a > general sense, and specifically together with the auth-source > package. Don't assume that people already know what xoauth2 is, how it > is different from oauth2, which services use it, etc. Explain it. I > would add such general information to the beginning of the "Commentary" > section. Nothing long is needed, just a general introduction and perhaps > links for where to read more. > Good suggestions. Added to the comments part. > Some examples of when it would be used, preferably with example code for > some use cases, would also go a long way. > I have added some examples on how to set it up and use it in Gnus and smtpmail after sending the earlier version. Please check it out at [1] (with the changes above.) >> Currently, auth-source search requires that the result include `:secret' >> most of the time, where when using xoauth2 it is actually the >> access-token. Actually, auth-source has existing support for xoauth2 >> authentication, though it assumes that the password value actually >> stores the access-token. > > Where can we find this "existing support"? Do you mean the > 'auth-source-xoauth2' package on GNU ELPA? > The basic support is actually in the Emacs core already, e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes one to put the access_token in place of `:secret' in the auth-source file as Emacs uses password as the access_token in both places. However, access_token expires quite frequently (e.g. about 1 hour for Gmail) and without refreshing it automatically it is practically impossible to use conveniently. Hence the propose hack and the following suggestion. >> Because xoauth2 also makes use of >> `secret'/`password', it makes it hard to determine whether to use >> password-based or xoauth2-based authentication, which is why my plugin >> asks users to set `auth' in auth-source to determine whether to use >> xoauth2. Another complication from this is that auth-source search >> requires the entry contains a `secret' most of the time, where it does >> not need to be set when using xoauth2. Therefore I workaround this by >> temporarily disables this check and try to retrieve access-token using >> oauth2 and set the result as password. >> >> Given the inconveniences of reusing password for access-token, I wonder >> whether we can add support for a separate `:access-token' key in the >> auth-source entry and use that instead of password when authenticating >> using xoauth2. This way, we can have both password and access-token in >> an auth-source entry and nnimap and smtpmail can use either one. More >> specifically: >> >> * When performing an auth-source search, if xoauth2 related fields are >> set (see the list of fields in the comments of my plugin), it will >> retrieve access-token using oauth2. >> >> * The search should change to check for either `secret'/`password' or >> `access-token' is available. >> >> * For `nnimap-login' and `smtpmail-try-auth-method', pass in both >> password and access-token, and for xoauth2 it should use access-token >> instead of password. >> >> If this is an acceptable approach, I'll try to draft a patch to >> implement this in Emacs. Otherwise, it may still worth implement the >> current approach directly in Emacs so as to avoid using hack like >> advice. > > I'm not very familiar with auth-source.el, but on a general level the > above makes sense to me. I've also Cc:ed Ted Zlatanov, the author of > auth-source.el > Thanks! Would also like to hear Ted's opinion on this and decide which route to take. >> Meanwhile, I wonder whether this may be worth release as a separate >> package so that users of older versions can use xoauth2 as well. I'd >> like to make it compatible with the agreed-upon approach to minimize any >> incompatibilities. >> >> Thanks for reading, and any comments are appreciated. > > Are you proposing to include this in Emacs core, on GNU ELPA, or > something else? > I'd like to contribute to Emacs core once a direction is decided. Maybe also put this plugin in ELPA to support older emacs versions if both are compatible. > Thanks. > [1] https://gitlab.com/xiyueden/auth-source-xoauth2-plugin [2] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/gnus/nnimap.el#n616 [3] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/mail/smtpmail.el#n640 -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-18 19:43 ` Xiyue Deng @ 2024-09-19 5:13 ` Andrew Cohen 2024-09-19 8:22 ` Xiyue Deng 0 siblings, 1 reply; 26+ messages in thread From: Andrew Cohen @ 2024-09-19 5:13 UTC (permalink / raw) To: Xiyue Deng; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas >>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes: XD> Hi Stefan, Stefan Kangas <stefankangas@gmail.com> writes: >> Xiyue Deng <manphiz@gmail.com> writes: >> [...] >>> Currently, auth-source search requires that the result include >>> `:secret' most of the time, where when using xoauth2 it is >>> actually the access-token. Actually, auth-source has existing >>> support for xoauth2 authentication, though it assumes that the >>> password value actually stores the access-token. >> >> Where can we find this "existing support"? Do you mean the >> 'auth-source-xoauth2' package on GNU ELPA? >> XD> The basic support is actually in the Emacs core already, XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes XD> one to put the access_token in place of `:secret' in the XD> auth-source file as Emacs uses password as the access_token in XD> both places. However, access_token expires quite frequently XD> (e.g. about 1 hour for Gmail) and without refreshing it XD> automatically it is practically impossible to use conveniently. XD> Hence the propose hack and the following suggestion. This isn't actually true. When I added the support many years ago, I updated auth-source so that the :secret field can be a function, and this is how you should be using the current xoauth support. On the bug thread I posted a suitable function that handles token refreshing (and its on my list of changes to emacs that I expect to push at some point). So everything necessary to use xoauth for nnimap and smtpmail with auth-source, including automatic token refreshing, is already present in emacs. Having said that, I think some of the ideas in Xiyue's code would be useful. However I think it would be best to base this on the existing code which works very well and is in use by at least me (and I think some others as well). Best, Andy -- Andrew Cohen ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-19 5:13 ` Andrew Cohen @ 2024-09-19 8:22 ` Xiyue Deng 2024-09-19 9:06 ` Andrew Cohen 0 siblings, 1 reply; 26+ messages in thread From: Xiyue Deng @ 2024-09-19 8:22 UTC (permalink / raw) To: Andrew Cohen; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas Hi Andrew, Andrew Cohen <acohen@ust.hk> writes: >>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes: > > XD> Hi Stefan, Stefan Kangas <stefankangas@gmail.com> writes: > > >> Xiyue Deng <manphiz@gmail.com> writes: > >> > > [...] > > > >>> Currently, auth-source search requires that the result include > >>> `:secret' most of the time, where when using xoauth2 it is > >>> actually the access-token. Actually, auth-source has existing > >>> support for xoauth2 authentication, though it assumes that the > >>> password value actually stores the access-token. > >> > >> Where can we find this "existing support"? Do you mean the > >> 'auth-source-xoauth2' package on GNU ELPA? > >> > > XD> The basic support is actually in the Emacs core already, > XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes > XD> one to put the access_token in place of `:secret' in the > XD> auth-source file as Emacs uses password as the access_token in > XD> both places. However, access_token expires quite frequently > XD> (e.g. about 1 hour for Gmail) and without refreshing it > XD> automatically it is practically impossible to use conveniently. > XD> Hence the propose hack and the following suggestion. > > > This isn't actually true. When I added the support many years ago, I > updated auth-source so that the :secret field can be a function, and > this is how you should be using the current xoauth support. Thanks for pointing this out! I found the place where `:secret' is handled as a function[1]. However, this requires a user to implement the oauth2 logic oneself, which I'm afraid is a bit too low-level and error-prone. (Actually, can I actually put a lisp function in auth-source.gpg?) Maybe auth-source source can host a helper function that checks if `:secret' is not set and xaouth2 is preferred (e.g. `:auth' is `xoauth2') and all required credentials are available it will get the access_token and put it `:secret' (or basically my hacky advice :) > On the bug thread I posted a suitable function that handles token > refreshing (and its on my list of changes to emacs that I expect to > push at some point). So everything necessary to use xoauth for nnimap > and smtpmail with auth-source, including automatic token refreshing, > is already present in emacs. > > Having said that, I think some of the ideas in Xiyue's code would be > useful. However I think it would be best to base this on the existing > code which works very well and is in use by at least me (and I think > some others as well). > Just remembered your comment in Bug#72358[2]. And of course if your proposals can be part of auth-source that would be great for the users. Still would be great to have a unified plan and make it happen. P.S. Is your set up mentioned in Bug#72358 still working for outlook.com emails? After reaching out to an MS representative they mentioned that token refresh was disabled[3] for outlook.com so I just gave up. Maybe it still works for Outlook Org emails? > Best, > Andy > > > -- > Andrew Cohen [1] https://git.savannah.gnu.org/cgit/emacs.git/tree/lisp/auth-source.el#n872 [2] https://debbugs.gnu.org/cgi/bugreport.cgi?bug=72358#47 [3] https://stackoverflow.com/questions/78787763/getting-aadsts65001-error-invalid-grant-when-trying-to-refresh-access-token-fo -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-19 8:22 ` Xiyue Deng @ 2024-09-19 9:06 ` Andrew Cohen 2024-09-19 22:37 ` Xiyue Deng ` (2 more replies) 0 siblings, 3 replies; 26+ messages in thread From: Andrew Cohen @ 2024-09-19 9:06 UTC (permalink / raw) To: Xiyue Deng; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas >>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes: XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes: >>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes: >> [...] XD> The basic support is actually in the Emacs core already, XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes XD> one to put the access_token in place of `:secret' in the XD> auth-source file as Emacs uses password as the access_token in XD> both places. However, access_token expires quite frequently XD> (e.g. about 1 hour for Gmail) and without refreshing it XD> automatically it is practically impossible to use conveniently. XD> Hence the propose hack and the following suggestion. >> >> >> This isn't actually true. When I added the support many years >> ago, I updated auth-source so that the :secret field can be a >> function, and this is how you should be using the current xoauth >> support. XD> Thanks for pointing this out! I found the place where `:secret' XD> is handled as a function[1]. However, this requires a user to XD> implement the oauth2 logic oneself, which I'm afraid is a bit XD> too low-level and error-prone. (Actually, can I actually put a XD> lisp function in auth-source.gpg?) I don't think you have to do anything low level, and I don't think there is anything error prone here; you can use the functions from oauth themselves (oauth2.el can create its own plstores, but I prefer to use auth-source.el to manage the stores). The only things needed are a call to oauth2-refresh-access to get a new token, and then oauth2-token-access-token to return the new access token. The function I wrote computes the refresh time to decide when to create a new token. This logic could easily be put into oauth2 instead. And yes, you can put the lisp function in auth-source.gpg (this is what I do). By the way there are some significant bugs in auth-source.el which I have fixed in my personal tree but haven't yet pushed. I have so little time for emacs at the moment, but I'll try to get around to it. And there is one major deficiency in auth-source.el that I want to deal with: obfuscation of the :secret. When Ted originally wrote auth-source.el he wrapped the :secret in a closure so that the secret itself wasn't visible in memory. At the time he did this, closures weren't fully part of emacs, and their implementation at the time didn't expose the contents of the closure in bytecode. But the current official implementation does, so this obfuscation trick no longer works. I want to remove it since it no longer works and might lead to confusion. XD> Maybe auth-source source can host a helper function that checks XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth' XD> is `xoauth2') and all required credentials are available it will XD> get the access_token and put it `:secret' (or basically my hacky XD> advice :) I think this isn't the right way to go. Currently xoauth2 is one of several supported SASL methods. The logic is supposed to be to try them in a certain order, but this hasn't worked properly for some time. Nobody has noticed since almost everyone uses only the basic method. In gnus there has always been a server variable, nnimap-authenticator, that chooses the preferred sasl method, which is how the current support for xaouth2 is designed to work. I think this is the right way to handle this (rather than relying on some specific form of the auth-source entry) but it would be good to fix the logic in nnimap.el to allow multiple methods to be tried. [...] XD> P.S. Is your set up mentioned in Bug#72358 still working for XD> outlook.com emails? After reaching out to an MS representative XD> they mentioned that token refresh was disabled[3] for XD> outlook.com so I just gave up. Maybe it still works for Outlook XD> Org emails? Yes, it still works perfectly. I suspect that the information they gave you isn't fully accurate :) -- Andrew Cohen ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-19 9:06 ` Andrew Cohen @ 2024-09-19 22:37 ` Xiyue Deng 2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors ` (2 more replies) 2024-09-22 12:01 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com> 2 siblings, 3 replies; 26+ messages in thread From: Xiyue Deng @ 2024-09-19 22:37 UTC (permalink / raw) To: Andrew Cohen; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas Andrew Cohen <acohen@ust.hk> writes: >>>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes: > > XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes: > > >>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes: > >> > > [...] > > XD> The basic support is actually in the Emacs core already, > XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes > XD> one to put the access_token in place of `:secret' in the > XD> auth-source file as Emacs uses password as the access_token in > XD> both places. However, access_token expires quite frequently > XD> (e.g. about 1 hour for Gmail) and without refreshing it > XD> automatically it is practically impossible to use conveniently. > XD> Hence the propose hack and the following suggestion. > >> > >> > >> This isn't actually true. When I added the support many years > >> ago, I updated auth-source so that the :secret field can be a > >> function, and this is how you should be using the current xoauth > >> support. > > XD> Thanks for pointing this out! I found the place where `:secret' > XD> is handled as a function[1]. However, this requires a user to > XD> implement the oauth2 logic oneself, which I'm afraid is a bit > XD> too low-level and error-prone. (Actually, can I actually put a > XD> lisp function in auth-source.gpg?) > > I don't think you have to do anything low level, and I don't think there > is anything error prone here; you can use the functions from oauth > themselves (oauth2.el can create its own plstores, but I prefer to use > auth-source.el to manage the stores). The only things needed are a call > to oauth2-refresh-access to get a new token, and then > oauth2-token-access-token to return the new access token. > Yes, I'm not worried about power users. I just think that the average Emacs user would be hesitant on writing ELisp themselves to enable xoauth2 login (hence low-level), especially when they don't have anything to copy from (yet). Many Gnus users are not programmers and would prefer writing "(nnimap-authenticator 'xoauth2)" and expect it to work. But I believe you don't object providing that convenience OOTB either. > The function I wrote computes the refresh time to decide when to create > a new token. This logic could easily be put into oauth2 instead. > I am planning on adding this to oauth2 as well. Will ask for your review when that happens. > And yes, you can put the lisp function in auth-source.gpg (this is what > I do). > TIL! (I used to have a handwritten script to get the values for offlineimap. Guess we should all be using `auth-info-password') > By the way there are some significant bugs in auth-source.el which I > have fixed in my personal tree but haven't yet pushed. I have so little > time for emacs at the moment, but I'll try to get around to it. And > there is one major deficiency in auth-source.el that I want to deal > with: obfuscation of the :secret. When Ted originally wrote > auth-source.el he wrapped the :secret in a closure so that the secret > itself wasn't visible in memory. At the time he did this, closures > weren't fully part of emacs, and their implementation at the time didn't > expose the contents of the closure in bytecode. But the current official > implementation does, so this obfuscation trick no longer works. I want > to remove it since it no longer works and might lead to confusion. > Looking forward to it! > XD> Maybe auth-source source can host a helper function that checks > XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth' > XD> is `xoauth2') and all required credentials are available it will > XD> get the access_token and put it `:secret' (or basically my hacky > XD> advice :) > > I think this isn't the right way to go. Currently xoauth2 is one of > several supported SASL methods. The logic is supposed to be to try them > in a certain order, but this hasn't worked properly for some > time. Nobody has noticed since almost everyone uses only the basic > method. In gnus there has always been a server variable, > nnimap-authenticator, that chooses the preferred sasl method, which is > how the current support for xaouth2 is designed to work. I think this > is the right way to handle this (rather than relying on some specific > form of the auth-source entry) but it would be good to fix the logic in > nnimap.el to allow multiple methods to be tried. > Right. The `:auth' trick I did is just to workaround the restriction that `nnimap-login' chooses basic method over other methods, and I'd prefer a better built-in support in auth-source myself. As you mentioned, maybe it can be remodeled after `smtpmail-try-auth-method' to so that the login method is chosen on demand instead of trial-and-error. > [...] > > XD> P.S. Is your set up mentioned in Bug#72358 still working for > XD> outlook.com emails? After reaching out to an MS representative > XD> they mentioned that token refresh was disabled[3] for > XD> outlook.com so I just gave up. Maybe it still works for Outlook > XD> Org emails? > > Yes, it still works perfectly. I suspect that the information they gave > you isn't fully accurate :) Thanks for confirming! I'll follow-up in private to try to figure this out if you don't mind. > -- > Andrew Cohen -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-19 22:37 ` Xiyue Deng @ 2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com> 2024-10-03 22:41 ` Xiyue Deng 2 siblings, 0 replies; 26+ messages in thread From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-22 12:05 UTC (permalink / raw) To: Xiyue Deng Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic, Stefan Kangas Xiyue Deng <manphiz@gmail.com> writes: >> [...] >> >> XD> P.S. Is your set up mentioned in Bug#72358 still working for >> XD> outlook.com emails? After reaching out to an MS representative >> XD> they mentioned that token refresh was disabled[3] for >> XD> outlook.com so I just gave up. Maybe it still works for Outlook >> XD> Org emails? >> >> Yes, it still works perfectly. I suspect that the information they gave >> you isn't fully accurate :) > > Thanks for confirming! I'll follow-up in private to try to figure this > out if you don't mind. Could you update me on this please too? We have an issue with this at work. ^ permalink raw reply [flat|nested] 26+ messages in thread
[parent not found: <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com>]
* bug#72992: 29.4; towards xoauth2 support in Emacs [not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com> @ 2024-09-22 21:40 ` Xiyue Deng 2024-09-22 23:50 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com> 0 siblings, 2 replies; 26+ messages in thread From: Xiyue Deng @ 2024-09-22 21:40 UTC (permalink / raw) To: Björn Bidar Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic, Stefan Kangas Hi Björn, Björn Bidar <bjorn.bidar@thaodan.de> writes: > Xiyue Deng <manphiz@gmail.com> writes: > >>> [...] >>> >>> XD> P.S. Is your set up mentioned in Bug#72358 still working for >>> XD> outlook.com emails? After reaching out to an MS representative >>> XD> they mentioned that token refresh was disabled[3] for >>> XD> outlook.com so I just gave up. Maybe it still works for Outlook >>> XD> Org emails? >>> >>> Yes, it still works perfectly. I suspect that the information they gave >>> you isn't fully accurate :) >> >> Thanks for confirming! I'll follow-up in private to try to figure this >> out if you don't mind. > > Could you update me on this please too? > We have an issue with this at work. I have reached out to Andrew offline and confirmed Andrew was using a corp account, so there might be some corp administration settings that enables the refreshing of access_token. It seems to me that this is still not possible for personal outlook.com accounts. -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-22 21:40 ` Xiyue Deng @ 2024-09-22 23:50 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com> 1 sibling, 0 replies; 26+ messages in thread From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-22 23:50 UTC (permalink / raw) To: Xiyue Deng Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic, Stefan Kangas Xiyue Deng <manphiz@gmail.com> writes: > Hi Björn, > > Björn Bidar <bjorn.bidar@thaodan.de> writes: > >> Xiyue Deng <manphiz@gmail.com> writes: >> >>>> [...] >>>> >>>> XD> P.S. Is your set up mentioned in Bug#72358 still working for >>>> XD> outlook.com emails? After reaching out to an MS representative >>>> XD> they mentioned that token refresh was disabled[3] for >>>> XD> outlook.com so I just gave up. Maybe it still works for Outlook >>>> XD> Org emails? >>>> >>>> Yes, it still works perfectly. I suspect that the information they gave >>>> you isn't fully accurate :) >>> >>> Thanks for confirming! I'll follow-up in private to try to figure this >>> out if you don't mind. >> >> Could you update me on this please too? >> We have an issue with this at work. > > I have reached out to Andrew offline and confirmed Andrew was using a > corp account, so there might be some corp administration settings that > enables the refreshing of access_token. It seems to me that this is > still not possible for personal outlook.com accounts. That matches my personal experience. Cooperate accounts are not on Outlook.com or are they? To bad I hope there would be some change, maybe someone should reach out to the EU or so. ^ permalink raw reply [flat|nested] 26+ messages in thread
[parent not found: <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com>]
* bug#72992: 29.4; towards xoauth2 support in Emacs [not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com> @ 2024-09-23 2:20 ` Xiyue Deng 0 siblings, 0 replies; 26+ messages in thread From: Xiyue Deng @ 2024-09-23 2:20 UTC (permalink / raw) To: Björn Bidar Cc: Andrew Cohen, Ted Zlatanov, 72992, Philip Kaludercic, Stefan Kangas Björn Bidar <bjorn.bidar@thaodan.de> writes: > Xiyue Deng <manphiz@gmail.com> writes: > >> Hi Björn, >> >> Björn Bidar <bjorn.bidar@thaodan.de> writes: >> >>> Xiyue Deng <manphiz@gmail.com> writes: >>> >>>>> [...] >>>>> >>>>> XD> P.S. Is your set up mentioned in Bug#72358 still working for >>>>> XD> outlook.com emails? After reaching out to an MS representative >>>>> XD> they mentioned that token refresh was disabled[3] for >>>>> XD> outlook.com so I just gave up. Maybe it still works for Outlook >>>>> XD> Org emails? >>>>> >>>>> Yes, it still works perfectly. I suspect that the information they gave >>>>> you isn't fully accurate :) >>>> >>>> Thanks for confirming! I'll follow-up in private to try to figure this >>>> out if you don't mind. >>> >>> Could you update me on this please too? >>> We have an issue with this at work. >> >> I have reached out to Andrew offline and confirmed Andrew was using a >> corp account, so there might be some corp administration settings that >> enables the refreshing of access_token. It seems to me that this is >> still not possible for personal outlook.com accounts. > > That matches my personal experience. Cooperate accounts are not on > Outlook.com or are they? > AIUI corp accounts usually have their own domain names, just the email system is operated by Outlook. > To bad I hope there would be some change, maybe someone should reach out > to the EU or so. OTOH, registered applications (e.g. thunderbird) can still login outlook.com emails through OAuth2, which also have full support for 2FA. Might worth taking a look at how they are doing it. -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-19 22:37 ` Xiyue Deng 2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com> @ 2024-10-03 22:41 ` Xiyue Deng 2024-10-08 13:38 ` Ted Zlatanov 2 siblings, 1 reply; 26+ messages in thread From: Xiyue Deng @ 2024-10-03 22:41 UTC (permalink / raw) To: Andrew Cohen; +Cc: Ted Zlatanov, Philip Kaludercic, 72992, Stefan Kangas Xiyue Deng <manphiz@gmail.com> writes: > Andrew Cohen <acohen@ust.hk> writes: > > [...] > >> By the way there are some significant bugs in auth-source.el which I >> have fixed in my personal tree but haven't yet pushed. I have so little >> time for emacs at the moment, but I'll try to get around to it. And >> there is one major deficiency in auth-source.el that I want to deal >> with: obfuscation of the :secret. When Ted originally wrote >> auth-source.el he wrapped the :secret in a closure so that the secret >> itself wasn't visible in memory. At the time he did this, closures >> weren't fully part of emacs, and their implementation at the time didn't >> expose the contents of the closure in bytecode. But the current official >> implementation does, so this obfuscation trick no longer works. I want >> to remove it since it no longer works and might lead to confusion. >> > > Looking forward to it! > Just want to follow up on this: may we try your fixes and maybe try to contribute for committing upstream? Also, for the :secret in closures, do you suggest to remove it or is there another up-to-date way to hide it in memory? >> XD> Maybe auth-source source can host a helper function that checks >> XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth' >> XD> is `xoauth2') and all required credentials are available it will >> XD> get the access_token and put it `:secret' (or basically my hacky >> XD> advice :) >> >> I think this isn't the right way to go. Currently xoauth2 is one of >> several supported SASL methods. The logic is supposed to be to try them >> in a certain order, but this hasn't worked properly for some >> time. Nobody has noticed since almost everyone uses only the basic >> method. In gnus there has always been a server variable, >> nnimap-authenticator, that chooses the preferred sasl method, which is >> how the current support for xaouth2 is designed to work. I think this >> is the right way to handle this (rather than relying on some specific >> form of the auth-source entry) but it would be good to fix the logic in >> nnimap.el to allow multiple methods to be tried. >> > > Right. The `:auth' trick I did is just to workaround the restriction > that `nnimap-login' chooses basic method over other methods, and I'd > prefer a better built-in support in auth-source myself. As you > mentioned, maybe it can be remodeled after `smtpmail-try-auth-method' to > so that the login method is chosen on demand instead of trial-and-error. > In this regard, is it desirable to make `auth-source-search-backends' a defgeneric acting on a given protocol (basic vs. xoauth2 vs. others), and similarly for `nnimap-login' et al.? >> [...] >> -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-10-03 22:41 ` Xiyue Deng @ 2024-10-08 13:38 ` Ted Zlatanov 2024-11-09 20:01 ` Xiyue Deng 0 siblings, 1 reply; 26+ messages in thread From: Ted Zlatanov @ 2024-10-08 13:38 UTC (permalink / raw) To: Xiyue Deng; +Cc: Andrew Cohen, Philip Kaludercic, 72992, Stefan Kangas On Thu, 03 Oct 2024 15:41:34 -0700 Xiyue Deng <manphiz@gmail.com> wrote: XD> Just want to follow up on this: may we try your fixes and maybe try to XD> contribute for committing upstream? Also, for the :secret in closures, XD> do you suggest to remove it or is there another up-to-date way to hide XD> it in memory? I think contributing the oauth2 support directly to Emacs is the best approach because it would help the greatest number of users without requiring extra configuration. I'd say modifying auth-source.el to fit the need is absolutely OK. I would just ask that if you modify the format of the authinfo file, to keep it compatible with JSON serialization for those of us that use an authinfo.json file. I'd prefer to find another way to hide the secrets if closures don't work anymore. I don't know if Emacs offers something; if not then we should make an effort to do it. But that effort should not block the oauth2 support, it's completely separate IMO. XD> Maybe auth-source source can host a helper function that checks XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth' XD> is `xoauth2') and all required credentials are available it will XD> get the access_token and put it `:secret' (or basically my hacky XD> advice :) Sure, if that makes the code easier. I think the important thing is just to make it compatible with the current usage and to avoid making the user customize things to make oauth2 support Just Work. XD> In this regard, is it desirable to make `auth-source-search-backends' a XD> defgeneric acting on a given protocol (basic vs. xoauth2 vs. others), XD> and similarly for `nnimap-login' et al.? I'm not sure if that would benefit the users. If it benefits the developers that's nice, but definitely not required, and especially if it changes the search API and can't be implemented in a compatible way. Because there may be a dozen packages on Github or whatever using that API, and updating all of them will be painful. Basically if the search API works right now, it's probably easier to leave it or make a new one and transition gradually. I hope this was helpful :) -- Ted Zlatanov <tzz@lifelogs.com> ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-10-08 13:38 ` Ted Zlatanov @ 2024-11-09 20:01 ` Xiyue Deng 0 siblings, 0 replies; 26+ messages in thread From: Xiyue Deng @ 2024-11-09 20:01 UTC (permalink / raw) To: Ted Zlatanov; +Cc: Andrew Cohen, Philip Kaludercic, 72992, Stefan Kangas [-- Attachment #1: Type: text/plain, Size: 2961 bytes --] Hi Ted, Ted Zlatanov <tzz@lifelogs.com> writes: > On Thu, 03 Oct 2024 15:41:34 -0700 Xiyue Deng <manphiz@gmail.com> wrote: > > XD> Just want to follow up on this: may we try your fixes and maybe try to > XD> contribute for committing upstream? Also, for the :secret in closures, > XD> do you suggest to remove it or is there another up-to-date way to hide > XD> it in memory? > > I think contributing the oauth2 support directly to Emacs is the best > approach because it would help the greatest number of users without > requiring extra configuration. I'd say modifying auth-source.el to fit > the need is absolutely OK. I would just ask that if you modify the > format of the authinfo file, to keep it compatible with JSON > serialization for those of us that use an authinfo.json file. > > I'd prefer to find another way to hide the secrets if closures don't > work anymore. I don't know if Emacs offers something; if not then we > should make an effort to do it. But that effort should not block the > oauth2 support, it's completely separate IMO. > > XD> Maybe auth-source source can host a helper function that checks > XD> if `:secret' is not set and xaouth2 is preferred (e.g. `:auth' > XD> is `xoauth2') and all required credentials are available it will > XD> get the access_token and put it `:secret' (or basically my hacky > XD> advice :) > > Sure, if that makes the code easier. I think the important thing is just > to make it compatible with the current usage and to avoid making the > user customize things to make oauth2 support Just Work. > > XD> In this regard, is it desirable to make `auth-source-search-backends' a > XD> defgeneric acting on a given protocol (basic vs. xoauth2 vs. others), > XD> and similarly for `nnimap-login' et al.? > > I'm not sure if that would benefit the users. If it benefits the > developers that's nice, but definitely not required, and especially if > it changes the search API and can't be implemented in a compatible way. > Because there may be a dozen packages on Github or whatever using that > API, and updating all of them will be painful. > > Basically if the search API works right now, it's probably easier to > leave it or make a new one and transition gradually. > > I hope this was helpful :) > > -- > Ted Zlatanov <tzz@lifelogs.com> It seems I completely missed your email, and sorry for that. I think your suggestions are very helpful: we should make oauth2 available for auth-source while keeping the existing interface. I think there are a few more things to do before that can happen: * Ship oauth2.el with Emacs, so that auth-source can make use of it. * Decide which sequence of credentials to try before giving up and throw an error. I wonder how hard it would be to make these happen. Since this thread is already very long, I'll probably file new bugs for tracking. Thanks again! -- Regards, Xiyue Deng [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 857 bytes --] ^ permalink raw reply [flat|nested] 26+ messages in thread
* bug#72992: 29.4; towards xoauth2 support in Emacs 2024-09-19 9:06 ` Andrew Cohen 2024-09-19 22:37 ` Xiyue Deng @ 2024-09-22 12:01 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com> 2 siblings, 0 replies; 26+ messages in thread From: Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2024-09-22 12:01 UTC (permalink / raw) To: Andrew Cohen Cc: Stefan Kangas, Ted Zlatanov, 72992, Philip Kaludercic, Xiyue Deng Andrew Cohen <acohen@ust.hk> writes: >>>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes: > > XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes: > > >>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes: > >> > > [...] > > XD> The basic support is actually in the Emacs core already, > XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes > XD> one to put the access_token in place of `:secret' in the > XD> auth-source file as Emacs uses password as the access_token in > XD> both places. However, access_token expires quite frequently > XD> (e.g. about 1 hour for Gmail) and without refreshing it > XD> automatically it is practically impossible to use conveniently. > XD> Hence the propose hack and the following suggestion. > >> > >> > >> This isn't actually true. When I added the support many years > >> ago, I updated auth-source so that the :secret field can be a > >> function, and this is how you should be using the current xoauth > >> support. > > XD> Thanks for pointing this out! I found the place where `:secret' > XD> is handled as a function[1]. However, this requires a user to > XD> implement the oauth2 logic oneself, which I'm afraid is a bit > XD> too low-level and error-prone. (Actually, can I actually put a > XD> lisp function in auth-source.gpg?) > > I don't think you have to do anything low level, and I don't think there > is anything error prone here; you can use the functions from oauth > themselves (oauth2.el can create its own plstores, but I prefer to use > auth-source.el to manage the stores). The only things needed are a call > to oauth2-refresh-access to get a new token, and then > oauth2-token-access-token to return the new access token. Is this documented? If yes where? I tried to look inside the auth manual nothing was mentioned. Would this method work with all backends? ^ permalink raw reply [flat|nested] 26+ messages in thread
[parent not found: <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com>]
* bug#72992: 29.4; towards xoauth2 support in Emacs [not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com> @ 2024-09-22 21:44 ` Xiyue Deng 0 siblings, 0 replies; 26+ messages in thread From: Xiyue Deng @ 2024-09-22 21:44 UTC (permalink / raw) To: Björn Bidar, Andrew Cohen Cc: Ted Zlatanov, 72992, Philip Kaludercic, Stefan Kangas Hi Björn, Björn Bidar <bjorn.bidar@thaodan.de> writes: > Andrew Cohen <acohen@ust.hk> writes: > >>>>>>> "XD" == Xiyue Deng <manphiz@gmail.com> writes: >> >> XD> Hi Andrew, Andrew Cohen <acohen@ust.hk> writes: >> >> >>>>>>> "XD" == Xiyue Deng <dengxiyue@gmail.com> writes: >> >> >> >> [...] >> >> XD> The basic support is actually in the Emacs core already, >> XD> e.g. for Gnus nnimap[2] and smtpmail[3]. However, this assumes >> XD> one to put the access_token in place of `:secret' in the >> XD> auth-source file as Emacs uses password as the access_token in >> XD> both places. However, access_token expires quite frequently >> XD> (e.g. about 1 hour for Gmail) and without refreshing it >> XD> automatically it is practically impossible to use conveniently. >> XD> Hence the propose hack and the following suggestion. >> >> >> >> >> >> This isn't actually true. When I added the support many years >> >> ago, I updated auth-source so that the :secret field can be a >> >> function, and this is how you should be using the current xoauth >> >> support. >> >> XD> Thanks for pointing this out! I found the place where `:secret' >> XD> is handled as a function[1]. However, this requires a user to >> XD> implement the oauth2 logic oneself, which I'm afraid is a bit >> XD> too low-level and error-prone. (Actually, can I actually put a >> XD> lisp function in auth-source.gpg?) >> >> I don't think you have to do anything low level, and I don't think there >> is anything error prone here; you can use the functions from oauth >> themselves (oauth2.el can create its own plstores, but I prefer to use >> auth-source.el to manage the stores). The only things needed are a call >> to oauth2-refresh-access to get a new token, and then >> oauth2-token-access-token to return the new access token. > > Is this documented? If yes where? > I tried to look inside the auth manual nothing was mentioned. > Would this method work with all backends? AIUI as of now you would need to implement this logic as a function in `:secret' of the auth-source entry. Please do correct me though. -- Xiyue Deng ^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2024-11-09 20:01 UTC | newest] Thread overview: 26+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-09-02 8:34 bug#72992: 29.4; towards xoauth2 support in Emacs Xiyue Deng [not found] ` <handler.72992.B.172532159013230.ack@debbugs.gnu.org> 2024-09-11 0:27 ` Xiyue Deng 2024-09-17 17:33 ` Xiyue Deng 2024-09-17 19:12 ` Philip Kaludercic 2024-09-18 6:24 ` Xiyue Deng 2024-09-18 14:11 ` Philip Kaludercic 2024-09-22 7:06 ` Xiyue Deng 2024-09-22 9:34 ` Philip Kaludercic 2024-09-22 22:00 ` Xiyue Deng 2024-09-23 6:17 ` Philip Kaludercic 2024-09-23 6:39 ` Xiyue Deng 2024-09-17 21:33 ` Stefan Kangas 2024-09-18 19:43 ` Xiyue Deng 2024-09-19 5:13 ` Andrew Cohen 2024-09-19 8:22 ` Xiyue Deng 2024-09-19 9:06 ` Andrew Cohen 2024-09-19 22:37 ` Xiyue Deng 2024-09-22 12:05 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f00802.050a0220.988f0.9640SMTPIN_ADDED_BROKEN@mx.google.com> 2024-09-22 21:40 ` Xiyue Deng 2024-09-22 23:50 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f0ad4f.500a0220.10c3c2.dde8SMTPIN_ADDED_BROKEN@mx.google.com> 2024-09-23 2:20 ` Xiyue Deng 2024-10-03 22:41 ` Xiyue Deng 2024-10-08 13:38 ` Ted Zlatanov 2024-11-09 20:01 ` Xiyue Deng 2024-09-22 12:01 ` Björn Bidar via Bug reports for GNU Emacs, the Swiss army knife of text editors [not found] ` <66f00712.170a0220.29d948.0047SMTPIN_ADDED_BROKEN@mx.google.com> 2024-09-22 21:44 ` Xiyue Deng
Code repositories for project(s) associated with this external index https://git.savannah.gnu.org/cgit/emacs.git https://git.savannah.gnu.org/cgit/emacs/org-mode.git This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.