diff options
Diffstat (limited to 'sx.el')
-rw-r--r-- | sx.el | 82 |
1 files changed, 53 insertions, 29 deletions
@@ -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))) @@ -70,48 +71,71 @@ 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) - "") - -(defun sx--deep-search (symbol list) - "Non-nil if SYMBOL is contained somewhere inside LIST." +(defun sx--deep-dot-search (data) + "Find symbols somewhere inside DATA which start with a `.'. +Returns a list where each element is a cons cell. The car is the +symbol, the cdr is the symbol without the `.'." (cond - ((symbolp list) - (eq symbol list)) - ((not (listp list)) - nil) - (t - (remove nil (mapcar (lambda (x) (sx--deep-search symbol x)) list))))) + ((symbolp data) + (let ((name (symbol-name data))) + (when (string-match "\\`\\." name) + ;; Return the cons cell inside a list, so it can be appended + ;; with other results in the clause below. + (list (cons data (intern (replace-match "" nil nil name))))))) + ((not (listp data)) nil) + (t (apply + #'append + (remove nil (mapcar #'sx--deep-dot-search data)))))) (defmacro sx-assoc-let (alist &rest body) - "Execute BODY while let-binding api symbols to their values in ALIST. -Any api symbol is any symbol listed in `sx--api-symbols'. Only -those present in BODY are letbound, which leads to optimal -performance. + "Execute BODY while let-binding dotted symbols to their values in ALIST. +Dotted symbol is any symbol starting with a `.'. Only those +present in BODY are letbound, which leads to optimal performance. For instance the following code (stack-core-with-data alist - (list title body)) + (list .title .body)) is equivalent to - (let ((title (cdr (assoc 'title alist))) - (body (cdr (assoc 'body alist)))) - (list title body))" + (let ((.title (cdr (assoc 'title alist))) + (.body (cdr (assoc 'body alist)))) + (list .title .body))" (declare (indent 1) (debug t)) - (let ((symbols (cl-member-if - (lambda (x) (sx--deep-search x body)) - sx--api-symbols))) - `(let ,(mapcar (lambda (x) `(,x (cdr (assoc ',x ,alist)))) symbols) + (let ((symbol-alist (sx--deep-dot-search body))) + `(let ,(mapcar (lambda (x) `(,(car x) (cdr (assoc ',(cdr x) ,alist)))) + symbol-alist) ,@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 |