254 lines
8.4 KiB
EmacsLisp
254 lines
8.4 KiB
EmacsLisp
|
;;; sx-tab.el --- functions for viewing different tabs -*- lexical-binding: t; -*-
|
|||
|
|
|||
|
;; Copyright (C) 2014 Artur Malabarba
|
|||
|
|
|||
|
;; Author: Artur Malabarba <bruce.connor.am@gmail.com>
|
|||
|
|
|||
|
;; This program 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.
|
|||
|
|
|||
|
;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
|
|||
|
;;; Commentary:
|
|||
|
|
|||
|
;; This file provides a single macro to define 'tabs' to view lists of
|
|||
|
;; questions.
|
|||
|
|
|||
|
;;; Tabs:
|
|||
|
|
|||
|
;; - `sx-tab-all-questions' :: All questions.
|
|||
|
;; - `sx-tab-unanswered' :: Unanswered questions.
|
|||
|
;; - `sx-tab-unanswered-my-tags' :: Unanswered questions in your followed tags.
|
|||
|
;; - `sx-tab-featured' :: Featured questions.
|
|||
|
;; - `sx-tab-starred' :: Starred questions.
|
|||
|
|
|||
|
;;; Code:
|
|||
|
|
|||
|
(require 'sx)
|
|||
|
(require 'sx-question-list)
|
|||
|
(require 'sx-interaction)
|
|||
|
|
|||
|
(defvar sx-tab--list nil
|
|||
|
"List of the names of all defined tabs.")
|
|||
|
|
|||
|
(defun sx-tab-switch (tab)
|
|||
|
"Switch to another question-list TAB."
|
|||
|
(interactive
|
|||
|
(list (sx-completing-read
|
|||
|
"Switch to tab: " sx-tab--list
|
|||
|
(lambda (tab) (not (equal tab sx-question-list--current-tab)))
|
|||
|
t)))
|
|||
|
(funcall (intern (format "sx-tab-%s" (downcase tab)))))
|
|||
|
|
|||
|
(defconst sx-tab--order-methods
|
|||
|
`(,@(default-value 'sx-question-list--order-methods)
|
|||
|
("Hottest Now" . hot)
|
|||
|
("Weekly Hottest" . week)
|
|||
|
("Monthly Hottest" . month))
|
|||
|
"Alist of possible values to be passed to the `sort' keyword.")
|
|||
|
|
|||
|
(defcustom sx-tab-default-order 'activity
|
|||
|
"Default ordering method used on `sx-tab-questions' and the likes.
|
|||
|
Possible values are the cdrs of `sx-tab--order-methods'."
|
|||
|
:type (cons 'choice
|
|||
|
(mapcar (lambda (c) `(const :tag ,(car c) ,(cdr c)))
|
|||
|
(cl-remove-duplicates
|
|||
|
sx-tab--order-methods
|
|||
|
:key #'cdr)))
|
|||
|
:group 'sx-question-list)
|
|||
|
|
|||
|
(eval-and-compile
|
|||
|
(defconst sx-tab--docstring-format
|
|||
|
"Display a list of %s questions for SITE.
|
|||
|
The variable `sx-tab-default-order' can be used to customize the
|
|||
|
sorting of the resulting list.
|
|||
|
|
|||
|
NO-UPDATE (the prefix arg) is passed to `sx-question-list-refresh'.
|
|||
|
If SITE is nil, use `sx-default-site'."
|
|||
|
"Format used on the docstring of `sx-tab-*' commands."))
|
|||
|
|
|||
|
|
|||
|
;;; The main macro
|
|||
|
(defmacro sx-tab--define (tab pager &optional printer refresher obsolete
|
|||
|
&rest body)
|
|||
|
"Define a StackExchange 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 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'.
|
|||
|
|
|||
|
If OBSOLETE is non-nil, it should be a string indicating the tab
|
|||
|
to use instead of this one.
|
|||
|
|
|||
|
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
|
|||
|
(intern (format "sx-tab--%s-buffer"
|
|||
|
(if obsolete (downcase obsolete)
|
|||
|
name))))
|
|||
|
(function-name
|
|||
|
(intern (concat "sx-tab-" name)))
|
|||
|
(use-instead
|
|||
|
(when obsolete (intern (concat "sx-tab-" (downcase obsolete))))))
|
|||
|
`(progn
|
|||
|
,(unless obsolete
|
|||
|
`(defvar ,buffer-variable nil
|
|||
|
,(format "Buffer where the %s questions are displayed." tab)))
|
|||
|
(defun ,function-name (&optional no-update site)
|
|||
|
,(format sx-tab--docstring-format tab)
|
|||
|
(interactive
|
|||
|
(list current-prefix-arg
|
|||
|
(sx--interactive-site-prompt)))
|
|||
|
(sx-initialize)
|
|||
|
(unless site (setq site sx-default-site))
|
|||
|
;; Create the buffer
|
|||
|
(unless (buffer-live-p ,buffer-variable)
|
|||
|
(setq ,buffer-variable
|
|||
|
(generate-new-buffer
|
|||
|
,(format "*question-list: %s *" (or obsolete tab)))))
|
|||
|
;; Fill the buffer with content.
|
|||
|
(with-current-buffer ,buffer-variable
|
|||
|
(sx-question-list-mode)
|
|||
|
(when ,printer (setq sx-question-list--print-function ,printer))
|
|||
|
(when ,refresher (setq sx-question-list--refresh-function ,refresher))
|
|||
|
(setq sx-question-list--next-page-function ,pager)
|
|||
|
(setq sx-question-list--site site)
|
|||
|
(setq sx-question-list--order 'activity)
|
|||
|
(setq sx-question-list--current-tab ,(or obsolete tab))
|
|||
|
,@body
|
|||
|
(sx-question-list-refresh 'redisplay no-update))
|
|||
|
(switch-to-buffer ,buffer-variable))
|
|||
|
,(when obsolete
|
|||
|
`(make-obsolete ',function-name ',use-instead nil))
|
|||
|
;; Add this tab to the list of existing tabs. So we can prompt
|
|||
|
;; the user with completion and stuff.
|
|||
|
(unless ,obsolete
|
|||
|
(add-to-list 'sx-tab--list ,tab)))))
|
|||
|
|
|||
|
|
|||
|
;;; Entry commands
|
|||
|
(sx-tab--define "All-Questions"
|
|||
|
(sx-question-list--make-pager 'questions)
|
|||
|
nil nil nil
|
|||
|
(setq sx-question-list--order-methods
|
|||
|
sx-tab--order-methods))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-all-questions "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Unanswered"
|
|||
|
(sx-question-list--make-pager 'questions 'unanswered))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-unanswered "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Unanswered-My-Tags"
|
|||
|
(sx-question-list--make-pager 'questions 'unanswered/my-tags))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-unanswered-my-tags "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Featured"
|
|||
|
(sx-question-list--make-pager 'questions 'featured))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-featured "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Starred"
|
|||
|
(sx-question-list--make-pager 'me 'favorites))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-starred "sx-tab" nil t)
|
|||
|
|
|||
|
|
|||
|
;;; Inter-modes navigation
|
|||
|
(defun sx-tab-meta-or-main ()
|
|||
|
"Switch to the meta version of a main site, or vice-versa.
|
|||
|
Inside a question, go to the frontpage of the site this question
|
|||
|
belongs to."
|
|||
|
(interactive)
|
|||
|
(if (and (derived-mode-p 'sx-question-list-mode)
|
|||
|
sx-question-list--site)
|
|||
|
(sx-question-list-switch-site
|
|||
|
(if (string-match "\\`meta\\." sx-question-list--site)
|
|||
|
(replace-match "" :fixedcase nil sx-question-list--site)
|
|||
|
(concat "meta." sx-question-list--site)))
|
|||
|
(sx-tab-all-questions nil (sx--site (sx--data-here 'question)))))
|
|||
|
|
|||
|
|
|||
|
;;; Obsolete tabs
|
|||
|
(defconst sx-tab--basic-question-pager
|
|||
|
(sx-question-list--make-pager 'questions))
|
|||
|
|
|||
|
(sx-tab--define "FrontPage"
|
|||
|
sx-tab--basic-question-pager
|
|||
|
nil nil "All-Questions"
|
|||
|
(setq sx-question-list--order 'activity)
|
|||
|
(setq sx-question-list--order-methods
|
|||
|
sx-tab--order-methods))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-frontpage "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Newest"
|
|||
|
sx-tab--basic-question-pager
|
|||
|
nil nil "All-Questions"
|
|||
|
(setq sx-question-list--order 'creation)
|
|||
|
(setq sx-question-list--order-methods
|
|||
|
sx-tab--order-methods))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-newest "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "TopVoted"
|
|||
|
sx-tab--basic-question-pager
|
|||
|
nil nil "All-Questions"
|
|||
|
(setq sx-question-list--order 'votes)
|
|||
|
(setq sx-question-list--order-methods
|
|||
|
sx-tab--order-methods))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-topvoted "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Hot"
|
|||
|
sx-tab--basic-question-pager
|
|||
|
nil nil "All-Questions"
|
|||
|
(setq sx-question-list--order 'hot)
|
|||
|
(setq sx-question-list--order-methods
|
|||
|
sx-tab--order-methods))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-hot "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Week"
|
|||
|
sx-tab--basic-question-pager
|
|||
|
nil nil "All-Questions"
|
|||
|
(setq sx-question-list--order 'week)
|
|||
|
(setq sx-question-list--order-methods
|
|||
|
sx-tab--order-methods))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-week "sx-tab" nil t)
|
|||
|
|
|||
|
(sx-tab--define "Month"
|
|||
|
sx-tab--basic-question-pager
|
|||
|
nil nil "All-Questions"
|
|||
|
(setq sx-question-list--order 'month)
|
|||
|
(setq sx-question-list--order-methods
|
|||
|
sx-tab--order-methods))
|
|||
|
;;;###autoload
|
|||
|
(autoload 'sx-tab-month "sx-tab" nil t)
|
|||
|
|
|||
|
(provide 'sx-tab)
|
|||
|
;;; sx-tab.el ends here
|
|||
|
|
|||
|
;; Local Variables:
|
|||
|
;; indent-tabs-mode: nil
|
|||
|
;; End:
|