conf-elfeed.el 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. ;;; Code:
  2. (require 'elfeed)
  3. (require 'elfeed-show)
  4. (require 'elfeed-org)
  5. ;; Control vars
  6. (defcustom distopico:elfeed-update-interval 300
  7. "Feeds update interval."
  8. :group 'elfeed
  9. :type 'integer)
  10. (defcustom distopico:elfeed-update-at-time "9:30"
  11. "Feeds update in specific hour."
  12. :group 'elfeed
  13. :type 'string)
  14. (defcustom distopico:elfeed-update-modeline-interval 60
  15. "Feeds update interval of modeline."
  16. :group 'elfeed
  17. :type 'integer)
  18. (defcustom distopico:elfeed-entry-pane-position 'right
  19. "Position of the popup entry pane."
  20. :group 'elfeed
  21. :type '(choice (const left) (const right) (const top) (const bottom)))
  22. (defcustom distopico:elfeed-entry-pane-size 0.50
  23. "Size (width or height, depending on position) of the popup entry pane."
  24. :group 'elfeed
  25. :type 'number)
  26. (defcustom distopico:elfeed-old-entries-read (elfeed-make-tagger :before "2 weeks ago" :remove 'unread)
  27. "Mark as unread old entries."
  28. :group 'elfeed
  29. :type 'function)
  30. (defvar distopico:elfeed-update-timer nil
  31. "Interval timer object.")
  32. (defvar distopico:elfeed-mode-line-format nil
  33. "Format to display in the mode line.")
  34. ;; Basic
  35. (setq rmh-elfeed-org-files (list "~/Documents/org/feeds.org"))
  36. ;; Tweaks
  37. (setq elfeed-show-entry-switch #'distopico:elfeed-switch-pane
  38. elfeed-show-entry-delete #'distopico:elfeed-delete-pane)
  39. ;; Prevent 'Queue timeout exceeded'
  40. (setf url-queue-timeout 30)
  41. ;; Custom key map
  42. (define-key elfeed-search-mode-map (kbd "C-q") 'distopico:elfeed-close)
  43. (define-key elfeed-search-mode-map (kbd "M-q") 'kill-this-buffer)
  44. (define-key elfeed-search-mode-map "q" 'distopico:elfeed-close)
  45. (define-key elfeed-search-mode-map "f" 'distopico:elfeed-group-filter-unread)
  46. (define-key elfeed-search-mode-map "F" 'distopico:elfeed-group-filter-all)
  47. (define-key elfeed-search-mode-map "i" 'distopico:elfeed-org-update)
  48. (define-key elfeed-search-mode-map "W" 'distopico:elfeed-week)
  49. (define-key elfeed-search-mode-map "B" 'distopico:elfeed-bookmarks)
  50. (define-key elfeed-search-mode-map (kbd "C-b") 'distopico:elfeed-search-toggle-bookmark)
  51. (define-key elfeed-show-mode-map "q" 'distopico:elfeed-delete-pane)
  52. (define-key elfeed-show-mode-map "B" 'distopico:elfeed-show-toggle-bookmark)
  53. (define-key elfeed-show-mode-map (kbd "M-<up>") 'elfeed-show-prev)
  54. (define-key elfeed-show-mode-map (kbd "M-<down>") 'elfeed-show-next)
  55. ;; Functions
  56. (defun distopico:elfeed-open ()
  57. "Custom function to open elfeed and delete others windows."
  58. (interactive)
  59. (let ((elfeed-search-buffer "*elfeed-search*"))
  60. (open-buffer-delete-others elfeed-search-buffer :elfeed-fullscreen 'elfeed t)
  61. (with-current-buffer (get-buffer elfeed-search-buffer)
  62. (unless (eq major-mode 'elfeed-search-mode)
  63. (elfeed-search-mode))
  64. (distopico:elfeed-unread-update))))
  65. (defun distopico:elfeed-close ()
  66. "Restore the previous window configuration and burry buffer."
  67. (interactive)
  68. (bury-buffer-restore-prev :elfeed-fullscreen)
  69. (distopico:elfeed-unread-update))
  70. (defun distopico:elfeed-week ()
  71. "List unread entries of last week."
  72. (interactive)
  73. (elfeed-search-set-filter "@1-week-ago +unread"))
  74. (defun distopico:elfeed-bookmarks ()
  75. "Return entrues with tag `bookmark'."
  76. (interactive)
  77. (elfeed-search-set-filter "+bookmark"))
  78. (defun distopico:elfeed-search-toggle-bookmark (tag)
  79. "Toggle TAG bookmark on all selected entries."
  80. (interactive (list (intern "bookmark")))
  81. (let ((entries (elfeed-search-selected)))
  82. (cl-loop for entry in entries
  83. when (elfeed-tagged-p tag entry)
  84. do (elfeed-untag entry tag)
  85. else do (elfeed-tag entry tag))
  86. (mapc #'elfeed-search-update-entry entries)
  87. (unless (use-region-p) (forward-line))))
  88. (defun distopico:elfeed-show-toggle-bookmark (&rest tag)
  89. "Toggle TAG bookmark to the displayed entry."
  90. (interactive (list (intern "bookmark")))
  91. (let ((entry elfeed-show-entry))
  92. (if (memq 'bookmark (elfeed-entry-tags entry))
  93. (apply #'elfeed-untag entry tag)
  94. (apply #'elfeed-tag entry tag))
  95. (with-current-buffer (elfeed-search-buffer)
  96. (elfeed-search-update-entry entry))
  97. (elfeed-show-refresh)))
  98. (defun distopico:elfeed-switch-pane (buff)
  99. "Display BUFF in a popup window."
  100. (popwin:popup-buffer
  101. buff
  102. :position distopico:elfeed-entry-pane-position
  103. :width distopico:elfeed-entry-pane-size
  104. :height distopico:elfeed-entry-pane-size
  105. :stick t
  106. :dedicated t))
  107. (defun distopico:elfeed-delete-pane (&optional nodelete)
  108. "Delete the *elfeed-entry* split pane, optional `NODELETE'."
  109. (interactive)
  110. (let* ((buff (get-buffer "*elfeed-entry*"))
  111. (window (get-buffer-window buff)))
  112. (kill-buffer buff)
  113. (if(not nodelete)
  114. (delete-window window))))
  115. (defun distopico:elfeed-total-unread ()
  116. "Return total of `unread' entries."
  117. (let ((counts 0))
  118. (with-elfeed-db-visit (e _)
  119. (let ((tags (elfeed-entry-tags e)))
  120. (when (memq 'unread tags)
  121. (dolist (tag tags)
  122. (unless (eq tag 'unread)
  123. (cl-incf counts))))))
  124. counts))
  125. (defun distopico:elfeed-tag-entries (&optional unread)
  126. "Get tag of entries, optional return `UNREAD' also."
  127. (let ((counts (make-hash-table)))
  128. (with-elfeed-db-visit (e _)
  129. (let ((tags (elfeed-entry-tags e)))
  130. (if unread
  131. (progn
  132. (when (memq 'unread tags)
  133. (dolist (tag tags)
  134. (unless (eq tag 'unread)
  135. (cl-incf (gethash tag counts 0))))))
  136. (progn
  137. (dolist (tag tags)
  138. (cl-incf (gethash tag counts 0)))))))
  139. (cl-loop for tag hash-keys of counts using (hash-values count)
  140. collect (cons tag count))))
  141. (defun distopico:elfeed-unread-update ()
  142. "Print tooltip help and icon for unread feeds."
  143. (interactive)
  144. (setq distopico:elfeed-mode-line-format
  145. (let ((unread
  146. (number-to-string (distopico:elfeed-total-unread))))
  147. (let ((unread-string
  148. (if (string= "0" unread) ""
  149. (if (window-system) "--"
  150. (format "[⇑ %s]" unread)))))
  151. (propertize
  152. unread-string
  153. 'display (if (boundp 'img:tron-feed)
  154. img:tron-feed
  155. "⇑")
  156. 'local-map (make-mode-line-mouse-map 'mouse-1 #'distopico:elfeed-open)
  157. 'help-echo (format "elfeed :: %s unread" unread)
  158. ))))
  159. (force-mode-line-update)
  160. (sit-for 0))
  161. (defun distopico:elfeed-group-filter (&optional unread)
  162. "Filter by group, optional show `UNREAD'."
  163. (let ((default-filter
  164. (concat
  165. "@6-months-ago"
  166. (if unread
  167. " +unread"
  168. "")))
  169. (default-value "*NONE*")
  170. tags-alist)
  171. (setq tags-alist
  172. (append
  173. (list (cons default-value default-filter))
  174. (mapcar
  175. #'(lambda (x)
  176. (let ((tag-name (symbol-name (car x)))
  177. (num-str (number-to-string (cdr x))))
  178. (cons (concat tag-name " (" num-str ")")
  179. (concat default-filter " +" tag-name))))
  180. (distopico:elfeed-tag-entries unread))))
  181. (unwind-protect
  182. (let ((elfeed-search-filter-active :live)
  183. (choose (completing-read
  184. (concat "Filter: " default-filter " +")
  185. (mapcar #'car tags-alist)
  186. nil nil nil t default-value)))
  187. (setq elfeed-search-filter
  188. (cdr (assoc choose tags-alist))))
  189. (elfeed-search-update :force))))
  190. (defun distopico:elfeed-group-filter-unread ()
  191. "Show only unread feeds."
  192. (interactive)
  193. (distopico:elfeed-group-filter t))
  194. (defun distopico:elfeed-group-filter-all ()
  195. "Show all feeds."
  196. (interactive)
  197. (distopico:elfeed-group-filter))
  198. (defun distopico:elfeed-org-update ()
  199. "Force to update feed in `org-mode' to elfeed list."
  200. (interactive)
  201. (rmh-elfeed-org-process rmh-elfeed-org-files rmh-elfeed-org-tree-id)
  202. (elfeed-update))
  203. (defun distopico:elfeed-new-entry-hook (entry)
  204. "Run hook after get new feed `ENTRY'."
  205. ;; TODO: notify new entry
  206. (distopico:elfeed-unread-update)
  207. (funcall distopico:elfeed-old-entries-read entry))
  208. (defun distopico:elfeed-init-load-hook ()
  209. "Run hook after load init.el file."
  210. (distopico:elfeed-run)
  211. (distopico:elfeed-mode-line t)
  212. ;; Update elfeed only when idle emacs and in specific hour time
  213. (run-at-time distopico:elfeed-update-at-time nil #'elfeed-update)
  214. (run-with-idle-timer distopico:elfeed-update-interval t #'elfeed-update))
  215. (defun distopico:elfeed-show-mode-hook ()
  216. "Hook when enter in show mode."
  217. (tabbar-local-mode 1)
  218. (buffer-face-set 'message-read-face)
  219. (visual-line-mode))
  220. ;;;###autoload
  221. (defun distopico:elfeed-run ()
  222. "Run elfeed without enter in buffer."
  223. (interactive)
  224. (elfeed-org)
  225. (elfeed)
  226. ;; (distopico:elfeed-org-update)
  227. ;; (let ((elfeed-search-buffer (get-buffer-create "*elfeed-search*")))
  228. ;; (with-current-buffer elfeed-search-buffer
  229. ;; (unless (eq major-mode 'elfeed-search-mode)
  230. ;; (elfeed-search-mode))
  231. ;; (elfeed-search-update)))
  232. )
  233. ;; Custom modes
  234. (define-minor-mode distopico:elfeed-mode-line
  235. "Minor mode Toggle unread feeds display in mode line."
  236. :global t :group 'hardware
  237. (setq distopico:elfeed-mode-line-format "")
  238. (and distopico:elfeed-update-timer (cancel-timer distopico:elfeed-update-timer))
  239. (if (not distopico:elfeed-mode-line-format)
  240. (message "Disabled elfeed mode line..")
  241. (setq distopico:elfeed-update-timer
  242. (run-at-time nil distopico:elfeed-update-modeline-interval #'distopico:elfeed-unread-update))
  243. (distopico:elfeed-unread-update)))
  244. ;; Hooks
  245. (add-hook 'elfeed-show-mode-hook 'distopico:elfeed-show-mode-hook)
  246. (add-hook 'elfeed-new-entry-hook 'distopico:elfeed-new-entry-hook)
  247. (add-hook 'distopico:after-init-load-hook 'distopico:elfeed-init-load-hook)
  248. (provide 'conf-elfeed)
  249. ;;; conf-elfeed.el ends here