From 1207f47bd2340922268a1340601d45e6c336c11a Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Fri, 7 Nov 2014 18:51:23 -0500 Subject: Introduce initialization logic and hooks --- sx.el | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'sx.el') diff --git a/sx.el b/sx.el index a1e504e..abf1ca8 100644 --- a/sx.el +++ b/sx.el @@ -112,6 +112,33 @@ is equivalent to `(let ,(mapcar (lambda (x) `(,x (cdr (assoc ',x ,alist)))) symbols) ,@body))) +(defcustom sx-init-hook nil + "Hook run when stack-mode initializes. + +Run after `sx-init--internal-hook'.") + +(defvar sx-init--internal-hook nil + "Hook run when stack-mode initializes. + +This is used internally to set initial values for variables such +as filters.") + +(defmacro sx-init-variable (variable value &optional setter) + "Set VARIABLE to VALUE using SETTER. +SETTER should be a function of two arguments. If SETTER is nil, +`set' is used." + (eval + `(add-hook + 'sx-init--internal-hook + (lambda () + (,(or setter #'setq) ,variable ,value)))) + nil) + +(defun stack-initialize () + (run-hooks + 'sx-init--internal-hook + 'sx-init-hook)) + (provide 'sx) ;;; sx.el ends here -- cgit v1.2.3 From 611a00ffcd36915e7927c574dfdaec44d0c0fa58 Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Sat, 8 Nov 2014 14:17:24 -0500 Subject: Delineate and alphabetize API symbols It's ugly to look at, but diffs will be more precise. --- sx.el | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index abf1ca8..54ad8d0 100644 --- a/sx.el +++ b/sx.el @@ -71,11 +71,41 @@ a string, just return it." ;;; Interpreting request data (defvar sx--api-symbols - '(accept_rate answer_count answer_id answers body body_markdown close_vote_count upvoted downvoted - comment_count comment_id creation_date delete_vote_count display_name - edited favorite_count is_accepted is_answered last_activity_date - last_edit_date last_editor link owner profile_image question_id - reopen_vote_count reputation score tags title user_id user_type view_count) + '( + accept_rate + answer_count + answer_id + answers + body + body_markdown + close_vote_count + comment_count + comment_id + creation_date + delete_vote_count + display_name + downvoted + edited + favorite_count + is_accepted + is_answered + last_activity_date + last_edit_date + last_editor + link + owner + profile_image + question_id + reopen_vote_count + reputation + score + tags + title + upvoted + user_id + user_type + view_count + ) "") (defun sx--deep-search (symbol list) -- cgit v1.2.3 From 6aa21b85ace92b01676c6da66372b409fe639920 Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Sat, 8 Nov 2014 15:49:17 -0500 Subject: Abstract out method calls Keeping method calls within `sx-request.el' was causing circular requirements. This commit sorts through all of the requirements for each of the files and ensures that this does not happen. Much of the content removed was for `sx-request-default-keyword-arguments-alist' and related items. It was unused, so it was pruned. If it is deemed necessary in the future, it should be included in `sx-method.el'. --- sx-auth.el | 19 +++++------ sx-filter.el | 4 +-- sx-method.el | 48 ++++++++++++++++++++++++++ sx-question-list.el | 6 ++-- sx-question.el | 6 ++-- sx-request.el | 98 +++++++++++++++++------------------------------------ sx.el | 3 +- test/tests.el | 1 + 8 files changed, 99 insertions(+), 86 deletions(-) create mode 100644 sx-method.el (limited to 'sx.el') diff --git a/sx-auth.el b/sx-auth.el index 049827d..7912508 100644 --- a/sx-auth.el +++ b/sx-auth.el @@ -50,16 +50,15 @@ questions)." (interactive) (setq sx-auth-access-token - (let* ((sx-request-api-root sx-auth-root) - (url (sx-request--build - "dialog" - `((client_id . ,sx-auth-client-id) - (scope . (read_inbox - no_expiry - write_access)) - (redirect_uri . ,(url-hexify-string - sx-auth-redirect-uri))) - ","))) + (let ((url (sx-request-build + "dialog" + `((client_id . ,sx-auth-client-id) + (scope . (read_inbox + no_expiry + write_access)) + (redirect_uri . ,(url-hexify-string + sx-auth-redirect-uri))) + "," sx-auth-root))) (browse-url url) (read-string "Enter the access token displayed on the webpage: "))) (if (string-equal "" sx-auth-access-token) diff --git a/sx-filter.el b/sx-filter.el index 0ba8186..4ed3dbe 100644 --- a/sx-filter.el +++ b/sx-filter.el @@ -28,6 +28,7 @@ (require 'sx) (require 'sx-cache) +(require 'sx-request) ;;; Customizations @@ -53,8 +54,7 @@ or string." "filter/create" keyword-arguments))) (url-hexify-string - (cdr (assoc 'filter - (elt response 0))))))) + (cdr (assoc 'filter (elt response 0))))))) ;;; Storage and Retrieval diff --git a/sx-method.el b/sx-method.el new file mode 100644 index 0000000..8dc5a65 --- /dev/null +++ b/sx-method.el @@ -0,0 +1,48 @@ +;;; sx-request.el --- requests for stack-mode + +;; Copyright (C) 2014 Sean Allred + +;; Author: Sean Allred +;; Keywords: + +;; 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 . + +;;; Commentary: + +;; + +;;; Code: +(require 'json) +(require 'url) +(require 'sx) +(require 'sx-request) +(require 'sx-filter) + +(defun sx-method-call + (method &optional keyword-arguments filter silent) + "Call METHOD with KEYWORD-ARGUMENTS using FILTER. + +If SILENT is non-nil, no messages will be printed. + +Return the entire response as a complex alist." + (sx-request-make + method + (cons (cons 'filter + (sx-filter-get-var + (cond (filter filter) + ((boundp 'stack-filter) stack-filter)))) + keyword-arguments))) + +(provide 'sx-method) +;;; sx-request.el ends here diff --git a/sx-question-list.el b/sx-question-list.el index 86e9194..caf24b1 100644 --- a/sx-question-list.el +++ b/sx-question-list.el @@ -20,11 +20,13 @@ ;;; Commentary: ;;; Code: -(require 'sx-question) -(require 'sx-time) (require 'tabulated-list) (require 'cl-lib) +(require 'sx) +(require 'sx-time) +(require 'sx-question) + ;;; Customization (defcustom sx-question-list-height 12 diff --git a/sx-question.el b/sx-question.el index 8957e6f..20a71cc 100644 --- a/sx-question.el +++ b/sx-question.el @@ -27,16 +27,14 @@ (require 'sx) (require 'sx-filter) (require 'sx-lto) -(require 'sx-request) +(require 'sx-method) -;; I don't know why this is here, but it was causing an API request on require. (defvar sx-question-browse-filter - ;; Remember: INCLUDE EXCLUDE BASE '(nil (user.profile_image shallow_user.profile_image))) (defun sx-question-get-questions (site &optional page) "Get the page PAGE of questions from SITE." - (sx-request-make + (sx-method-call "questions" `((site . ,site) (page . ,page)) diff --git a/sx-request.el b/sx-request.el index 3656b94..f987d2c 100644 --- a/sx-request.el +++ b/sx-request.el @@ -1,9 +1,9 @@ -;;; sx-request.el --- requests for stack-mode +;;; sx-request.el --- requests and url manipulation -*- lexical-binding: t; -*- ;; Copyright (C) 2014 Sean Allred -;; Author: Sean Allred -;; Keywords: +;; Author: Sean Allred +;; Keywords: help ;; 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 @@ -23,10 +23,26 @@ ;; ;;; Code: -(require 'json) + (require 'url) +(require 'json) + (require 'sx) -(require 'sx-filter) + + +;;; Variables + +(defconst sx-request-api-key + "0TE6s1tveCpP9K5r5JNDNQ((" + "When passed, this key provides a higher request quota.") + +(defconst sx-request-api-version + "2.2" + "The current version of the API.") + +(defconst sx-request-api-root + (format "http://api.stackexchange.com/%s/" sx-request-api-version) + "The base URL to make requests from.") (defcustom sx-request-silent-p t @@ -51,45 +67,15 @@ recent call. Set by `sx-request-make'.") number, `sx-request-make' will begin printing out the number of requests left every time it finishes a call.") -(defcustom sx-request-default-keyword-arguments-alist - '(("filters/create") - ("sites") - ("questions" (site . emacs)) - (t nil)) - "Keywords to use as the default for a given method. - -The first element of each list is the method call the keywords -apply to. The remaining cons cells (and they must be conses) are -the values for each keyword. - -For each list, if no keywords are provided, the method's -arguments are forced to the default as determined by the API. - -For each cons cell, if the cdr is `nil', then the keyword will be -forced to the default as determined by the API. + +;;; Making Requests -See `sx-request-get-default-keyword-arguments' and -`sx-request-build-keyword-arguments'. -") - -(defconst sx-request-api-version - "2.2" - "The current version of the API.") - -(defconst sx-request-api-root - (format "http://api.stackexchange.com/%s/" sx-request-api-version) - "The base URL to make requests from.") - -(defconst sx-request-api-key - "0TE6s1tveCpP9K5r5JNDNQ((" - "When passed, this key provides a higher request quota.") - -(defun sx-request--make +(defun sx-request-make (method &optional args silent) (let ((url-automatic-caching sx-request-cache-p) (url-inhibit-uncompression t) (silent (or silent sx-request-silent-p)) - (call (sx-request--build + (call (sx-request-build method (cons (cons 'key sx-request-api-key) args)))) @@ -133,30 +119,19 @@ See `sx-request-get-default-keyword-arguments' and (cdr (assoc 'error_name response)) (cdr (assoc 'error_message response)))) (when (< (setq sx-request-remaining-api-requests - (cdr (assoc 'quote_remaining response))) + (cdr (assoc 'quota_remaining response))) sx-request-remaining-api-requests-message-threshold) (sx-message "%d API requests reamining" sx-request-remaining-api-requests)) (cdr (assoc 'items response)))))))) -(defun sx-request-make - (method &optional keyword-arguments filter silent) - "Make a request to the StackExchange API using METHOD and -optional KEYWORD-ARGUMENTS. If no KEYWORD-ARGUMENTS are given, -`sx-default-keyword-arguments-alist' is used. Return the -entire response as a complex alist." - (sx-request--make - method - (cons (cons 'filter - (sx-filter-get-var - (cond (filter filter) - ((boundp 'stack-filter) stack-filter)))) - keyword-arguments))) - -(defun sx-request--build (method keyword-arguments &optional kv-value-sep) + +;;; Support Functions + +(defun sx-request-build (method keyword-arguments &optional kv-value-sep root) "Build the request string that will be used to process REQUEST with the given KEYWORD-ARGUMENTS." - (let ((base (concat sx-request-api-root method)) + (let ((base (concat (or root sx-request-api-root) method)) (args (sx-request--build-keyword-arguments keyword-arguments kv-value-sep))) (if (string-equal "" args) @@ -181,16 +156,5 @@ false, use the symbol `false'. Each element is processed with alist)) "&")) -(defun sx-request--get-default-keyword-arguments (method) - "Gets the correct keyword arguments for METHOD." - (let ((entry (assoc method sx-request-default-keyword-arguments-alist))) - (cdr (or entry (assoc t sx-request-default-keyword-arguments-alist))))) - -;;; @todo sx-request-change-default-keyword-arguments -;;; (method new-keyword-arguments) -;;; @todo sx-request-change-default-keyword-arguments-for-key -;;; (method key new-value) - - (provide 'sx-request) ;;; sx-request.el ends here diff --git a/sx.el b/sx.el index 54ad8d0..2f7b6a7 100644 --- a/sx.el +++ b/sx.el @@ -25,7 +25,8 @@ ;;; Code: -;;; Requirements +;;; Utility Functions + (defun sx-message (format-string &rest args) "Display a message" (message "[stack] %s" (apply #'format format-string args))) diff --git a/test/tests.el b/test/tests.el index 7915ac0..a66394c 100644 --- a/test/tests.el +++ b/test/tests.el @@ -35,6 +35,7 @@ (expand-file-name (format "../../.cask/%s/elpa" emacs-version) sx-test-data-dir)) (package-initialize) + (require 'cl-lib) (require 'sx) (require 'sx-question) -- cgit v1.2.3 From b8da42344ebe3f380bb6f615c2ab13bb12c24876 Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Sat, 8 Nov 2014 16:54:51 -0500 Subject: Use macro --- sx-request.el | 22 ++++++++++------------ sx.el | 5 +++++ 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'sx.el') diff --git a/sx-request.el b/sx-request.el index f987d2c..4e2ba5c 100644 --- a/sx-request.el +++ b/sx-request.el @@ -112,18 +112,16 @@ number of requests left every time it finishes a call.") (sx-message "Unable to parse response: %S" response) (error "Response could not be read by `json-read-from-string'"))) ;; If we get here, the response is a valid data structure - (when (assoc 'error_id response) - (error "Request failed: (%s) [%i %s] %S" - method - (cdr (assoc 'error_id response)) - (cdr (assoc 'error_name response)) - (cdr (assoc 'error_message response)))) - (when (< (setq sx-request-remaining-api-requests - (cdr (assoc 'quota_remaining response))) - sx-request-remaining-api-requests-message-threshold) - (sx-message "%d API requests reamining" - sx-request-remaining-api-requests)) - (cdr (assoc 'items response)))))))) + (sx-assoc-let response + (when error_id + (error "Request failed: (%s) [%i %s] %S" + method error_id error_name error_message)) + (when (< (setq sx-request-remaining-api-requests + quota_remaining) + sx-request-remaining-api-requests-message-threshold) + (sx-message "%d API requests reamining" + sx-request-remaining-api-requests)) + items))))))) ;;; Support Functions diff --git a/sx.el b/sx.el index 2f7b6a7..00fda40 100644 --- a/sx.el +++ b/sx.el @@ -87,7 +87,11 @@ a string, just return it." display_name downvoted edited + error_id + error_name + error_message favorite_count + items is_accepted is_answered last_activity_date @@ -97,6 +101,7 @@ a string, just return it." owner profile_image question_id + quota_remaining reopen_vote_count reputation score -- cgit v1.2.3 From 5fcd0dbd2c180b85898f42a7cd24a5835d6e3eda Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Sat, 8 Nov 2014 16:58:58 -0500 Subject: Use macro --- sx-filter.el | 4 ++-- sx.el | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'sx.el') diff --git a/sx-filter.el b/sx-filter.el index 4ed3dbe..aa815a2 100644 --- a/sx-filter.el +++ b/sx-filter.el @@ -53,8 +53,8 @@ or string." (let ((response (sx-request-make "filter/create" keyword-arguments))) - (url-hexify-string - (cdr (assoc 'filter (elt response 0))))))) + (sx-assoc-let (elt response 0) + (url-hexify-string filter))))) ;;; Storage and Retrieval diff --git a/sx.el b/sx.el index 00fda40..6165714 100644 --- a/sx.el +++ b/sx.el @@ -91,6 +91,7 @@ a string, just return it." error_name error_message favorite_count + filter items is_accepted is_answered -- cgit v1.2.3