diff options
-rw-r--r-- | sx-question-mode.el | 71 | ||||
-rw-r--r-- | sx-question.el | 11 | ||||
-rw-r--r-- | sx-request.el | 4 | ||||
-rw-r--r-- | sx-site.el | 10 | ||||
-rw-r--r-- | sx-time.el | 2 | ||||
-rw-r--r-- | sx.el | 45 |
6 files changed, 101 insertions, 42 deletions
diff --git a/sx-question-mode.el b/sx-question-mode.el index e436b40..d971a49 100644 --- a/sx-question-mode.el +++ b/sx-question-mode.el @@ -150,14 +150,16 @@ If WINDOW is given, use that to display the buffer." '((((background dark)) :background "#090909") (((background light)) :background "#f4f4f4")) "Face used on the question body in the question buffer. -Shouldn't have a foreground, or this will interfere with + +This shouldn't have a foreground, or this will interfere with font-locking." :group 'sx-question-mode-faces) (defcustom sx-question-mode-last-edit-format " (edited %s ago by %s)" "Format used to describe last edit date in the header. -First %s is replaced with the date, and the second %s with the -editor's name." + +First \"%s\" is replaced with the date and the second \"%s\" with +the editor's name." :type 'string :group 'sx-question-mode) @@ -179,8 +181,9 @@ editor's name." (defcustom sx-question-mode-comments-format "%s: %s\n" "Format used to display comments. -First \"%s\" is replaced with user name. -Second \"%s\" is replaced with the comment." + +First \"%s\" is replaced with user name. Second \"%s\" is +replaced with the comment." :type 'string :group 'sx-question-mode) @@ -194,6 +197,7 @@ Second \"%s\" is replaced with the comment." ;;;; Functions (defun sx-question-mode--print-question (question) "Print a buffer describing QUESTION. + QUESTION must be a data structure returned by `json-read'." ;; Clear the overlays (mapc #'delete-overlay sx-question-mode--overlays) @@ -220,10 +224,11 @@ QUESTION must be a data structure returned by `json-read'." follow-link t) "") -(defun sx-question-mode--print-section (data) - "Print a section corresponding to DATA. -DATA can represent a question or an answer." - (sx-assoc-let data +(defun sx-question-mode--print-section (question-data) + "Print a section corresponding to QUESTION-DATA. + +QUESTION-DATA can represent a question or an answer." + (sx-assoc-let question-data (insert sx-question-mode-header-title (apply #'propertize @@ -291,9 +296,12 @@ DATA can represent a question or an answer." (propertize .display_name 'face 'sx-question-mode-author))) -(defun sx-question-mode--print-comment (data) - "Print the comment described by alist DATA." - (sx-assoc-let data +(defun sx-question-mode--print-comment (comment-data) + "Print the comment described by alist COMMENT-DATA. + +The comment is printed according to +`sx-question-mode-comments-format'." + (sx-assoc-let comment-data (insert (format sx-question-mode-comments-format @@ -309,7 +317,10 @@ DATA can represent a question or an answer." (defmacro sx-question-mode--wrap-in-overlay (properties &rest body) "Execute BODY and wrap any inserted text in an overlay. -Overlay is pushed on `sx-question-mode--overlays' and given PROPERTIES. + +Overlay is pushed on `sx-question-mode--overlays' and given +PROPERTIES. + Return the result of BODY." (declare (indent 1) (debug t)) @@ -323,9 +334,14 @@ Return the result of BODY." result)) (defun sx-question-mode--insert-header (&rest args) - "Insert HEADER and VALUE. -HEADER is given `sx-question-mode-header' face, and value is given FACE. -\(fn header value face [header value face] [header value face] ...)" + "Insert propertized ARGS. + +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. + +Use as (fn header value face + [header value face] ...)" (while args (insert (propertize (pop args) 'face 'sx-question-mode-header) @@ -339,7 +355,7 @@ HEADER is given `sx-question-mode-header' face, and value is given FACE. "String to be displayed as the bullet of markdown list items.") (defun sx-question-mode--fill-and-fontify (text) - "Fill TEXT according to `markdown-mode' and return it." + "Return TEXT filled according to `markdown-mode'." (with-temp-buffer (erase-buffer) (insert text) @@ -397,6 +413,7 @@ HEADER is given `sx-question-mode-header' face, and value is given FACE. (defun sx-question-mode--propertize-link (text url) "Return a link propertized version of string TEXT. + URL is used as 'help-echo and 'url properties." (propertize text @@ -418,22 +435,23 @@ URL is used as 'help-echo and 'url properties." 'action #'sx-question-mode-follow-link)) (defun sx-question-mode-follow-link (&optional pos) - "Follow link at POS or point" + "Follow link at POS. If POS is nil, use `point'." (interactive) (browse-url (or (get-text-property (or pos (point)) 'url) (error "No url under point: %s" (or pos (point)))))) -(defun sx-question-mode-find-reference (id &optional id2) +(defun sx-question-mode-find-reference (id &optional fallback-id) "Find url identified by reference ID in current buffer. -If ID is nil, use ID2 instead." + +If ID is nil, use FALLBACK-ID instead." (save-excursion (save-match-data (goto-char (point-min)) (when (search-forward-regexp (format (rx line-start (0+ blank) "[%s]:" (1+ blank) (group-n 1 (1+ (not blank)))) - (or id id2)) + (or id fallback-id)) nil t) (match-string-no-properties 1))))) @@ -454,8 +472,10 @@ If ID is nil, use ID2 instead." ;; for comments). (defcustom sx-question-mode-recenter-line 1 "Screen line to which we recenter after moving between sections. + This is used as an argument to `recenter', only used if the end of section is outside the window. + If nil, no recentering is performed." :type '(choice (const :tag "Don't recenter" nil) integer) @@ -463,6 +483,7 @@ If nil, no recentering is performed." (defun sx-question-mode-next-section (&optional n) "Move down to next section (question or answer) of this buffer. + Prefix argument N moves N sections down or up." (interactive "p") (let ((count (if n (abs n) 1))) @@ -485,13 +506,16 @@ Prefix argument N moves N sections down or up." (defun sx-question-mode-previous-section (&optional n) "Move down to previous section (question or answer) of this buffer. + Prefix argument N moves N sections up or down." (interactive "p") (sx-question-mode-next-section (- (or n 1)))) (defun sx-question-mode--goto-property-change (prop &optional direction) "Move forward until the value of text-property sx-question-mode--PROP changes. + Return the new value of PROP at point. + If DIRECTION is negative, move backwards instead." (let ((prop (intern (format "sx-question-mode--%s" prop))) (func (if (and (numberp direction) @@ -525,8 +549,10 @@ If DIRECTION is negative, move backwards instead." ;;; Major-mode (define-derived-mode sx-question-mode markdown-mode "Question" - "Major mode for a question and its answers. + "Major mode to display and navigate a question and its answers. + Letters do not insert themselves; instead, they are commands. + \\<sx-question-mode> \\{sx-question-mode}" ;; Determine how to close this window. @@ -559,6 +585,7 @@ Letters do not insert themselves; instead, they are commands. (defun sx-question-mode-refresh () "Refresh currently displayed question. + Queries the API for any changes to the question or its answers or comments, and redisplays it." (interactive) diff --git a/sx-question.el b/sx-question.el index 0342479..827b7c3 100644 --- a/sx-question.el +++ b/sx-question.el @@ -58,17 +58,18 @@ Return a list of questions, each consed with (site SITE). (page . ,page)) sx-question-browse-filter))) -(defun sx-question-get-question (site id) - "Query SITE for a question ID and return it. +(defun sx-question-get-question (site question-id) + "Query SITE for a QUESTION-ID and return it. -If ID doesn't exist on SITE, raise an error." +If QUESTION-ID doesn't exist on SITE, raise an error." (let ((res (sx-method-call - (format "questions/%s" id) + (format "questions/%s" question-id) `((site . ,site)) sx-question-browse-filter))) (if (vectorp res) (elt res 0) - (error "Couldn't find question %S in %S" id site)))) + (error "Couldn't find question %S in %S" + question-id site)))) ;;; Question Properties diff --git a/sx-request.el b/sx-request.el index 0434a7b..b3668fe 100644 --- a/sx-request.el +++ b/sx-request.el @@ -171,7 +171,9 @@ contains a 'vector'. See `sx-request--build-keyword-arguments'." (concat base "?" args)))) (defun sx-request--build-keyword-arguments (alist &optional kv-value-sep) - "Build a \"key=value&key=value&...\"-style string with the elements + "Format ALIST as a key-value joined with KV-VALUE-SEP. + +Build a \"key=value&key=value&...\"-style string with the elements of ALIST. If any value in the alist is `nil', that pair will not be included in the return. If you wish to pass a notion of false, use the symbol `false'. Each element is processed with @@ -19,8 +19,6 @@ ;;; Commentary: -;; - ;;; Code: (require 'sx-method) @@ -43,7 +41,8 @@ related_site.api_site_parameter related_site.relation) nil - none)) + none) + "") (defun sx-site--get-site-list () (sx-cache-get @@ -54,7 +53,10 @@ (defcustom sx-site-favorites nil - "Favorite sites." + "List of favorite sites. + +Each entry is a string corresponding to a single site's +api_site_parameter." :group 'sx-site) (defun sx-site-get-api-tokens () @@ -51,12 +51,14 @@ (defcustom sx-time-date-format-year "%H:%M %e %b %Y" "Format used for dates on a past year. + See also `sx-time-date-format'." :type 'string :group 'sx-time) (defcustom sx-time-date-format "%H:%M - %d %b" "Format used for dates on this year. + See also `sx-time-date-format-year'." :type 'string :group 'sx-time) @@ -28,7 +28,7 @@ ;;; Utility Functions (defun sx-message (format-string &rest args) - "Display a message" + "Display a message." (message "[stack] %s" (apply #'format format-string args))) (defun sx-message-help-echo () @@ -37,8 +37,9 @@ (when echo (message "%s" echo)))) (defun sx--thing-as-string (thing &optional sequence-sep) - "Return a string representation of THING. If THING is already -a string, just return it." + "Return a string representation of THING. + +If THING is already a string, just return it." (cond ((stringp thing) thing) ((symbolp thing) (symbol-name thing)) @@ -48,7 +49,24 @@ a string, just return it." thing (if sequence-sep sequence-sep ";"))))) (defun sx--filter-data (data desired-tree) - "Filters DATA and returns the DESIRED-TREE" + "Filters DATA and returns the DESIRED-TREE. + +For example: + + (sx--filter-data + '((prop1 . value1) + (prop2 . value2) + (prop3 + (test1 . 1) + (test2 . 2)) + (prop4 . t)) + '(prop1 (prop3 test2))) + +would yeild + + ((prop1 . value1) + (prop3 + (test2 . 2)))" (if (vectorp data) (apply #'vector (mapcar (lambda (entry) @@ -58,7 +76,7 @@ a string, just return it." (delq nil (mapcar (lambda (cons-cell) - ;; TODO the resolution of `f' is O(2n) in the worst + ;; @TODO the resolution of `f' is O(2n) in the worst ;; case. It may be faster to implement the same ;; functionality as a `while' loop to stop looking the ;; list once it has found a match. Do speed tests. @@ -78,6 +96,7 @@ a string, just return it." ;;; Interpreting request data (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 @@ -93,11 +112,12 @@ symbol, the cdr is the symbol without the `.'." (remove nil (mapcar #'sx--deep-dot-search data)))))) (defmacro sx-assoc-let (alist &rest body) - "Execute BODY while let-binding dotted symbols to their values in ALIST. + "Execute BODY with dotted symbols let-bound 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 +For instance, the following code (stack-core-with-data alist (list .title .body)) @@ -125,15 +145,17 @@ Run after `sx-init--internal-hook'.") This is used internally to set initial values for variables such as filters.") -(defun sx--< (property x y &optional pred) +(defun sx--< (property x y &optional predicate) "Non-nil if PROPERTY attribute of question X is less than that of Y. -With optional argument predicate, use it instead of `<'." - (funcall (or pred #'<) + +With optional argument PREDICATE, use it instead of `<'." + (funcall (or predicate #'<) (cdr (assoc property x)) (cdr (assoc property y)))) (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 @@ -144,6 +166,9 @@ SETTER should be a function of two arguments. If SETTER is nil, nil) (defun stack-initialize () + "Initialize SX. + +Runs `sx-init--internal-hook' and `sx-init-hook', in that order." (run-hooks 'sx-init--internal-hook 'sx-init-hook)) |