217 lines
6.2 KiB
EmacsLisp
217 lines
6.2 KiB
EmacsLisp
;;; sx-inbox.el --- base inbox logic -*- 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:
|
||
|
||
;;; Code:
|
||
|
||
(require 'sx)
|
||
(require 'sx-filter)
|
||
(require 'sx-method)
|
||
(require 'sx-question-list)
|
||
(require 'sx-interaction)
|
||
|
||
|
||
;;; API
|
||
(defconst sx-inbox-filter
|
||
'((inbox_item.answer_id
|
||
inbox_item.body
|
||
inbox_item.comment_id
|
||
inbox_item.creation_date
|
||
inbox_item.is_unread
|
||
inbox_item.item_type
|
||
inbox_item.link
|
||
inbox_item.question_id
|
||
inbox_item.site
|
||
inbox_item.title)
|
||
(site.logo_url
|
||
site.audience
|
||
site.icon_url
|
||
site.high_resolution_icon_url
|
||
site.site_state
|
||
site.launch_date
|
||
site.markdown_extensions
|
||
site.related_sites
|
||
site.styling))
|
||
"Filter used when retrieving inbox items.")
|
||
|
||
(defcustom sx-inbox-fill-column 40
|
||
"`fill-column' used in `sx-inbox-mode'."
|
||
:type 'integer
|
||
:group 'sx)
|
||
|
||
(defun sx-inbox-get (&optional notifications page keywords)
|
||
"Get an array of inbox items for the current user.
|
||
If NOTIFICATIONS is non-nil, query from `notifications' method,
|
||
otherwise use `inbox' method.
|
||
|
||
Return an array of items. Each item is an alist of properties
|
||
returned by the API.
|
||
See https://api.stackexchange.com/docs/types/inbox-item
|
||
|
||
KEYWORDS are added to the method call along with PAGE.
|
||
|
||
`sx-method-call' is used with `sx-inbox-filter'."
|
||
(sx-method-call (if notifications 'notifications 'inbox)
|
||
:keywords keywords
|
||
:page page
|
||
:filter sx-inbox-filter))
|
||
|
||
|
||
;;; Major-mode
|
||
(defvar sx-inbox--notification-p nil
|
||
"If non-nil, current buffer lists notifications, not inbox.")
|
||
(make-variable-buffer-local 'sx-inbox--notification-p)
|
||
|
||
(defvar sx-inbox--unread-inbox nil
|
||
"List of inbox items still unread.")
|
||
|
||
(defvar sx-inbox--unread-notifications nil
|
||
"List of notifications items still unread.")
|
||
|
||
(defvar sx-inbox--read-inbox nil
|
||
"List of inbox items which are read.
|
||
These are identified by their links.")
|
||
|
||
(defvar sx-inbox--read-notifications nil
|
||
"List of notification items which are read.
|
||
These are identified by their links.")
|
||
|
||
(defconst sx-inbox--header-line
|
||
'(" "
|
||
(:propertize "n p j k" face mode-line-buffer-id)
|
||
": Navigate"
|
||
" "
|
||
(:propertize "RET" face mode-line-buffer-id)
|
||
": View"
|
||
" "
|
||
(:propertize "v" face mode-line-buffer-id)
|
||
": Visit externally"
|
||
" "
|
||
(:propertize "q" face mode-line-buffer-id)
|
||
": Quit")
|
||
"Header-line used on the inbox list.")
|
||
|
||
(defconst sx-inbox--mode-line
|
||
'(" "
|
||
(:propertize
|
||
(sx-inbox--notification-p
|
||
"Notifications"
|
||
"Inbox")
|
||
face mode-line-buffer-id))
|
||
"Mode-line used on the inbox list.")
|
||
|
||
(define-derived-mode sx-inbox-mode
|
||
sx-question-list-mode "Question List"
|
||
"Mode used to list inbox and notification items."
|
||
(toggle-truncate-lines 1)
|
||
(setq fill-column sx-inbox-fill-column)
|
||
(setq sx-question-list--print-function #'sx-inbox--print-info)
|
||
(setq sx-question-list--next-page-function
|
||
(lambda (page) (sx-inbox-get sx-inbox--notification-p page)))
|
||
(setq tabulated-list-format
|
||
[("Type" 30 t nil t) ("Date" 10 t :right-align t) ("Title" 0)])
|
||
(setq mode-line-format sx-inbox--mode-line)
|
||
(setq header-line-format sx-inbox--header-line))
|
||
|
||
|
||
;;; Keybinds
|
||
(mapc (lambda (x) (define-key sx-inbox-mode-map (car x) (cadr x)))
|
||
'(
|
||
("t" nil)
|
||
("a" nil)
|
||
("h" nil)
|
||
("m" sx-inbox-mark-read)
|
||
([?\r] sx-display)
|
||
))
|
||
|
||
|
||
;;; print-info
|
||
(defun sx-inbox--print-info (data)
|
||
"Convert `json-read' DATA into tabulated-list format.
|
||
|
||
This is the default printer used by `sx-inbox'. It assumes DATA
|
||
is an alist containing the elements:
|
||
`answer_id', `body', `comment_id', `creation_date', `is_unread',
|
||
`item_type', `link', `question_id', `site', `title'."
|
||
(list
|
||
data
|
||
(sx-assoc-let data
|
||
(vector
|
||
(list
|
||
(concat (capitalize
|
||
(replace-regexp-in-string
|
||
"_" " " (or .item_type .notification_type)))
|
||
(cond (.answer_id " on Answer at:")
|
||
(.question_id " on:")))
|
||
'face 'font-lock-keyword-face)
|
||
(list
|
||
(concat (sx-time-since .creation_date)
|
||
sx-question-list-ago-string)
|
||
'face 'sx-question-list-date)
|
||
(list
|
||
(propertize
|
||
" " 'display
|
||
(concat "\n " (propertize .title 'face 'sx-question-list-date) "\n"
|
||
(let ((col fill-column))
|
||
(with-temp-buffer
|
||
(setq fill-column col)
|
||
(insert " " .body)
|
||
(fill-region (point-min) (point-max))
|
||
(buffer-string))))
|
||
'face 'default))))))
|
||
|
||
|
||
;;; Entry commands
|
||
(defvar sx-inbox--buffer nil
|
||
"Buffer being used to display inbox.")
|
||
|
||
;;;###autoload
|
||
(defun sx-inbox (&optional notifications)
|
||
"Display a buffer listing inbox items.
|
||
With prefix NOTIFICATIONS, list notifications instead of inbox."
|
||
(interactive "P")
|
||
(setq sx-inbox--buffer (get-buffer-create "*sx-inbox*"))
|
||
(let ((inhibit-read-only t))
|
||
(with-current-buffer sx-inbox--buffer
|
||
(erase-buffer)
|
||
(sx-inbox-mode)
|
||
(setq sx-inbox--notification-p notifications)
|
||
(tabulated-list-revert)))
|
||
(let ((w (get-buffer-window sx-inbox--buffer)))
|
||
(if (window-live-p w)
|
||
(select-window w)
|
||
(pop-to-buffer sx-inbox--buffer)
|
||
(enlarge-window
|
||
(- (+ fill-column 4) (window-width))
|
||
'horizontal))))
|
||
|
||
;;;###autoload
|
||
(defun sx-inbox-notifications ()
|
||
"Display a buffer listing notification items."
|
||
(interactive)
|
||
(sx-inbox t))
|
||
|
||
(provide 'sx-inbox)
|
||
;;; sx-inbox.el ends here
|
||
|
||
;; Local Variables:
|
||
;; indent-tabs-mode: nil
|
||
;; End:
|