emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/ement ca672b5aab 1/4: Add: (ement-directory-next) and a


From: ELPA Syncer
Subject: [elpa] externals/ement ca672b5aab 1/4: Add: (ement-directory-next) and associated changes
Date: Fri, 23 Sep 2022 18:57:36 -0400 (EDT)

branch: externals/ement
commit ca672b5aab229b35ba9a0b750862cb2937addfe4
Author: Adam Porter <adam@alphapapa.net>
Commit: Adam Porter <adam@alphapapa.net>

    Add: (ement-directory-next) and associated changes
---
 README.org         |   6 ++
 ement-directory.el | 160 +++++++++++++++++++++++++++++++++++------------------
 2 files changed, 113 insertions(+), 53 deletions(-)

diff --git a/README.org b/README.org
index 36f9a137a3..f6d727e362 100644
--- a/README.org
+++ b/README.org
@@ -219,6 +219,11 @@ These bindings are common to all of the following buffer 
types:
 +  Show buffer of next unread room: ~SPC~
 +  Move between room names: ~TAB~ / ~<backtab>~
 
+*** Directory buffers
+
++ View/join a room: ~RET~ / ~mouse-1~
++ Load next batch of rooms: ~+~
+
 *** Mentions/notifications buffers
 
 +  Move between events: ~TAB~ / ~<backtab>~
@@ -286,6 +291,7 @@ Note that, while ~matrix-client~ remains usable, and 
probably will for some time
 *Additions*
 + Command ~ement-directory~ shows a server's room directory.
 + Command ~ement-directory-search~ searches a server's room directory.
++ Command ~ement-directory-next~ fetches the next batch of rooms in a 
directory.
 + Command ~ement-leave-room~ accepts a ~FORCE-P~ argument (interactively, with 
prefix) to leave a room without prompting.
 + Command ~ement-forget-room~ accepts a ~FORCE-P~ argument (interactively, 
with prefix) to also leave the room, and to forget it without prompting.
 
diff --git a/ement-directory.el b/ement-directory.el
index 8e9057df3c..87e390a552 100644
--- a/ement-directory.el
+++ b/ement-directory.el
@@ -41,6 +41,7 @@
   (let ((map (make-sparse-keymap)))
     (define-key map (kbd "RET") #'ement-directory-RET)
     (define-key map [mouse-1] #'ement-directory-mouse-1)
+    (define-key map (kbd "+") #'ement-directory-next)
     map))
 
 (defgroup ement-directory nil
@@ -149,10 +150,12 @@
 
 ;; TODO: Pagination of results.
 
-(cl-defun ement-directory (&key server session (limit 1000))
+(cl-defun ement-directory (&key server session since (limit 100))
   "View the public room directory on SERVER with SESSION.
 Show up to LIMIT rooms.  Interactively, with prefix, prompt for
-server and LIMIT."
+server and LIMIT.
+
+SINCE may be a next-batch token."
   (interactive (let* ((session (ement-complete-session :prompt "Search on 
session: "))
                       (server (if current-prefix-arg
                                   (read-string "Search on server: " nil nil
@@ -161,48 +164,91 @@ server and LIMIT."
                       (args (list :server server :session session)))
                  (when current-prefix-arg
                    (cl-callf plist-put args
-                     :limit (read-number "Limit number of rooms: " 1000)))
+                     :limit (read-number "Limit number of rooms: " 100)))
                  args))
   (pcase-let ((revert-function (lambda (&rest _ignore)
                                  (interactive)
                                  (ement-directory :server server :session 
session :limit limit)))
-              (endpoint "publicRooms"))
-    (ement-api session endpoint :params (list (list "limit" limit))
+              (endpoint "publicRooms")
+              (params (list (list "limit" limit))))
+    (when since
+      (cl-callf append params (list (list "since" since))))
+    (ement-api session endpoint :params params
       :then (lambda (results)
-              (ement-directory--view results
-                                     :buffer-name (format "*Ement Directory: 
%s*" server)
-                                     :root-section-name (format "Ement 
Directory: %s" server)
-                                     :init-fn (lambda ()
-                                                (setf (alist-get 'session 
ement-directory-etc) session)
-                                                (setq-local 
revert-buffer-function revert-function)))))
+              (pcase-let (((map ('chunk rooms) ('next_batch next-batch)
+                                ('total_room_count_estimate remaining))
+                           results))
+                (ement-directory--view rooms :append-p since
+                  :buffer-name (format "*Ement Directory: %s*" server)
+                  :root-section-name (format "Ement Directory: %s" server)
+                  :init-fn (lambda ()
+                             (setf (alist-get 'server ement-directory-etc) 
server
+                                   (alist-get 'session ement-directory-etc) 
session
+                                   (alist-get 'next-batch ement-directory-etc) 
next-batch
+                                   (alist-get 'limit ement-directory-etc) 
limit)
+                             (setq-local revert-buffer-function 
revert-function)
+                             (when remaining
+                               (message
+                                (substitute-command-keys
+                                 "%s rooms remaining (use 
\\[ement-directory-next] to fetch more)")
+                                remaining)))))))
     (ement-message "Listing %s rooms on %s..." limit server)))
 
-(cl-defun ement-directory-search (query &key server session)
+(cl-defun ement-directory-search (query &key server session since (limit 1000))
   "View public rooms on SERVER matching QUERY.
 QUERY is a string used to filter results."
   (interactive (let* ((session (ement-complete-session :prompt "Search on 
session: "))
                       (server (if current-prefix-arg
-                                  (read-string "Search on server: ")
+                                  (read-string "Search on server: " nil nil
+                                               (ement-server-name 
(ement-session-server session)))
                                 (ement-server-name (ement-session-server 
session))))
-                      (query (read-string (format "Search for rooms on %s: " 
server))))
-                 (list query :server server :session session)))
+                      (query (read-string (format "Search for rooms on %s 
matching: " server)))
+                      (args (list query :server server :session session)))
+                 (when current-prefix-arg
+                   (cl-callf plist-put (cdr args)
+                     :limit (read-number "Limit number of rooms: " 1000)))
+                 args))
   ;; TODO: Handle "include_all_networks" and "third_party_instance_id".  See ยง 
10.5.4.
   (pcase-let* ((revert-function (lambda (&rest _ignore)
                                   (interactive)
                                   (ement-directory-search query :server server 
:session session)))
                (endpoint "publicRooms")
-               (data (ement-alist "limit" 1000
-                                  "filter" (ement-alist "generic_search_term" 
query))))
+               (data (rassq-delete-all nil
+                                       (ement-alist "limit" limit
+                                                    "filter" (ement-alist 
"generic_search_term" query)
+                                                    "since" since))))
     (ement-api session endpoint :method 'post :data (json-encode data)
       :then (lambda (results)
-              (ement-directory--view results
-                                     :buffer-name (format "*Ement Directory: 
\"%s\" on %s*" query server)
-                                     :root-section-name (format "Ement 
Directory: \"%s\" on %s" query server)
-                                     :init-fn (lambda ()
-                                                (setf (alist-get 'session 
ement-directory-etc) session)
-                                                (setq-local 
revert-buffer-function revert-function)))))
+              (pcase-let (((map ('chunk rooms) ('next_batch next-batch)
+                                ('total_room_count_estimate remaining))
+                           results))
+                (ement-directory--view rooms :append-p since
+                  :buffer-name (format "*Ement Directory: \"%s\" on %s*" query 
server)
+                  :root-section-name (format "Ement Directory: \"%s\" on %s" 
query server)
+                  :init-fn (lambda ()
+                             (setf (alist-get 'server ement-directory-etc) 
server
+                                   (alist-get 'session ement-directory-etc) 
session
+                                   (alist-get 'next-batch ement-directory-etc) 
next-batch
+                                   (alist-get 'limit ement-directory-etc) limit
+                                   (alist-get 'query ement-directory-etc) 
query)
+                             (setq-local revert-buffer-function 
revert-function)
+                             (when remaining
+                               (message
+                                (substitute-command-keys
+                                 "%s rooms remaining (use 
\\[ement-directory-next] to fetch more)")
+                                remaining)))))))
     (ement-message "Searching for %S on %s..." query server)))
 
+(defun ement-directory-next ()
+  "Fetch next batch of results in `ement-directory' buffer."
+  (interactive)
+  (pcase-let (((map next-batch query limit server session) 
ement-directory-etc))
+    (unless next-batch
+      (user-error "No more results"))
+    (if query
+        (ement-directory-search query :server server :session session :limit 
limit :since next-batch)
+      (ement-directory :server server :session session :limit limit :since 
next-batch))))
+
 (defun ement-directory-mouse-1 (event)
   "Call `ement-directory-RET' at EVENT."
   (interactive "e")
@@ -229,18 +275,27 @@ QUERY is a string used to filter results."
 
 ;;;; Functions
 
-(cl-defun ement-directory--view (results &key init-fn
-                                         (buffer-name "*Ement Directory*")
-                                         (root-section-name "Ement Directory")
-                                         (keys ement-directory-default-keys)
-                                         (display-buffer-action 
'(display-buffer-same-window)))
-  "View RESULTS in an `ement-directory-mode' buffer.
-Calls INIT-FN immediately after activating major mode.  Sets
+(cl-defun ement-directory--view (rooms &key init-fn append-p
+                                       (buffer-name "*Ement Directory*")
+                                       (root-section-name "Ement Directory")
+                                       (keys ement-directory-default-keys)
+                                       (display-buffer-action 
'(display-buffer-same-window)))
+  "View ROOMS in an `ement-directory-mode' buffer.
+ROOMS should be a list of rooms from an API request.  Calls
+INIT-FN immediately after activating major mode.  Sets
 BUFFER-NAME and ROOT-SECTION-NAME, and uses
-DISPLAY-BUFFER-ACTION.  KEYS are a list of `taxy' keys.  To be
-called by `ement-directory-search'."
-  (let (format-table column-sizes window-start)
-    (cl-labels ((format-item (item) (gethash item format-table))
+DISPLAY-BUFFER-ACTION.  KEYS are a list of `taxy' keys.  If
+APPEND-P, add ROOMS to buffer rather than replacing existing
+contents.  To be called by `ement-directory-search'."
+  (declare (indent defun))
+  (let (column-sizes window-start)
+    (cl-labels ((format-item
+                 ;; NOTE: We use the buffer-local variable 
`ement-directory-etc' rather
+                 ;; than a closure variable because the taxy-magit-section 
struct's format
+                 ;; table is not stored in it, and we can't reuse closures' 
variables.
+                 ;; (It would be good to store the format table in the 
taxy-magit-section
+                 ;; in the future, to make this cleaner.)
+                 (item) (gethash item (alist-get 'format-table 
ement-directory-etc)))
                 ;; NOTE: Since these functions take an "item" (which is a 
[room session]
                 ;; vector), they're prefixed "item-" rather than "room-".
                 (size
@@ -259,32 +314,31 @@ called by `ement-directory-search'."
                                 :item-indent 2
                                 ;; :heading-face-fn #'heading-face
                                 args)))
-      (unless ement-sessions
-        (error "Ement: Not connected.  Use `ement-connect' to connect"))
       (with-current-buffer (get-buffer-create buffer-name)
-        (ement-directory-mode)
+        (unless (eq 'ement-directory-mode major-mode)
+          ;; Don't obliterate buffer-local variables.
+          (ement-directory-mode))
         (when init-fn
           (funcall init-fn))
-        (pcase-let* (((map ('chunk rooms)) results)
-                     (taxy (cl-macrolet ((first-item
-                                          (pred) `(lambda (taxy)
-                                                    (when (taxy-items taxy)
-                                                      (,pred (car (taxy-items 
taxy)))))))
-                             (thread-last
-                               (make-fn
-                                :name root-section-name
-                                :take (taxy-make-take-function keys 
ement-directory-keys))
-                               (taxy-fill (cl-coerce rooms 'list))
-                               (taxy-sort #'> #'size)
-                               (taxy-sort* #'string> #'taxy-name))))
+        (pcase-let* ((taxy (if append-p
+                               (alist-get 'taxy ement-directory-etc)
+                             (make-fn
+                              :name root-section-name
+                              :take (taxy-make-take-function keys 
ement-directory-keys))))
                      (taxy-magit-section-insert-indent-items nil)
                      (inhibit-read-only t)
-                     (format-cons (taxy-magit-section-format-items
-                                   ement-directory-columns 
ement-directory-column-formatters taxy))
                      (pos (point))
                      (section-ident (when (magit-current-section)
-                                      (magit-section-ident 
(magit-current-section)))))
-          (setf format-table (car format-cons)
+                                      (magit-section-ident 
(magit-current-section))))
+                     (format-cons))
+          (setf taxy (thread-last taxy
+                                  (taxy-fill (cl-coerce rooms 'list))
+                                  (taxy-sort #'> #'size)
+                                  (taxy-sort* #'string> #'taxy-name))
+                (alist-get 'taxy ement-directory-etc) taxy
+                format-cons (taxy-magit-section-format-items
+                             ement-directory-columns 
ement-directory-column-formatters taxy)
+                (alist-get 'format-table ement-directory-etc) (car format-cons)
                 column-sizes (cdr format-cons)
                 header-line-format (taxy-magit-section-format-header
                                     column-sizes 
ement-directory-column-formatters)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]