aboutsummaryrefslogtreecommitdiff
path: root/sx-question-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'sx-question-mode.el')
-rw-r--r--sx-question-mode.el128
1 files changed, 42 insertions, 86 deletions
diff --git a/sx-question-mode.el b/sx-question-mode.el
index a9e14e7..59313d1 100644
--- a/sx-question-mode.el
+++ b/sx-question-mode.el
@@ -84,10 +84,6 @@ If WINDOW is given, use that to display the buffer."
;;; Printing a question's content
;;;; Faces and Variables
-(defvar sx-question-mode--overlays nil
- "Question mode overlays.")
-(make-variable-buffer-local 'sx-question-mode--overlays)
-
(defface sx-question-mode-header
'((t :inherit font-lock-variable-name-face))
"Face used on the question headers in the question buffer."
@@ -194,12 +190,12 @@ replaced with the comment."
QUESTION must be a data structure returned by `json-read'."
(setq sx-question-mode--data question)
;; Clear the overlays
- (mapc #'delete-overlay sx-question-mode--overlays)
- (setq sx-question-mode--overlays nil)
+ (mapc #'delete-overlay sx--overlays)
+ (setq sx--overlays nil)
;; Print everything
(sx-question-mode--print-section question)
(sx-assoc-let question
- (mapc #'sx-question-mode--print-section .answers))
+ (mapc #'sx-question-mode--print-section .answers))
(goto-char (point-min))
(with-selected-window sx-question-mode--window
(sx-question-mode-next-section)))
@@ -221,11 +217,10 @@ QUESTION must be a data structure returned by `json-read'."
(defun sx-question-mode--print-section (data)
"Print a section corresponding to DATA.
DATA can represent a question or an answer."
- ;; This makes `data' accessible through
- ;; `(get-text-property (point) 'sx-question-mode--data-here)'
- (sx-question-mode--wrap-in-text-property
- (list 'sx-question-mode--data-here data)
- (sx-assoc-let data
+ ;; This makes `data' accessible through `sx--data-here'.
+ (sx-assoc-let data
+ (sx--wrap-in-text-property
+ (list 'sx--data-here data)
(insert sx-question-mode-header-title
(apply
#'propertize
@@ -238,7 +233,7 @@ DATA can represent a question or an answer."
;; face, action and help-echo
sx-question-mode--title-properties))
;; Sections can be hidden with overlays
- (sx-question-mode--wrap-in-overlay
+ (sx--wrap-in-overlay
'(sx-question-mode--section-content t)
(sx-question-mode--insert-header
;; Author
@@ -265,28 +260,29 @@ DATA can represent a question or an answer."
(propertize sx-question-mode-separator
'face 'sx-question-mode-header
'sx-question-mode--section 4))
- (sx-question-mode--wrap-in-overlay
+ (sx--wrap-in-overlay
'(face sx-question-mode-content-face)
(insert "\n"
(sx-question-mode--fill-and-fontify
.body_markdown)
"\n"
(propertize sx-question-mode-separator
- 'face 'sx-question-mode-header))))
- ;; Comments
- (when .comments
- (insert "\n"
- (apply #'propertize
- sx-question-mode-comments-title
- 'face 'sx-question-mode-title-comments
- 'sx-question-mode--section 3
- sx-question-mode--title-properties))
- (sx-question-mode--wrap-in-overlay
- '(sx-question-mode--section-content t)
- (insert "\n")
- (sx-question-mode--wrap-in-overlay
- '(face sx-question-mode-content-face)
- (mapc #'sx-question-mode--print-comment .comments)))))))
+ 'face 'sx-question-mode-header)))))
+ ;; Comments have their own `sx--data-here' property (so they can
+ ;; be upvoted too).
+ (when .comments
+ (insert "\n"
+ (apply #'propertize
+ sx-question-mode-comments-title
+ 'face 'sx-question-mode-title-comments
+ 'sx-question-mode--section 3
+ sx-question-mode--title-properties))
+ (sx--wrap-in-overlay
+ '(sx-question-mode--section-content t)
+ (insert "\n")
+ (sx--wrap-in-overlay
+ '(face sx-question-mode-content-face)
+ (mapc #'sx-question-mode--print-comment .comments))))))
(defun sx-question-mode--propertize-display-name (author)
"Return display_name of AUTHOR with `sx-question-mode-author' face."
@@ -298,46 +294,21 @@ DATA can represent a question or an answer."
"Print the comment described by alist COMMENT-DATA.
The comment is indented, filled, and then printed according to
`sx-question-mode-comments-format'."
- (sx-assoc-let comment-data
- (insert
- (format
- sx-question-mode-comments-format
- (sx-question-mode--propertize-display-name .owner)
- (substring
- ;; We fill with three spaces at the start, so the comment is
- ;; slightly indented.
- (sx-question-mode--fill-and-fontify
- (concat " " .body_markdown))
- ;; Then we remove the spaces from the first line, since we'll
- ;; add the username there anyway.
- 3)))))
-
-(defmacro sx-question-mode--wrap-in-overlay (properties &rest body)
- "Start a scope with overlay PROPERTIES and execute BODY.
-Overlay is pushed on `sx-question-mode--overlays' and given
-PROPERTIES.
-
-Return the result of BODY."
- (declare (indent 1)
- (debug t))
- `(let ((p (point-marker))
- (result (progn ,@body)))
- (let ((ov (make-overlay p (point)))
- (props ,properties))
- (while props
- (overlay-put ov (pop props) (pop props)))
- (push ov sx-question-mode--overlays))
- result))
-
-(defmacro sx-question-mode--wrap-in-text-property (properties &rest body)
- "Start a scope with PROPERTIES and execute BODY.
-Return the result of BODY."
- (declare (indent 1)
- (debug t))
- `(let ((p (point-marker))
- (result (progn ,@body)))
- (add-text-properties p (point) ,properties)
- result))
+ (sx--wrap-in-text-property
+ (list 'sx--data-here comment-data)
+ (sx-assoc-let comment-data
+ (insert
+ (format
+ sx-question-mode-comments-format
+ (sx-question-mode--propertize-display-name .owner)
+ (substring
+ ;; We fill with three spaces at the start, so the comment is
+ ;; slightly indented.
+ (sx-question-mode--fill-and-fontify
+ (concat " " .body_markdown))
+ ;; Then we remove the spaces from the first line, since we'll
+ ;; add the username there anyway.
+ 3))))))
(defun sx-question-mode--insert-header (&rest args)
"Insert propertized ARGS.
@@ -345,9 +316,7 @@ ARGS is a list of repeating values -- `header', `value', and
`face'. `header' is given `sx-question-mode-header' as a face,
where `value' is given `face' as its face.
-Syntax:
-
- \(fn HEADER VALUE FACE [HEADER VALUE FACE] [HEADER VALUE FACE] ...)"
+\(fn HEADER VALUE FACE [HEADER VALUE FACE] [HEADER VALUE FACE] ...)"
(while args
(insert
(propertize (pop args) 'face 'sx-question-mode-header)
@@ -572,7 +541,7 @@ Letters do not insert themselves; instead, they are commands.
`(("n" sx-question-mode-next-section)
("p" sx-question-mode-previous-section)
("g" sx-question-mode-refresh)
- ("v" sx-question-mode-visit)
+ ("v" sx-visit)
("q" quit-window)
(" " scroll-up-command)
(,(kbd "S-SPC") scroll-down-command)
@@ -583,19 +552,6 @@ Letters do not insert themselves; instead, they are commands.
(,(kbd "<backtab>") backward-button)
([return] push-button)))
-(defun sx-question-mode-visit ()
- "Visit the currently displayed question."
- (interactive)
- (sx-question-mode--ensure-mode)
- (sx-assoc-let
- ;; This allows us to visit the thing-at-point. Which could be a
- ;; question or an answer. We use `append', so that if one
- ;; doesn't have a `link' item we can fallback to
- ;; `sx-question-mode--data'.
- (append (get-text-property (point) 'sx-question-mode--data-here)
- sx-question-mode--data)
- (browse-url .link)))
-
(defun sx-question-mode-refresh ()
"Refresh currently displayed question.
Queries the API for any changes to the question or its answers or