Created
March 30, 2014 16:13
-
-
Save cvmat/9875148 to your computer and use it in GitHub Desktop.
A patch for adding a filtering function to twittering-mode.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# HG changeset patch | |
# Parent 05a3cec6c0d2e8b3305e51788f923c69c343bfe3 | |
diff --git a/twittering-mode.el b/twittering-mode.el | |
--- a/twittering-mode.el | |
+++ b/twittering-mode.el | |
@@ -639,6 +639,36 @@ | |
(defvar twittering-relative-retrieval-count-alist '() | |
"An alist for counting retrieval of primary timelines.") | |
+(defvar twittering-excluded-pattern-alist '() | |
+ "*An alist of hidden tweet patterns for each timeline. | |
+Each element looks like: | |
+ (TIMELINE-SPECIFIER (SYM1 . REGEXP1) (SYM2 . REGEXP2) ...). | |
+ | |
+TIMELINE-SPECIFIER must be a string or a list of strings. | |
+Each string is a regexp for specifying timelines. | |
+Following regexps (REGEXP1, REGEXP2, ...) specify which tweet should | |
+be hidden in a certain timeline. | |
+ | |
+In a timeline that matches TIMELINE-SPECIFIER, a tweet is hidden if | |
+its elements specified by SYM1, SYM2, ... match corresponding REGEXP1, REGEXP2, | |
+... respectively. | |
+ | |
+If a timeline matches multiple specifiers, all regexps of matched elements | |
+are effective. | |
+ | |
+For example, if you specify | |
+ '(((\":home\" \":mentions\") (text . \"http://\")) | |
+ (\"^[^:]\" (text . \"sample\") (user-screen-name . \"\\`FOO\\'\")) | |
+ (\"twitter/.*\" (text . \"^aa\"))), | |
+the following tweets are hidden. | |
+ | |
+- tweets including \"http://\" in the home timeline and the mentions timeline, | |
+- tweets that are posted by the user FOO and include \"sample\" | |
+ in user timelines and list timelines, | |
+- tweets including \"aa\" at a beginning of a line in list timelines of | |
+ twitter, such as \"twitter/media\" or \"twitter/support\".") | |
+ | |
+ | |
;;;; | |
;;;; Macro and small utility function | |
;;;; | |
@@ -4918,7 +4948,21 @@ | |
(cond | |
((twittering-timeline-spec-primary-p spec) | |
(if (equal spec base-spec) | |
- base-statuses | |
+ (let ((pattern-list | |
+ (twittering-get-excluded-pattern-list-for-timeline-spec | |
+ spec))) | |
+ (if pattern-list | |
+ (remove | |
+ nil | |
+ (mapcar | |
+ (lambda (status) | |
+ (if (twittering-match-pattern-list status pattern-list) | |
+ (progn | |
+ (debug-printf "Exclude the status: %s" status) | |
+ nil) | |
+ status)) | |
+ base-statuses)) | |
+ base-statuses)) | |
nil)) | |
((eq type 'exclude-if) | |
(let* ((direct-base (car (twittering-get-base-timeline-specs spec))) | |
@@ -4965,6 +5009,68 @@ | |
nil)))) | |
;;;; | |
+;;;; Excluded patterns | |
+;;;; | |
+ | |
+(defun twittering-get-excluded-pattern-list-for-timeline-spec-string (spec-string) | |
+ (let ((entry-list twittering-excluded-pattern-alist)) | |
+ (remove | |
+ nil | |
+ (mapcar | |
+ (lambda (entry) | |
+ (let ((spec-regexp | |
+ (if (listp (car entry)) | |
+ (concat "\\(?:" | |
+ (mapconcat 'identity (car entry) "\\|") | |
+ "\\)") | |
+ (car entry))) | |
+ (pattern-list (cdr entry))) | |
+ (when (string-match spec-regexp spec-string) | |
+ pattern-list))) | |
+ entry-list)))) | |
+ | |
+(defun twittering-get-excluded-pattern-list-for-timeline-spec (spec) | |
+ (when twittering-excluded-pattern-alist | |
+ (let* ((spec-string (twittering-timeline-spec-to-string spec)) | |
+ (short-spec-string (twittering-timeline-spec-to-string spec t)) | |
+ (regexp-list | |
+ (twittering-get-excluded-pattern-list-for-timeline-spec-string | |
+ spec-string))) | |
+ (if (string= spec-string short-spec-string) | |
+ regexp-list | |
+ (append regexp-list | |
+ (twittering-get-excluded-pattern-list-for-timeline-spec-string | |
+ short-spec-string)))))) | |
+ | |
+(defun twittering-match-pattern (status pattern) | |
+ (let* ((rest pattern) | |
+ (matched t)) | |
+ (while (and rest matched) | |
+ (let* ((current (car rest)) | |
+ (sym (car current)) | |
+ (regexp (cdr current)) | |
+ (value (cdr (assq sym status))) | |
+ (value | |
+ (if (eq sym 'text) | |
+ (twittering-make-fontified-tweet-text-with-entity status) | |
+ value))) | |
+ (unless (and (stringp value) | |
+ (string-match regexp value)) | |
+ (setq matched nil)) | |
+ (setq rest (cdr rest)))) | |
+ matched)) | |
+ | |
+(defun twittering-match-pattern-list (status pattern-list) | |
+ (let* ((rest pattern-list) | |
+ (matched nil)) | |
+ (while (and rest (not matched)) | |
+ (let ((current (car rest))) | |
+ (when (twittering-match-pattern status current) | |
+ (setq matched t)) | |
+ (setq rest (cdr rest)))) | |
+ matched)) | |
+ | |
+;;;; | |
;;;; Retrieved statuses (timeline data) | |
;;;; | |
@@ -5033,8 +5139,30 @@ | |
(let ((id1 (cdr (assq 'id status1))) | |
(id2 (cdr (assq 'id status2)))) | |
(twittering-status-id< id2 id1)))))) | |
+ ((eq type :single) | |
+ ;; The timeline spec '(:single) does not correspond to an ordinary | |
+ ;; timeline. It means an unordered set of tweets retrieved by the | |
+ ;; 'retrieve-single-tweet command of `twittering-call-api'. | |
+ ;; If this function is used with the spec '(:single), a specific tweet | |
+ ;; will be required with the user's intention. | |
+ ;; In this case, exclusion by patterns does not required. | |
+ (elt (gethash spec twittering-timeline-data-table) 2)) | |
(t | |
- (elt (gethash spec twittering-timeline-data-table) 2))))) | |
+ (let ((statuses (elt (gethash spec twittering-timeline-data-table) 2)) | |
+ (pattern-list | |
+ (twittering-get-excluded-pattern-list-for-timeline-spec spec))) | |
+ (if pattern-list | |
+ (remove | |
+ nil | |
+ (mapcar | |
+ (lambda (status) | |
+ (if (twittering-match-pattern-list status pattern-list) | |
+ (progn | |
+ (debug-printf "Exclude the status: %s" status) | |
+ nil) | |
+ status)) | |
+ statuses)) | |
+ statuses)))))) | |
(defun twittering-remove-timeline-data (&optional spec) | |
(let ((spec (or spec (twittering-current-timeline-spec)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment