From 1afeaf67be32a8ef1599452d09b4cf7b326d0954 Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Mon, 1 Dec 2014 08:45:50 -0500 Subject: Standardize local variables - Move lexical-binding to top of file; fixes #123 - Use indent-tabs-mode: nil for all files --- sx.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index f77b313..8cfb5dc 100644 --- a/sx.el +++ b/sx.el @@ -1,4 +1,4 @@ -;;; sx.el --- StackExchange client. Ask and answer questions on Stack Overflow, Super User, and the likes. -*- lexical-binding: t; -*- +;;; sx.el --- StackExchange client. Ask and answer questions on Stack Overflow, Super User, and the likes -*- lexical-binding: t; -*- ;; Copyright (C) 2014 Sean Allred -- cgit v1.2.3 From a812b209b24401827a7020051ac3726358795231 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Sun, 4 Jan 2015 21:22:42 -0200 Subject: Use defconst instead of defvar where appropriate. Fix #200 --- sx-auth.el | 64 +++++++++++++++++++++++++++-------------------------- sx-favorites.el | 2 +- sx-filter.el | 2 +- sx-inbox.el | 6 ++--- sx-networks.el | 2 +- sx-notify.el | 2 +- sx-question-list.el | 2 +- sx-question-mode.el | 2 +- sx-site.el | 2 +- sx-tag.el | 2 +- sx-time.el | 2 +- sx.el | 2 +- 12 files changed, 46 insertions(+), 44 deletions(-) (limited to 'sx.el') diff --git a/sx-auth.el b/sx-auth.el index 686aa0c..cba310d 100644 --- a/sx-auth.el +++ b/sx-auth.el @@ -47,32 +47,33 @@ what you are doing! This variable is set with `sx-auth-authenticate'.") -(defvar sx-auth-method-auth '((me . t) - (inbox . t) - (notifications . t) - (events . t) - (posts (comments add)) - (comments delete - edit - flags - upvote) - (answers accept - delete - downvote - edit - flags - upvote) - (questions answers - add - close - delete - downvote - edit - favorite - flags - render - upvote - (unanswered my-tags))) +(defconst sx-auth-method-auth + '((me . t) + (inbox . t) + (notifications . t) + (events . t) + (posts (comments add)) + (comments delete + edit + flags + upvote) + (answers accept + delete + downvote + edit + flags + upvote) + (questions answers + add + close + delete + downvote + edit + favorite + flags + render + upvote + (unanswered my-tags))) "List of methods that require auth. Methods are of the form \(METHOD . SUBMETHODS) where SUBMETHODS is \(METHOD METHOD METHOD ...). @@ -80,11 +81,12 @@ Methods are of the form \(METHOD . SUBMETHODS) where SUBMETHODS If all SUBMETHODS require auth or there are no submethods, form will be \(METHOD . t)") -(defvar sx-auth-filter-auth '(question.upvoted - question.downvoted - answer.upvoted - answer.downvoted - comment.upvoted) +(defconst sx-auth-filter-auth + '(question.upvoted + question.downvoted + answer.upvoted + answer.downvoted + comment.upvoted) "List of filter types that require auth. Keywords are of the form \(OBJECT TYPES) where TYPES is \(FILTER FILTER FILTER).") diff --git a/sx-favorites.el b/sx-favorites.el index 7fdc772..d98b4c2 100644 --- a/sx-favorites.el +++ b/sx-favorites.el @@ -30,7 +30,7 @@ (require 'sx-networks) (require 'sx-filter) -(defvar sx-favorite-list-filter +(defconst sx-favorite-list-filter (sx-filter-from-nil (question.question_id))) diff --git a/sx-filter.el b/sx-filter.el index 4695446..57c491d 100644 --- a/sx-filter.el +++ b/sx-filter.el @@ -107,7 +107,7 @@ return the compiled filter." ;;; Browsing filter -(defvar sx-browse-filter +(defconst sx-browse-filter (sx-filter-from-nil ((question body_markdown bounty_amount diff --git a/sx-inbox.el b/sx-inbox.el index 01000a6..1efceb1 100644 --- a/sx-inbox.el +++ b/sx-inbox.el @@ -28,7 +28,7 @@ ;;; API -(defvar sx-inbox-filter +(defconst sx-inbox-filter '((inbox_item.answer_id inbox_item.body inbox_item.comment_id @@ -91,7 +91,7 @@ These are identified by their links.") "List of notification items which are read. These are identified by their links.") -(defvar sx-inbox--header-line +(defconst sx-inbox--header-line '(" " (:propertize "n p j k" face mode-line-buffer-id) ": Navigate" @@ -106,7 +106,7 @@ These are identified by their links.") ": Quit") "Header-line used on the inbox list.") -(defvar sx-inbox--mode-line +(defconst sx-inbox--mode-line '(" " (:propertize (sx-inbox--notification-p diff --git a/sx-networks.el b/sx-networks.el index 2695689..45eaf05 100644 --- a/sx-networks.el +++ b/sx-networks.el @@ -29,7 +29,7 @@ (require 'sx-site) (require 'sx-filter) -(defvar sx-network--user-filter +(defconst sx-network--user-filter (sx-filter-from-nil ((badge_count bronze silver diff --git a/sx-notify.el b/sx-notify.el index 6dc90b9..0c9a5b8 100644 --- a/sx-notify.el +++ b/sx-notify.el @@ -27,7 +27,7 @@ ;;; mode-line notification -(defvar sx-notify--mode-line +(defconst sx-notify--mode-line '((sx-inbox--unread-inbox (sx-inbox--unread-notifications " [")) (sx-inbox--unread-inbox (:propertize diff --git a/sx-question-list.el b/sx-question-list.el index b9f34a0..c72dc0d 100644 --- a/sx-question-list.el +++ b/sx-question-list.el @@ -228,7 +228,7 @@ and thus not displayed in the list of questions. This is ignored if `sx-question-list--refresh-function' is set.") (make-variable-buffer-local 'sx-question-list--dataset) -(defvar sx-question-list--header-line +(defconst sx-question-list--header-line '(" " (:propertize "n p j k" face mode-line-buffer-id) ": Navigate" diff --git a/sx-question-mode.el b/sx-question-mode.el index f702822..5303ebb 100644 --- a/sx-question-mode.el +++ b/sx-question-mode.el @@ -178,7 +178,7 @@ property." ;;; Major-mode -(defvar sx-question-mode--header-line +(defconst sx-question-mode--header-line '(" " (:propertize "n p TAB" face mode-line-buffer-id) ": Navigate" diff --git a/sx-site.el b/sx-site.el index 02f618e..9b2ea34 100644 --- a/sx-site.el +++ b/sx-site.el @@ -28,7 +28,7 @@ (require 'sx-cache) (require 'sx-filter) -(defvar sx-site-browse-filter +(defconst sx-site-browse-filter (sx-filter-from-nil ((site site_type name diff --git a/sx-tag.el b/sx-tag.el index 7ac80c6..5e75890 100644 --- a/sx-tag.el +++ b/sx-tag.el @@ -26,7 +26,7 @@ ;;; Getting the list from a site -(defvar sx-tag-filter +(defconst sx-tag-filter (sx-filter-from-nil (tag.name tag.synonyms)) diff --git a/sx-time.el b/sx-time.el index 1d1267b..9fa0037 100644 --- a/sx-time.el +++ b/sx-time.el @@ -26,7 +26,7 @@ (require 'time-date) -(defvar sx-time-seconds-to-string +(defconst sx-time-seconds-to-string ;; (LIMIT NAME VALUE) ;; We use an entry if the number of seconds in question is less than ;; LIMIT, but more than the previous entry's LIMIT. diff --git a/sx.el b/sx.el index 8cfb5dc..3271755 100644 --- a/sx.el +++ b/sx.el @@ -300,7 +300,7 @@ Return the result of BODY." (push ov sx--overlays)) result)) -(defvar sx--ascii-replacement-list +(defconst sx--ascii-replacement-list '(("[:space:]" . "") ("àåáâäãåą" . "a") ("èéêëę" . "e") -- cgit v1.2.3 From 065ef960b3fcf80ea68dbcbbcca8c276a2d09b07 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 5 Jan 2015 00:53:01 -0200 Subject: Move sx--multiple-read to sx-tag-multiple-read --- sx-search.el | 13 ++++--------- sx-tag.el | 33 +++++++++++++++++++++++++++++++++ sx.el | 18 ------------------ 3 files changed, 37 insertions(+), 27 deletions(-) (limited to 'sx.el') diff --git a/sx-search.el b/sx-search.el index d47905e..8614f49 100644 --- a/sx-search.el +++ b/sx-search.el @@ -32,13 +32,11 @@ (require 'sx) (require 'sx-question-list) +(require 'sx-tag) (defvar sx-search--query-history nil "Query history for interactive prompts.") -(defvar sx-search--tag-history nil - "Tags history for interactive prompts.") - ;;; Basic function (defun sx-search-get-questions (site page query &optional tags excluded-tags keywords) @@ -84,15 +82,12 @@ prefix argument, the user is asked for everything." (when (string= query "") (setq query nil)) (when current-prefix-arg - (setq tags (sx--multiple-read - (format "Tags (%s)" - (if query "optional" "mandatory")) - 'sx-search--tag-history)) + (setq tags (sx-tag-multiple-read + site (format "Tags%s" (if query " (optional)" "")))) (when (and (not query) (string= "" tags)) (sx-user-error "Must supply either QUERY or TAGS")) (setq excluded-tags - (sx--multiple-read - "Excluded tags (optional)" 'sx-search--tag-history))) + (sx-tag-multiple-read site "Excluded tags (optional)"))) (list site query tags excluded-tags))) ;; Here starts the actual function diff --git a/sx-tag.el b/sx-tag.el index 0f726fd..41ed9eb 100644 --- a/sx-tag.el +++ b/sx-tag.el @@ -99,6 +99,39 @@ Return the list of invalid tags in TAGS." :site site)))) (cl-remove-if (lambda (x) (member x result)) tags))) + +;;; Prompt the user for tags. +(defvar sx-tag-history nil + "Tags history for interactive prompts.") + +;;; @TODO: Make it so that hitting BACKSPACE with an empty input +;;; deletes a previously submitted tag. +(defun sx-tag-multiple-read (site prompt &optional initial-value) + "Interactively read a list of tags for SITE. +Call `sx-completing-read' multiple times, until input is empty. +Return a list of tags given by the user. + +PROMPT is a string displayed to the user and should not end with +a space nor a colon. INITIAL-VALUE is a list of already-selected +tags." + (let ((completion-list (sx-tag-list--get site)) + (list initial-value) + input) + (while (not (string= + "" + (setq input (sx-completing-read + (concat prompt " [" + (mapconcat #'identity list ",") + "]: ") + completion-list + (lambda (x) (not (member x list))) + nil + 'require-match + nil + 'sx-tag-history)))) + (push input list)) + list)) + (provide 'sx-tag) ;;; sx-tag.el ends here diff --git a/sx.el b/sx.el index 3271755..9924308 100644 --- a/sx.el +++ b/sx.el @@ -176,24 +176,6 @@ All ARGS are passed to `completing-read' or `ido-completing-read'." (apply (if ido-mode #'ido-completing-read #'completing-read) args)) -(defun sx--multiple-read (prompt hist-var) - "Interactively query the user for a list of strings. -Call `read-string' multiple times, until the input is empty. - -PROMPT is a string displayed to the user and should not end with -a space nor a colon. HIST-VAR is a quoted symbol, indicating a -list in which to store input history." - (let (list input) - (while (not (string= - "" - (setq input (read-string - (concat prompt " [" - (mapconcat #'identity list ",") - "]: ") - "" hist-var)))) - (push input list)) - list)) - (defmacro sx-sorted-insert-skip-first (newelt list &optional predicate) "Inserted NEWELT into LIST sorted by PREDICATE. This is designed for the (site id id ...) lists. So the first car -- cgit v1.2.3 From e061fb947a02290314be7247d81963e7bfd0987b Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Mon, 5 Jan 2015 16:31:10 -0200 Subject: Move define-conditional-key to sx.el --- sx-switchto.el | 12 ------------ sx.el | 12 ++++++++++++ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'sx.el') diff --git a/sx-switchto.el b/sx-switchto.el index 458586a..ed83360 100644 --- a/sx-switchto.el +++ b/sx-switchto.el @@ -54,18 +54,6 @@ ;;; These are keys which depend on context. ;;;; For instance, it makes no sense to have `switch-site' bound to a ;;;; key on a buffer with no `sx-question-list--site' variable. -(defmacro sx--define-conditional-key (keymap key def &rest body) - "In KEYMAP, define key sequence KEY as DEF conditionally. -This is like `define-key', except the definition \"disapears\" -whenever BODY evaluates to nil." - (declare (indent 3) - (debug (form form form &rest sexp))) - `(define-key ,keymap ,key - '(menu-item - ,(format "maybe-%s" (or (car (cdr-safe def)) def)) ignore - :filter (lambda (&optional _) - (when (progn ,@body) ,def))))) - (sx--define-conditional-key sx-switchto-map "s" #'sx-question-list-switch-site (and (boundp 'sx-question-list--site) sx-question-list--site)) diff --git a/sx.el b/sx.el index 9924308..bfc647d 100644 --- a/sx.el +++ b/sx.el @@ -247,6 +247,18 @@ Anything before the (sub)domain is removed." (rx string-start (or (and (0+ word) (optional ":") "//"))) "" url))) +(defmacro sx--define-conditional-key (keymap key def &rest body) + "In KEYMAP, define key sequence KEY as DEF conditionally. +This is like `define-key', except the definition \"disapears\" +whenever BODY evaluates to nil." + (declare (indent 3) + (debug (form form form &rest sexp))) + `(define-key ,keymap ,key + '(menu-item + ,(format "maybe-%s" (or (car (cdr-safe def)) def)) ignore + :filter (lambda (&optional _) + (when (progn ,@body) ,def))))) + ;;; Printing request data (defvar sx--overlays nil -- cgit v1.2.3 From 5b66d7865fb9f160586c7d579f8df7195804e927 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 6 Jan 2015 19:29:46 -0200 Subject: Typo --- sx.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index bfc647d..8680fc3 100644 --- a/sx.el +++ b/sx.el @@ -249,7 +249,7 @@ Anything before the (sub)domain is removed." (defmacro sx--define-conditional-key (keymap key def &rest body) "In KEYMAP, define key sequence KEY as DEF conditionally. -This is like `define-key', except the definition \"disapears\" +This is like `define-key', except the definition \"disappears\" whenever BODY evaluates to nil." (declare (indent 3) (debug (form form form &rest sexp))) -- cgit v1.2.3 From 9c55ae8efcd7a9b9f940d00f9a14dc439a7c225b Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 6 Jan 2015 19:57:22 -0200 Subject: Use site_par instead of site --- sx.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index 3271755..5aec9e5 100644 --- a/sx.el +++ b/sx.el @@ -90,7 +90,7 @@ with a `link' property)." (defun sx--link-to-data (link) "Convert string LINK into data that can be displayed." - (let ((result (list (cons 'site (sx--site link))))) + (let ((result (list (cons 'site_par (sx--site link))))) ;; Try to strip a question or answer ID (when (or ;; Answer -- cgit v1.2.3 From f64d2922ed44dcacd3a0fd06eb494e94bd128bbe Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Tue, 6 Jan 2015 23:02:59 -0200 Subject: Define sx-format-replacements Use FORMAT-STRING to format the values in ALIST. --- sx.el | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'sx.el') diff --git a/sx.el b/sx.el index e080271..6112510 100644 --- a/sx.el +++ b/sx.el @@ -337,6 +337,30 @@ removed from the display name before it is returned." (format "[%s]" (car kar)) (cdr kar) string))) string)) +(defun sx-format-replacements (format alist) + "Use FORMAT-STRING to format the values in ALIST. +ALIST is a list with elements of the form (CHAR . STRING). +The value is a copy of FORMAT-STRING, but with certain constructs +replaced by text as given by ALIST. + +The construct is a `%' character followed by any other character. +The replacement is the STRING corresponding to CHAR in ALIST. + +The %% construct is special, it is replaced with a single %, even +if ALIST contains a different string at the ?% entry." + (let ((alist (cons '(?% . "%") alist))) + (with-temp-buffer + (insert format) + (goto-char (point-min)) + (while (search-forward "%" nil 'noerror) + (delete-char -1) + (unless (eobp) + (insert + (or (cdr (assq (char-after) alist)) + (error "ALIST has no value for `%c'" (char-after)))) + (delete-char 1))) + (buffer-string)))) + (defcustom sx-init-hook nil "Hook run when SX initializes. -- cgit v1.2.3 From 2fed944ba8c3bbf85b4c9eb225ff8a785597521b Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Wed, 7 Jan 2015 12:45:36 -0200 Subject: Improve sx-format-replacements to take a property-alist --- sx.el | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index 6112510..f01a11d 100644 --- a/sx.el +++ b/sx.el @@ -337,14 +337,17 @@ removed from the display name before it is returned." (format "[%s]" (car kar)) (cdr kar) string))) string)) -(defun sx-format-replacements (format alist) +(defun sx-format-replacements (format alist &optional property-alist) "Use FORMAT-STRING to format the values in ALIST. ALIST is a list with elements of the form (CHAR . STRING). The value is a copy of FORMAT-STRING, but with certain constructs replaced by text as given by ALIST. The construct is a `%' character followed by any other character. -The replacement is the STRING corresponding to CHAR in ALIST. +The replacement is the STRING corresponding to CHAR in ALIST. In +addition, if CHAR is also the car of an element in +PROPERTY-ALIST, the cdr of that element should be a list of text +properties which will be applied on the replacement. The %% construct is special, it is replaced with a single %, even if ALIST contains a different string at the ?% entry." @@ -352,12 +355,22 @@ if ALIST contains a different string at the ?% entry." (with-temp-buffer (insert format) (goto-char (point-min)) - (while (search-forward "%" nil 'noerror) - (delete-char -1) - (unless (eobp) - (insert - (or (cdr (assq (char-after) alist)) - (error "ALIST has no value for `%c'" (char-after)))) + (while (search-forward-regexp + (rx "%" (group-n 1 (* (any "-+ #0-9.")))) nil 'noerror) + (let* ((char (char-after)) + ;; Understand flags + (flag (match-string 1)) + (val (cdr-safe (assq char alist)))) + (unless val + (error "Invalid format character: `%%%c'" char)) + ;; Insert first, to preserve text properties. + (insert-and-inherit + (apply #'propertize + (format (concat "%" flag "s") val) + (cdr-safe (assq char property-alist)))) + ;; Delete the specifier body. + (replace-match "") + ;; Delete `char-after'. (delete-char 1))) (buffer-string)))) -- cgit v1.2.3 From c46dd1cde6d8428a73be0f2e6918b701af541004 Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Wed, 7 Jan 2015 15:46:13 -0200 Subject: Fix sx-format-replacements replace-match moves point --- sx.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index f01a11d..4159933 100644 --- a/sx.el +++ b/sx.el @@ -369,7 +369,8 @@ if ALIST contains a different string at the ?% entry." (format (concat "%" flag "s") val) (cdr-safe (assq char property-alist)))) ;; Delete the specifier body. - (replace-match "") + (delete-region (match-beginning 0) + (match-end 0)) ;; Delete `char-after'. (delete-char 1))) (buffer-string)))) -- cgit v1.2.3 From dc98b2bd2a7b805e5d3c8a410bcaf137cd4cf78a Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Wed, 7 Jan 2015 15:54:53 -0200 Subject: sx-format-replacements: Fix propertizing --- sx.el | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index 4159933..d67771b 100644 --- a/sx.el +++ b/sx.el @@ -364,10 +364,10 @@ if ALIST contains a different string at the ?% entry." (unless val (error "Invalid format character: `%%%c'" char)) ;; Insert first, to preserve text properties. - (insert-and-inherit - (apply #'propertize - (format (concat "%" flag "s") val) - (cdr-safe (assq char property-alist)))) + (insert-and-inherit (format (concat "%" flag "s") val)) + (when property-alist + (add-text-properties (match-end 0) (point) + (cdr-safe (assq char property-alist)))) ;; Delete the specifier body. (delete-region (match-beginning 0) (match-end 0)) -- cgit v1.2.3 From 5e29ea61e86c399cb966fc2299566d43694c2cfe Mon Sep 17 00:00:00 2001 From: Artur Malabarba Date: Wed, 7 Jan 2015 16:29:09 -0200 Subject: Move @name to sx-user --- sx-user.el | 42 ++++++++++++++++++++++++++++++++++++++++++ sx.el | 33 --------------------------------- 2 files changed, 42 insertions(+), 33 deletions(-) (limited to 'sx.el') diff --git a/sx-user.el b/sx-user.el index fe620ca..2e8c89a 100644 --- a/sx-user.el +++ b/sx-user.el @@ -148,6 +148,48 @@ the `sx-button-user' category." :type 'sx-button-user) text)))) + +;;; @name conversion +(defconst sx-user--ascii-replacement-list + '(("[:space:]" . "") + ("àåáâäãåą" . "a") + ("èéêëę" . "e") + ("ìíîïı" . "i") + ("òóôõöøőð" . "o") + ("ùúûüŭů" . "u") + ("çćčĉ" . "c") + ("żźž" . "z") + ("śşšŝ" . "s") + ("ñń" . "n") + ("ýÿ" . "y") + ("ğĝ" . "g") + ("ř" . "r") + ("ł" . "l") + ("đ" . "d") + ("ß" . "ss") + ("Þ" . "th") + ("ĥ" . "h") + ("ĵ" . "j") + ("^[:ascii:]" . "")) + "List of replacements to use for non-ascii characters. +Used to convert user names into @mentions.") + +(defun sx-user--@name (user) + "Get the `display_name' of USER prepended with @. +In order to correctly @mention the user, all whitespace is +removed from the display name and a series of unicode conversions +are performed before it is returned +See `sx-user--ascii-replacement-list'. + +If all you need is the @name, this is very slightly faster than +using `sx-user--format'." + (sx-assoc-let user + (if (stringp .display_name) + (concat "@" (sx--recursive-replace + sx-user--ascii-replacement-list .display_name)) + ;; "" + ))) + (provide 'sx-user) ;;; sx-user.el ends here diff --git a/sx.el b/sx.el index d67771b..36ecfca 100644 --- a/sx.el +++ b/sx.el @@ -294,39 +294,6 @@ Return the result of BODY." (push ov sx--overlays)) result)) -(defconst sx--ascii-replacement-list - '(("[:space:]" . "") - ("àåáâäãåą" . "a") - ("èéêëę" . "e") - ("ìíîïı" . "i") - ("òóôõöøőð" . "o") - ("ùúûüŭů" . "u") - ("çćčĉ" . "c") - ("żźž" . "z") - ("śşšŝ" . "s") - ("ñń" . "n") - ("ýÿ" . "y") - ("ğĝ" . "g") - ("ř" . "r") - ("ł" . "l") - ("đ" . "d") - ("ß" . "ss") - ("Þ" . "th") - ("ĥ" . "h") - ("ĵ" . "j") - ("^[:ascii:]" . "")) - "List of replacements to use for non-ascii characters. -Used to convert user names into @mentions.") - -(defun sx--user-@name (user) - "Get the `display_name' of USER prepended with @. -In order to correctly @mention the user, all whitespace is -removed from the display name before it is returned." - (sx-assoc-let user - (when (stringp .display_name) - (concat "@" (sx--recursive-replace - sx--ascii-replacement-list .display_name))))) - (defun sx--recursive-replace (alist string) "Replace each car of ALIST with its cdr in STRING." (if alist -- cgit v1.2.3 From 3328a62d42ff3ca62c31366a4cd0cfd38a3ec663 Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Thu, 15 Jan 2015 00:01:32 -0500 Subject: Create and implement comparator creation macro This obsoletes `sx--<'. --- sx-question-list.el | 10 +++++----- sx.el | 24 +++++++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) (limited to 'sx.el') diff --git a/sx-question-list.el b/sx-question-list.el index 1b7fe5a..5909156 100644 --- a/sx-question-list.el +++ b/sx-question-list.el @@ -322,11 +322,11 @@ into consideration. ;; Add a setter to protect the value. :group 'sx-question-list) -(defun sx-question-list--date-more-recent-p (x y) - "Non-nil if tabulated-entry X is newer than Y." - (sx--< - sx-question-list-date-sort-method - (car x) (car y) #'>)) +(sx--create-comparator sx-question-list--date-more-recent-p + "Non-nil if tabulated-entry A is newer than B." + > (lambda (x) + (cdr (assoc sx-question-list-date-sort-method + (car x))))) ;;; Keybinds diff --git a/sx.el b/sx.el index e080271..87907de 100644 --- a/sx.el +++ b/sx.el @@ -259,6 +259,23 @@ whenever BODY evaluates to nil." :filter (lambda (&optional _) (when (progn ,@body) ,def))))) +(defmacro sx--create-comparator (name doc compare-func get-func) + "Define a new comparator called NAME with documentation DOC. +COMPARE-FUNC is a function that takes the return value of +GET-FUNC and performs the actual comparison." + (declare (indent 1) (doc-string 2)) + (let ((gpf (intern (format " %S--get-prop-function" name))) + (cf (intern (format " %S--compare-function" name)))) + ;; Leading space to hide from completion systems + `(progn + ;; In using `defalias', the macro supports both function + ;; symbols and lambda expressions. + (defalias ',gpf ,get-func) + (defalias ',cf ,compare-func) + (defun ,name (a b) + ,doc + (,cf (,gpf a) (,gpf b)))))) + ;;; Printing request data (defvar sx--overlays nil @@ -349,13 +366,6 @@ 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 predicate) - "Non-nil if PROPERTY attribute of alist X is less than that of Y. -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, -- cgit v1.2.3 From 67f1cd1dc24560a21eef8186590020d26d9e55d7 Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Thu, 15 Jan 2015 00:26:14 -0500 Subject: Fix letbinding `gpf' used to stand for `get-property-function', but this was abstracted into a `get-function'. The letbinding was never changed. This commit also conveniently allows me to say: Fix #226. --- sx.el | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index 87907de..1cfba12 100644 --- a/sx.el +++ b/sx.el @@ -264,17 +264,17 @@ whenever BODY evaluates to nil." COMPARE-FUNC is a function that takes the return value of GET-FUNC and performs the actual comparison." (declare (indent 1) (doc-string 2)) - (let ((gpf (intern (format " %S--get-prop-function" name))) - (cf (intern (format " %S--compare-function" name)))) + (let ((gf (intern (format " %S--get-prop-function" name))) + (cf (intern (format " %S--compare-function" name)))) ;; Leading space to hide from completion systems `(progn ;; In using `defalias', the macro supports both function ;; symbols and lambda expressions. - (defalias ',gpf ,get-func) - (defalias ',cf ,compare-func) + (defalias ',gf ,get-func) + (defalias ',cf ,compare-func) (defun ,name (a b) ,doc - (,cf (,gpf a) (,gpf b)))))) + (,cf (,gf a) (,gf b)))))) ;;; Printing request data -- cgit v1.2.3 From 6c4e7c6b95e8bd7d83e5d0f868d9fb3a70c7a974 Mon Sep 17 00:00:00 2001 From: Sean Allred Date: Fri, 16 Jan 2015 00:45:35 -0500 Subject: Don't define aliases with comparators The aliases were created in the fear that runtime would be slower to interpret the duplicated lambda expressions for get-func. After testing, this was found not to be the case. `funcall' is a much nicer solution. --- sx.el | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'sx.el') diff --git a/sx.el b/sx.el index 1cfba12..829570f 100644 --- a/sx.el +++ b/sx.el @@ -264,17 +264,14 @@ whenever BODY evaluates to nil." COMPARE-FUNC is a function that takes the return value of GET-FUNC and performs the actual comparison." (declare (indent 1) (doc-string 2)) - (let ((gf (intern (format " %S--get-prop-function" name))) - (cf (intern (format " %S--compare-function" name)))) - ;; Leading space to hide from completion systems - `(progn - ;; In using `defalias', the macro supports both function - ;; symbols and lambda expressions. - (defalias ',gf ,get-func) - (defalias ',cf ,compare-func) - (defun ,name (a b) - ,doc - (,cf (,gf a) (,gf b)))))) + `(progn + ;; In using `defalias', the macro supports both function + ;; symbols and lambda expressions. + (defun ,name (a b) + ,doc + (funcall ,compare-func + (funcall ,get-func a) + (funcall ,get-func b))))) ;;; Printing request data -- cgit v1.2.3