diff options
author | Sean Allred <code@seanallred.com> | 2014-11-25 21:55:46 -0500 |
---|---|---|
committer | Sean Allred <code@seanallred.com> | 2014-11-25 21:55:46 -0500 |
commit | 07a1456fe7a91d1589f689d40ac4391f35e695b9 (patch) | |
tree | 1c79f7808dc280e29ca2ca93dc57792ba8286d4f | |
parent | 56c95d4670f97c66e9cfcf52b6209f954a284b21 (diff) | |
parent | 977182943de4e3824a9178f3f3c114648b227265 (diff) |
Merge pull request #95 from vermiculus/commenting
Commenting
-rw-r--r-- | sx-interaction.el | 80 | ||||
-rw-r--r-- | sx-question-list.el | 9 | ||||
-rw-r--r-- | sx-question-mode.el | 12 | ||||
-rw-r--r-- | sx-question.el | 2 | ||||
-rw-r--r-- | sx.el | 12 |
5 files changed, 106 insertions, 9 deletions
diff --git a/sx-interaction.el b/sx-interaction.el index a9203bd..404fb56 100644 --- a/sx-interaction.el +++ b/sx-interaction.el @@ -106,5 +106,85 @@ changes." ;; Display the changes in `data'. (sx--maybe-update-display)))) + +;;; Commenting +(defun sx-comment (data 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)) + (sx-assoc-let data + ;; Get the comment text + (when (eq text 'query) + (setq text (read-string + "Comment text: " + (when .comment_id + (sx--user-@name .owner)))) + (while (< (string-width text) 15) + (setq text (read-string "Comment text (at least 15 characters): " text)))) + ;; If non-interactive, `text' could be anything. + (unless (stringp text) + (error "Comment body must be a string")) + ;; And post + (let ((result + (sx-method-call 'posts + :id (or .post_id .answer_id .question_id) + :submethod "comments/add" + :auth 'warn + :url-method "POST" + :filter sx-browse-filter + :site .site + :keywords `((body ,text))))) + ;; The api returns the new DATA. + (when (> (length result) 0) + (sx--add-comment-to-object + (elt result 0) + (if .post_id + (sx--get-post .post_type .site .post_id) + data)) + ;; Display the changes in `data'. + (sx--maybe-update-display))))) + +(defun sx--get-post (type site id) + "Find in the database a post identified by TYPE, SITE and ID. +TYPE is `question' or `answer'. +SITE is a string. +ID is an integer." + (let ((db (cons sx-question-mode--data + sx-question-list--dataset))) + (setq db + (cond + ((string= type "question") db) + ((string= type "answer") + (apply #'cl-map 'list #'identity + (mapcar (lambda (x) (cdr (assoc 'answers x))) db))))) + (car (cl-member-if + (lambda (x) (sx-assoc-let x + (and (equal (or .answer_id .question_id) id) + (equal .site site)))) + db)))) + +(defun sx--add-comment-to-object (comment object) + "Add COMMENT to OBJECT's `comments' property. +OBJECT can be a question or an answer." + (let ((com-cell (assoc 'comments object)) + (count-cell (assoc 'comment_count object))) + (if com-cell + (progn + (setcdr + com-cell + (apply #'vector + (append + (cl-map 'list #'identity + (cdr com-cell)) + (list comment))))) + ;; No previous comments, add it manually. + (setcdr object (cons (car object) (cdr object))) + (setcar object `(comments . [,comment]))))) + (provide 'sx-interaction) ;;; sx-interaction.el ends here diff --git a/sx-question-list.el b/sx-question-list.el index 4d7681b..2965ede 100644 --- a/sx-question-list.el +++ b/sx-question-list.el @@ -427,8 +427,10 @@ This does not update `sx-question-mode--window'." (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)))) + (let ((list + (cl-map 'list #'identity + (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. @@ -436,7 +438,8 @@ This does not update `sx-question-mode--window'." ;; And update the dataset. ;; @TODO: Check for duplicates. (setq sx-question-list--dataset - (append sx-question-list--dataset list)) + (append sx-question-list--dataset + list)) (sx-question-list-refresh 'redisplay 'no-update) (forward-line 1))))) diff --git a/sx-question-mode.el b/sx-question-mode.el index f1a8cc0..70b8866 100644 --- a/sx-question-mode.el +++ b/sx-question-mode.el @@ -499,11 +499,12 @@ Prefix argument N moves N sections down or up." (unless (and (overlayp ov) (overlay-get ov 'invisible)) (cl-decf count))))) - (when sx-question-mode-recenter-line - (let ((ov (car-safe (sx-question-mode--section-overlays-at (line-end-position))))) - (when (and (overlayp ov) (> (overlay-end ov) (window-end))) - (recenter sx-question-mode-recenter-line)))) - (sx-message-help-echo)) + (when (equal (selected-window) (get-buffer-window)) + (when sx-question-mode-recenter-line + (let ((ov (car-safe (sx-question-mode--section-overlays-at (line-end-position))))) + (when (and (overlayp ov) (> (overlay-end ov) (window-end))) + (recenter sx-question-mode-recenter-line)))) + (sx-message-help-echo))) (defun sx-question-mode-previous-section (&optional n) "Move down to previous section (question or answer) of this buffer. @@ -571,6 +572,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) + ("c" sx-comment) ("v" sx-visit) ("u" sx-toggle-upvote) ("d" sx-toggle-downvote) diff --git a/sx-question.el b/sx-question.el index de07c94..a7aadb2 100644 --- a/sx-question.el +++ b/sx-question.el @@ -43,7 +43,7 @@ property. "Query SITE for a QUESTION-ID and return it. If QUESTION-ID doesn't exist on SITE, raise an error." (let ((res (sx-method-call 'questions - :id id + :id question-id :site site :auth t :filter sx-browse-filter))) @@ -56,6 +56,7 @@ question.link question.upvoted question.downvoted + question.question_id user.display_name comment.owner comment.body_markdown @@ -65,6 +66,10 @@ comment.creation_date comment.upvoted comment.score + comment.post_type + comment.post_id + comment.comment_id + answer.answer_id answer.last_editor answer.link answer.owner @@ -193,6 +198,13 @@ Return the result of BODY." (add-text-properties p (point) ,properties) result)) +(defun sx--user-@name (user) + "Get the `display_name' of USER prepended with @." + (sx-assoc-let user + (when (stringp .display_name) + (concat "@" .display_name)))) + + ;;; Assoc-let (defun sx--site (data) "Get the site in which DATA belongs. |