From eca252dfddba3b18d4da74bee1b802c8d59e0c4a Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Sat, 29 Nov 2014 20:53:52 +0000 Subject: New "Add a Comment" button --- sx-interaction.el | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'sx-interaction.el') diff --git a/sx-interaction.el b/sx-interaction.el index 5f3ece6..92b062b 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -117,15 +117,18 @@ changes." ;;; Commenting -(defun sx-comment (data text) +(defun sx-comment (data &optional text) "Post a comment on DATA given by TEXT. DATA can be a question, an answer, or a comment. Interactively, it is guessed from context at point. If DATA is a comment, the comment is posted as a reply to it. TEXT is a string. Interactively, it is read from the minibufer." - (interactive - (list (sx--data-here) 'query)) + (interactive (list (sx--data-here) 'query)) + ;; When clicking the "Add a Comment" button, first arg is a marker. + (when (markerp data) + (setq data (sx--data-here)) + (setq text 'query)) (sx-assoc-let data ;; Get the comment text (when (eq text 'query) -- cgit v1.2.3 From d2ac145a981521e23cd975ff41e84dc90fa161e5 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 1 Dec 2014 01:13:04 +0000 Subject: Make sx--data-here throw error on failure. --- sx-interaction.el | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'sx-interaction.el') diff --git a/sx-interaction.el b/sx-interaction.el index 5f3ece6..87f72a5 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -29,13 +29,20 @@ ;;; Using data in buffer -(defun sx--data-here () - "Get the text property `sx--data-here'." +(defun sx--data-here (&optional noerror) + "Get data for the question or other object under point. +If NOERROR is non-nil, don't throw an error on failure. + +This looks at the text property `sx--data-here'. If it's not set, +it looks at a few other reasonable variables. If those fail too, +it throws an error." (or (get-text-property (point) 'sx--data-here) (and (derived-mode-p 'sx-question-list-mode) (tabulated-list-get-id)) (or (derived-mode-p 'sx-question-mode) - sx-question-mode--data))) + sx-question-mode--data) + (and (null noerror) + (error "No question data found here")))) (defun sx--maybe-update-display () "Refresh the question list if we're inside it." -- cgit v1.2.3 From 5924ca1de182fc6a865179e7166029cb68c86d1a Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 1 Dec 2014 01:13:52 +0000 Subject: Section Comment --- sx-interaction.el | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sx-interaction.el') diff --git a/sx-interaction.el b/sx-interaction.el index 87f72a5..8f87a47 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -58,6 +58,8 @@ Only fields contained in TO are copied." (setcar to (car from)) (setcdr to (cdr from))) + +;;; Visiting (defun sx-visit (data &optional copy-as-kill) "Visit DATA in a web browser. DATA can be a question, answer, or comment. Interactively, it is -- cgit v1.2.3 From 5bb980d36c6e0346da629ceeb1835a020e75a9b4 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 1 Dec 2014 02:02:14 +0000 Subject: Refactor sx-question-list-display-question into 2 other functions --- sx-interaction.el | 24 ++++++++++++++++++ sx-question-list.el | 70 ++++++++++++++++++++++++----------------------------- 2 files changed, 56 insertions(+), 38 deletions(-) (limited to 'sx-interaction.el') diff --git a/sx-interaction.el b/sx-interaction.el index 8f87a47..f34c49c 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -82,6 +82,30 @@ If DATA is a question, also mark it as read." (sx-question--mark-read data) (sx--maybe-update-display)))) + +;;; Displaying +(defun sx-display-question (&optional data focus window) + "Display question given by DATA, on WINDOW. +When DATA is nil, display question under point. When FOCUS is +non-nil (the default when called interactively), also focus the +relevant window. + +If WINDOW nil, the window is decided by +`sx-question-mode-display-buffer-function'." + (interactive (list (sx--data-here) t)) + (when (sx-question--mark-read data) + (sx--maybe-update-display)) + ;; Display the question. + (setq window + (get-buffer-window + (sx-question-mode--display data window))) + (when focus + (if (window-live-p window) + (select-window window) + (switch-to-buffer sx-question-mode--buffer)))) + + +;;; Voting (defun sx-toggle-upvote (data) "Apply or remove upvote from DATA. DATA can be a question, answer, or comment. Interactively, it is diff --git a/sx-question-list.el b/sx-question-list.el index 9185531..d2e1bb6 100644 --- a/sx-question-list.el +++ b/sx-question-list.el @@ -301,7 +301,7 @@ into consideration. ("d" sx-toggle-downvote) ("h" sx-question-list-hide) ("m" sx-question-list-mark-read) - ([?\r] sx-question-list-display-question))) + ([?\r] sx-display-question))) (defun sx-question-list-hide (data) "Hide question under point. @@ -421,7 +421,37 @@ Displayed in `sx-question-mode--window', replacing any question that may currently be there." (interactive "p") (sx-question-list-next n) - (sx-question-list-display-question)) + (sx-display-question + (tabulated-list-get-id) + nil + (sx-question-list--create-question-window))) + +(defun sx-question-list--create-question-window () + "Create or find a window where a question can be displayed. + +If any current window displays a question, that window is +returned. If none do, a new one is created such that the +question-list window remains `sx-question-list-height' lines +high (if possible)." + (or (sx-question-mode--get-window) + ;; Create a proper window. + (let ((window + (condition-case er + (split-window (selected-window) sx-question-list-height 'below) + (error + ;; If the window is too small to split, use any one. + (if (string-match + "Window # too small for splitting" + (car (cdr-safe er))) + (next-window) + (error (cdr er))))))) + ;; Configure the window to be closed on `q'. + (set-window-prev-buffers window nil) + (set-window-parameter + window 'quit-restore + ;; See (info "(elisp) Window Parameters") + `(window window ,(selected-window) ,sx-question-mode--buffer)) + window))) (defun sx-question-list-next (n) "Move cursor down N questions. @@ -483,42 +513,6 @@ This does not update `sx-question-mode--window'." (interactive "p") (sx-question-list-next-far (- n))) -(defun sx-question-list-display-question (&optional data focus) - "Display question given by DATA. -When DATA is nil, display question under point. When FOCUS is -non-nil (the default when called interactively), also focus the -relevant window." - (interactive '(nil t)) - (unless data (setq data (tabulated-list-get-id))) - (unless data (error "No question here!")) - (when (sx-question--mark-read data) - (sx-question-list-refresh 'redisplay 'no-update)) - (unless (and (window-live-p sx-question-mode--window) - (null (equal sx-question-mode--window (selected-window)))) - (setq sx-question-mode--window - (condition-case er - (split-window (selected-window) sx-question-list-height 'below) - (error - ;; If the window is too small to split, use current one. - (if (string-match - "Window # too small for splitting" - (car (cdr-safe er))) - nil - (error (cdr er))))))) - ;; Display the question. - (sx-question-mode--display data sx-question-mode--window) - ;; Configure the window to be closed on `q'. - (set-window-prev-buffers sx-question-mode--window nil) - (set-window-parameter - sx-question-mode--window - 'quit-restore - ;; See (info "(elisp) Window Parameters") - `(window window ,(selected-window) ,sx-question-mode--buffer)) - (when focus - (if sx-question-mode--window - (select-window sx-question-mode--window) - (switch-to-buffer sx-question-mode--buffer)))) - (defun sx-question-list-switch-site (site) "Switch the current site to SITE and display its questions. Use `ido-completing-read' if variable `ido-mode' is active. -- cgit v1.2.3 From 39f2ae05597edd902610764b9b402111d33a8fe7 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 1 Dec 2014 10:30:08 +0000 Subject: question-mod now uses overlays to store the sx--data-here property This lets us stack one inside each other (comments inside questions) without overwriting them. --- sx-interaction.el | 6 +++--- sx-question-print.el | 4 ++-- sx.el | 24 +++++++++++++----------- 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'sx-interaction.el') diff --git a/sx-interaction.el b/sx-interaction.el index 92b062b..b6113a2 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -31,11 +31,11 @@ ;;; Using data in buffer (defun sx--data-here () "Get the text property `sx--data-here'." - (or (get-text-property (point) 'sx--data-here) + (or (get-pos-property (point) 'sx--data-here) (and (derived-mode-p 'sx-question-list-mode) (tabulated-list-get-id)) - (or (derived-mode-p 'sx-question-mode) - sx-question-mode--data))) + (and (derived-mode-p 'sx-question-mode) + sx-question-mode--data))) (defun sx--maybe-update-display () "Refresh the question list if we're inside it." diff --git a/sx-question-print.el b/sx-question-print.el index f49346b..45124c4 100644 --- a/sx-question-print.el +++ b/sx-question-print.el @@ -185,7 +185,7 @@ QUESTION must be a data structure returned by `json-read'." DATA can represent a question or an answer." ;; This makes `data' accessible through `sx--data-here'. (sx-assoc-let data - (sx--wrap-in-text-property + (sx--wrap-in-overlay (list 'sx--data-here data) (insert sx-question-mode-header-title) (insert-text-button @@ -270,7 +270,7 @@ 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--wrap-in-text-property + (sx--wrap-in-overlay (list 'sx--data-here comment-data) (sx-assoc-let comment-data (insert diff --git a/sx.el b/sx.el index fc58b02..f1d3634 100644 --- a/sx.el +++ b/sx.el @@ -215,6 +215,11 @@ Anything before the (sub)domain is removed." "Overlays created by sx on this buffer.") (make-variable-buffer-local 'sx--overlays) +(defvar sx--overlay-printing-depth 0 + "Track how many overlays we're printing on top of each other. +Used for assigning higher priority to inner overlays.") +(make-variable-buffer-local 'sx--overlay-printing-depth) + (defmacro sx--wrap-in-overlay (properties &rest body) "Start a scope with overlay PROPERTIES and execute BODY. Overlay is pushed on the buffer-local variable `sx--overlays' and @@ -224,24 +229,21 @@ Return the result of BODY." (declare (indent 1) (debug t)) `(let ((p (point-marker)) - (result (progn ,@body))) + (result (progn ,@body)) + ;; The first overlay is the shallowest. Any overlays created + ;; while the first one is still being created go deeper and + ;; deeper. + (sx--overlay-printing-depth (1+ sx--overlay-printing-depth))) (let ((ov (make-overlay p (point))) (props ,properties)) (while props (overlay-put ov (pop props) (pop props))) + ;; Let's multiply by 10 just in case we ever want to put + ;; something in the middle. + (overlay-put ov 'priority (* 10 sx--overlay-printing-depth)) (push ov sx--overlays)) result)) -(defmacro sx--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)) - (defun sx--user-@name (user) "Get the `display_name' of USER prepended with @. In order to correctly @mention the user, all whitespace is -- cgit v1.2.3 From 5cfd9b840e3835ed373a8c6e67291c69f336a3b6 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 1 Dec 2014 15:31:28 +0000 Subject: Switch get-pos-property to get-char-property --- sx-interaction.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sx-interaction.el') diff --git a/sx-interaction.el b/sx-interaction.el index b6113a2..305e61c 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -31,7 +31,7 @@ ;;; Using data in buffer (defun sx--data-here () "Get the text property `sx--data-here'." - (or (get-pos-property (point) 'sx--data-here) + (or (get-char-property (point) 'sx--data-here) (and (derived-mode-p 'sx-question-list-mode) (tabulated-list-get-id)) (and (derived-mode-p 'sx-question-mode) -- cgit v1.2.3 From 8795a394f90f143239edeabd870bf0767303543d Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 2 Dec 2014 15:24:47 +0000 Subject: Redo sx--data-here take &optional noerror --- sx-interaction.el | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'sx-interaction.el') diff --git a/sx-interaction.el b/sx-interaction.el index b04a49e..b67e0df 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -29,13 +29,20 @@ ;;; Using data in buffer -(defun sx--data-here () - "Get the text property `sx--data-here'." - (or (get-char-property (point) 'sx--data-here) +(defun sx--data-here (&optional noerror) + "Get data for the question or other object under point. +If NOERROR is non-nil, don't throw an error on failure. + +This looks at the text property `sx--data-here'. If it's not set, +it looks at a few other reasonable variables. If those fail too, +it throws an error." + (or (get-text-property (point) 'sx--data-here) (and (derived-mode-p 'sx-question-list-mode) (tabulated-list-get-id)) (and (derived-mode-p 'sx-question-mode) - sx-question-mode--data))) + sx-question-mode--data) + (and (null noerror) + (error "No question data found here")))) (defun sx--maybe-update-display () "Refresh the question list if we're inside it." -- cgit v1.2.3