aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sx-question-list.el106
-rw-r--r--sx-question-mode.el3
-rw-r--r--sx-tab.el18
3 files changed, 73 insertions, 54 deletions
diff --git a/sx-question-list.el b/sx-question-list.el
index 4719d84..4d80305 100644
--- a/sx-question-list.el
+++ b/sx-question-list.el
@@ -164,14 +164,7 @@ If this is not set, the value of `sx-question-list--dataset' is
used, and the list is simply redisplayed.")
(make-variable-buffer-local 'sx-question-list--refresh-function)
-(defvar sx-question-list--next-page-function
- (lambda ()
- (or (sx-question-get-questions
- sx-question-list--current-site
- (cl-incf sx-question-list--pages-so-far))
- ;; If the `get' failed, don't increment.
- (and (cl-decf sx-question-list--pages-so-far)
- nil)))
+(defvar sx-question-list--next-page-function nil
"Function used to fetch the next page of questions to be displayed.
Used by `sx-question-list-mode'. This is a function, called with
no arguments, which returns a list questions to be displayed,
@@ -201,38 +194,52 @@ This is ignored if `sx-question-list--refresh-function' is set.")
"Major mode for browsing a list of questions from StackExchange.
Letters do not insert themselves; instead, they are commands.
-To use this mode, activate it and then optionally set some of the
-following variables:
-
- 1. `sx-question-list--print-function'
- 2. `sx-question-list--refresh-function'
- 3. `sx-question-list--next-page-function'
- 4. `sx-question-list--dataset'
+The recommended way of using this mode is to activate it and then
+set `sx-question-list--next-page-function'. The return value of
+this function is mapped with `sx-question-list--print-function',
+so you may need to customize the latter if the former does not
+return a list of questions.
+
+The full list of variables which can be set is:
+ 1. `sx-question-list--site'
+ Set this to the name of the site if that makes sense. If it
+ doesn't leave it as nil.
+ 2. `sx-question-list--print-function'
+ Change this if the data you're dealing with is not strictly a
+ list of questions (see the doc for details).
+ 3. `sx-question-list--refresh-function'
+ This is used to populate the initial list. It is only necessary
+ if item 4 does not fit your needs.
+ 4. `sx-question-list--next-page-function'
+ This is used to fetch further questions. If item 3 is nil, it is
+ also used to populate the initial list.
+ 5. `sx-question-list--dataset'
+ This is only used if both 3 and 4 are nil. It can be used to
+ display a static list.
\\<sx-question-list-mode-map>
If none of these is configured, the behaviour is that of a
\"Frontpage\", for the site given by
-`sx-question-list--current-site'.
+`sx-question-list--site'.
-Function 1 is mandatory, but it also has a sane default which is
+Item 2 is mandatory, but it also has a sane default which is
usually enough.
-As long as one of 2, 3, or 4 is provided, the other two are
+As long as one of 3, 4, or 5 is provided, the other two are
entirely optional. Populating or refreshing the list of questions
is done in the following way:
- - Set `sx-question-list--pages-so-far' to 0.
+ - Set `sx-question-list--pages-so-far' to 1.
- Call function 2.
- - If function 2 is not given, call function 3 instead.
- - If 3 is also not given, it has a safe default (see the doc).
- - If 3 is set to nil use the value of 4.
+ - If function 2 is not given, call function 3 with argument 1.
+ - If 3 is not given use the value of 4.
-For better integration, items 2 and 3 should take into
-consideration the variable `sx-question-list--current-site'. If
-the application in question has no use for this variable, it
-should unbind \\[sx-question-list-switch-site].
+Adding further questions to the bottom of the list is done by:
+ - Increment `sx-question-list--pages-so-far'.
+ - Call function 3 with argument `sx-question-list--pages-so-far'.
+ - If it returns anything, append to the dataset and refresh the
+ display; otherwise, decrement `sx-question-list--pages-so-far'.
-Function 3 should probably use the value of
-`sx-question-list--pages-so-far'. If it does, it needs to update
-the value manually.
+If `sx-question-list--site' is given, items 3 and 4 should take it
+into consideration.
\\{sx-question-list-mode-map}"
(hl-line-mode 1)
@@ -349,7 +356,7 @@ Non-interactively, DATA is a question alist."
(setq sx-question-list--total-count
(length tabulated-list-entries))))
-(defvar sx-question-list--current-site "emacs"
+(defvar sx-question-list--site nil
"Site being displayed in the *question-list* buffer.")
(defun sx-question-list-refresh (&optional redisplay no-update)
@@ -361,13 +368,13 @@ a new list before redisplaying."
;; Reset the mode-line unread count (we rebuild it here).
(setq sx-question-list--unread-count 0)
(unless no-update
- (setq sx-question-list--pages-so-far 0))
+ (setq sx-question-list--pages-so-far 1))
(let ((question-list
(or (and no-update sx-question-list--dataset)
(and (functionp sx-question-list--refresh-function)
(funcall sx-question-list--refresh-function))
(and (functionp sx-question-list--next-page-function)
- (funcall sx-question-list--next-page-function))
+ (funcall sx-question-list--next-page-function 1))
sx-question-list--dataset)))
(setq sx-question-list--dataset question-list)
;; Print the result.
@@ -423,18 +430,23 @@ This does not update `sx-question-mode--window'."
(defun sx-question-list-next-page ()
"Fetch and display the next page of questions."
(interactive)
- (let ((list (when sx-question-list--next-page-function
- (funcall sx-question-list--next-page-function))))
- ;; Try to be at the right place.
- (goto-char (point-max))
- (forward-line -1)
- (if (null list)
- (message "No further questions.")
- ;; @TODO: Check for duplicates.
- (setq sx-question-list--dataset
- (append sx-question-list--dataset list))
- (sx-question-list-refresh 'redisplay 'no-update)
- (forward-line 1))))
+ ;; Stay at the last line.
+ (goto-char (point-max))
+ (forward-line -1)
+ (when (functionp sx-question-list--next-page-function)
+ ;; Try to get more questions
+ (let ((list (funcall sx-question-list--next-page-function
+ (1+ sx-question-list--pages-so-far))))
+ (if (null list)
+ (message "No further questions.")
+ ;; If it worked, increment the variable.
+ (cl-incf sx-question-list--pages-so-far)
+ ;; And update the dataset.
+ ;; @TODO: Check for duplicates.
+ (setq sx-question-list--dataset
+ (append sx-question-list--dataset list))
+ (sx-question-list-refresh 'redisplay 'no-update)
+ (forward-line 1)))))
(defun sx-question-list-previous (n)
"Move cursor up N questions.
@@ -502,15 +514,15 @@ relevant window."
"Switch the current site to SITE and display its questions.
Use `ido-completing-read' if variable `ido-mode' is active.
Retrieve completions from `sx-site-get-api-tokens'.
-Sets `sx-question-list--current-site' and then call
+Sets `sx-question-list--site' and then call
`sx-question-list-refresh' with `redisplay'."
(interactive
(list (funcall (if ido-mode #'ido-completing-read #'completing-read)
"Switch to site: " (sx-site-get-api-tokens)
- (lambda (site) (not (equal site sx-question-list--current-site)))
+ (lambda (site) (not (equal site sx-question-list--site)))
t)))
(when (and (stringp site) (> (length site) 0))
- (setq sx-question-list--current-site site)
+ (setq sx-question-list--site site)
(sx-question-list-refresh 'redisplay)))
(provide 'sx-question-list)
diff --git a/sx-question-mode.el b/sx-question-mode.el
index f1705a5..a9e14e7 100644
--- a/sx-question-mode.el
+++ b/sx-question-mode.el
@@ -604,8 +604,7 @@ comments, and redisplays it."
(sx-question-mode--ensure-mode)
(sx-assoc-let sx-question-mode--data
(sx-question-mode--display
- (sx-question-get-question
- sx-question-list--current-site .question_id)
+ (sx-question-get-question .site .question_id)
(selected-window))))
(defun sx-question-mode--ensure-mode ()
diff --git a/sx-tab.el b/sx-tab.el
index 29398d2..8a51236 100644
--- a/sx-tab.el
+++ b/sx-tab.el
@@ -32,18 +32,22 @@
:type 'string
:group 'stack-exchange)
-(defmacro sx-tab--define (tab &optional printer refresher pager)
+(defmacro sx-tab--define (tab pager &optional printer refresher
+ &rest body)
"Define a stack-exchange tab called TAB.
TAB is a capitalized string.
This defines a command `sx-tab-TAB' for displaying the tab,
and a variable `sx-tab--TAB-buffer' for holding the bufer.
-The arguments PRINTER, REFRESHER, and PAGER, if non-nil, are
+The arguments PAGER, PRINTER, and REFRESHER, if non-nil, are
respectively used to set the value of the variables
`sx-question-list--print-function',
`sx-question-list--refresh-function', and
-`sx-question-list--next-page-function'."
+`sx-question-list--next-page-function'.
+
+BODY is evaluated after activating the mode and setting these
+variables, but before refreshing the display."
(declare (indent 1) (debug t))
(let* ((name (downcase tab))
(buffer-variable
@@ -81,14 +85,18 @@ If SITE is nil, use `sx-tab-default-site'."
`(setq sx-question-list--refresh-function ,refresher))
,(when pager
`(setq sx-question-list--next-page-function ,pager))
- (setq sx-question-list--current-site site)
+ (setq sx-question-list--site site)
(setq sx-question-list--current-tab ,tab)
+ ,@body
(sx-question-list-refresh 'redisplay no-update))
(switch-to-buffer ,buffer-variable)))))
;;; FrontPage
-(sx-tab--define "FrontPage")
+(sx-tab--define "FrontPage"
+ (lambda (page)
+ (sx-question-get-questions
+ sx-question-list--site page)))
(provide 'sx-tab)
;;; sx-tab.el ends here