1 ;;; newst-reader.el --- Generic RSS reader functions.
3 ;; Copyright (C) 2003-2015 Free Software Foundation, Inc.
5 ;; Author: Ulf Jasper <ulf.jasper@web.de>
6 ;; Filename: newst-reader.el
7 ;; URL: http://www.nongnu.org/newsticker
8 ;; Time-stamp: "24. September 2011, 15:47:49 (ulf)"
11 ;; ======================================================================
13 ;; This file is part of GNU Emacs.
15 ;; GNU Emacs is free software: you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation, either version 3 of the License, or
18 ;; (at your option) any later version.
20 ;; GNU Emacs is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 ;; GNU General Public License for more details.
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
28 ;; ======================================================================
33 ;; ======================================================================
36 (require 'newst-backend
)
38 ;; ======================================================================
40 ;; ======================================================================
41 (defun newsticker--set-customvar-formatting (symbol value
)
42 "Set newsticker-variable SYMBOL value to VALUE.
43 Calls all actions which are necessary in order to make the new
45 (if (or (not (boundp symbol
))
46 (equal (symbol-value symbol
) value
))
48 ;; something must have changed
50 (when (fboundp 'newsticker--forget-preformatted
)
51 (newsticker--forget-preformatted))))
53 ;; ======================================================================
55 (defgroup newsticker-reader nil
56 "Settings for the feed reader."
59 (defcustom newsticker-frontend
61 "Newsticker frontend for reading news.
62 This must be one of the functions `newsticker-plainview' or
63 `newsticker-treeview'."
64 :type
'(choice :tag
"Frontend"
65 (const :tag
"Single buffer (plainview)" newsticker-plainview
)
66 (const :tag
"Tree view (treeview)" newsticker-treeview
))
67 :group
'newsticker-reader
)
69 ;; image related things
70 (defcustom newsticker-enable-logo-manipulations
72 "If non-nil newsticker manipulates logo images.
73 This enables the following image properties: heuristic mask for all
74 logos, and laplace-conversion for images without new items."
76 :group
'newsticker-reader
)
78 (defcustom newsticker-justification
80 "How to fill item descriptions.
81 If non-nil newsticker calls `fill-region' to wrap long lines in
82 item descriptions. However, if an item description contains HTML
83 text and `newsticker-html-renderer' is non-nil, filling is not
85 :type
'(choice :tag
"Justification"
86 (const :tag
"No filling" nil
)
87 (const :tag
"Left" left
)
88 (const :tag
"Right" right
)
89 (const :tag
"Center" center
)
90 (const :tag
"Full" full
))
91 :set
'newsticker--set-customvar-formatting
92 :group
'newsticker-reader
)
94 (defcustom newsticker-use-full-width
96 "Decides whether to use the full window width when filling.
97 If non-nil newsticker sets `fill-column' so that the whole
98 window is used when filling. See also `newsticker-justification'."
100 :set
'newsticker--set-customvar-formatting
101 :group
'newsticker-reader
)
103 (defcustom newsticker-html-renderer
104 (if (fboundp 'libxml-parse-html-region
)
106 "Function for rendering HTML contents.
107 If non-nil, newsticker.el will call this function whenever it
108 finds HTML-like tags in item descriptions.
109 Possible functions include `shr-render-region', `w3m-region', `w3-region', and
110 `newsticker-htmlr-render'.
111 Newsticker automatically loads the respective package w3m, w3, or
112 htmlr if this option is set."
113 :type
'(choice :tag
"Function"
114 (const :tag
"None" nil
)
115 (const :tag
"SHR" shr-render-region
)
116 (const :tag
"w3" w3-region
)
117 (const :tag
"w3m" w3m-region
)
118 (const :tag
"htmlr" newsticker-htmlr-render
))
119 :set
'newsticker--set-customvar-formatting
120 :group
'newsticker-reader
)
122 (defcustom newsticker-date-format
124 "Format for the date part in item and feed lines.
125 See `format-time-string' for a list of valid specifiers."
127 :set
'newsticker--set-customvar-formatting
128 :group
'newsticker-reader
)
130 (defgroup newsticker-faces nil
131 "Settings for the faces of the feed reader."
132 :group
'newsticker-reader
)
134 (defface newsticker-feed-face
135 '((default :weight bold
:height
1.2)
136 (((class color
) (background dark
)) :foreground
"white")
137 (((class color
) (background light
)) :foreground
"black"))
138 "Face for news feeds."
139 :group
'newsticker-faces
)
141 (defface newsticker-extra-face
142 '((default :slant italic
:height
0.8)
143 (((class color
) (background dark
)) :foreground
"gray50")
144 (((class color
) (background light
)) :foreground
"gray50"))
145 "Face for newsticker dates."
146 :group
'newsticker-faces
)
148 (defface newsticker-enclosure-face
149 '((default :weight bold
)
150 (((class color
) (background dark
)) :background
"orange")
151 (((class color
) (background light
)) :background
"orange"))
152 "Face for enclosed elements."
153 :group
'newsticker-faces
)
155 ;; ======================================================================
156 ;;; Utility functions
157 ;; ======================================================================
158 (defun newsticker--insert-enclosure (item keymap
)
159 "Insert enclosure element of a news ITEM into the current buffer.
160 KEYMAP will be applied."
161 (let ((enclosure (newsticker--enclosure item
))
164 (let ((url (cdr (assoc 'url enclosure
)))
165 (length (string-to-number (or (cdr (assoc 'length enclosure
))
167 (type (cdr (assoc 'type enclosure
))))
168 (cond ((> length
1048576)
169 (insert (format "Enclosed file (%s, %1.2f MBytes)" type
170 (/ length
1048576))))
172 (insert (format "Enclosed file (%s, %1.2f KBytes)" type
175 (insert (format "Enclosed file (%s, %1.2f Bytes)" type
178 (insert (format "Enclosed file (%s, unknown size)" type
))))
179 (add-text-properties beg
(point)
180 (list 'mouse-face
'highlight
183 "mouse-2: visit (%s)" url
)
189 (defun newsticker--print-extra-elements (item keymap
)
190 "Insert extra-elements of ITEM in a pretty form into the current buffer.
192 (let ((ignored-elements '(items link title description content
193 content
:encoded dc
:subject
194 dc
:date entry item guid pubDate
197 (left-column-width 1))
198 (mapc (lambda (extra-element)
199 (when (listp extra-element
) ;; take care of broken xml
201 (unless (memq (car extra-element
) ignored-elements
)
202 (setq left-column-width
(max left-column-width
204 (car extra-element
))))))))
205 (newsticker--extra item
))
206 (mapc (lambda (extra-element)
207 (when (listp extra-element
) ;; take care of broken xml
209 (unless (memq (car extra-element
) ignored-elements
)
210 (newsticker--do-print-extra-element extra-element
213 (newsticker--extra item
))))
215 (defun newsticker--do-print-extra-element (extra-element width keymap
)
216 "Actually print an EXTRA-ELEMENT using the given WIDTH.
218 (let ((name (symbol-name (car extra-element
))))
219 (insert (format "%s: " name
))
220 (insert (make-string (- width
(length name
)) ?
)))
221 (let (;;(attributes (cadr extra-element)) ;FIXME!!!!
222 (contents (cddr extra-element
)))
223 (cond ((listp contents
)
226 (string-match "^http://.*" i
))
228 (insert i
" ") ; avoid self-reference from the
232 (list 'mouse-face
'highlight
235 (format "mouse-2: visit (%s)" i
)
237 (insert (format "%s" i
))))
240 (insert (format "%s" contents
))))
243 (defun newsticker--image-read (feed-name-symbol disabled
)
244 "Read the cached image for FEED-NAME-SYMBOL from disk.
245 If DISABLED is non-nil the image will be converted to a disabled look
246 \(unless `newsticker-enable-logo-manipulations' is not t\).
248 (let ((image-name (concat (newsticker--images-dir)
249 (symbol-name feed-name-symbol
)))
251 (when (file-exists-p image-name
)
252 (condition-case error-data
253 (setq img
(create-image
255 :conversion
(and newsticker-enable-logo-manipulations
258 :mask
(and newsticker-enable-logo-manipulations
262 (message "Error: cannot create image for %s: %s"
263 feed-name-symbol error-data
))))
266 ;; the functions we need for retrieval and display
268 (defun newsticker-show-news ()
269 "Start reading news. You may want to bind this to a key."
271 (newsticker-start t
) ;; will start only if not running
272 ;; Load the html rendering packages
273 (if newsticker-html-renderer
274 (cond ((eq newsticker-html-renderer
'w3m-region
)
276 ((eq newsticker-html-renderer
'w3-region
)
278 ((eq newsticker-html-renderer
'newsticker-htmlr-render
)
280 (funcall newsticker-frontend
))
282 ;; ======================================================================
284 ;; ======================================================================
286 (defun newsticker-browse-url-item (feed item
)
287 "Convert FEED ITEM to html and call `browse-url' on result."
289 (let ((t-file (make-temp-file "newsticker")))
290 (with-temp-file t-file
291 (insert "<?xml version=\"1.0\" encoding=\"utf-8\"?>
292 <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"
293 \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">
294 <html xmlns=\"http://www.w3.org/1999/xhtml\">
296 (insert "<h1>" feed
": " (newsticker--title item
) "</h1>")
297 (insert (format-time-string newsticker-date-format
298 (newsticker--time item
)))
300 (insert (or (newsticker--desc item
) "[No Description]"))
301 (when (newsticker--enclosure item
)
302 (insert "<br/><hr/><i>")
303 (newsticker--insert-enclosure item nil
)
305 (when (newsticker--extra item
)
306 (insert "<br/><hr/><tt>")
307 (newsticker--print-extra-elements item nil
)
309 (insert "</body></html>"))
310 (browse-url t-file
)))
312 (provide 'newst-reader
)
314 ;;; newst-reader.el ends here