Commit | Line | Data |
---|---|---|
2900b2d8 | 1 | ;;; newst-reader.el --- Generic RSS reader functions. |
2415d4c6 | 2 | |
acaf905b | 3 | ;; Copyright (C) 2003-2012 Free Software Foundation, Inc. |
2415d4c6 | 4 | |
2415d4c6 | 5 | ;; Author: Ulf Jasper <ulf.jasper@web.de> |
2900b2d8 | 6 | ;; Filename: newst-reader.el |
2415d4c6 | 7 | ;; URL: http://www.nongnu.org/newsticker |
2ac2721a | 8 | ;; Time-stamp: "24. September 2011, 15:47:49 (ulf)" |
bd78fa1d | 9 | ;; Package: newsticker |
2415d4c6 UJ |
10 | |
11 | ;; ====================================================================== | |
12 | ||
faeb9c70 GM |
13 | ;; This file is part of GNU Emacs. |
14 | ||
2415d4c6 UJ |
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. | |
19 | ||
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. | |
24 | ||
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/>. | |
27 | ||
28 | ;; ====================================================================== | |
29 | ;;; Commentary: | |
30 | ||
31 | ;; See newsticker.el | |
32 | ||
33 | ;; ====================================================================== | |
34 | ;;; Code: | |
35 | ||
8e39154d | 36 | (require 'newst-backend) |
2415d4c6 UJ |
37 | |
38 | ;; ====================================================================== | |
39 | ;;; Customization | |
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 | |
44 | value effective." | |
45 | (if (or (not (boundp symbol)) | |
46 | (equal (symbol-value symbol) value)) | |
47 | (set symbol value) | |
48 | ;; something must have changed | |
49 | (set symbol value) | |
50 | (when (fboundp 'newsticker--forget-preformatted) | |
51 | (newsticker--forget-preformatted)))) | |
52 | ||
53 | ;; ====================================================================== | |
54 | ;; reader | |
55 | (defgroup newsticker-reader nil | |
56 | "Settings for the feed reader." | |
57 | :group 'newsticker) | |
58 | ||
59 | (defcustom newsticker-frontend | |
60 | 'newsticker-treeview | |
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) | |
68 | ||
69 | ;; image related things | |
70 | (defcustom newsticker-enable-logo-manipulations | |
71 | t | |
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." | |
75 | :type 'boolean | |
76 | :group 'newsticker-reader) | |
77 | ||
78 | (defcustom newsticker-justification | |
79 | 'left | |
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 | |
84 | done." | |
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) | |
93 | ||
94 | (defcustom newsticker-use-full-width | |
95 | t | |
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'." | |
99 | :type 'boolean | |
100 | :set 'newsticker--set-customvar-formatting | |
101 | :group 'newsticker-reader) | |
102 | ||
103 | (defcustom newsticker-html-renderer | |
104 | nil | |
105 | "Function for rendering HTML contents. | |
2ac2721a UJ |
106 | If non-nil, newsticker.el will call this function whenever it |
107 | finds HTML-like tags in item descriptions. Possible functions | |
108 | are `w3m-region', `w3-region', and `newsticker-htmlr-render'. | |
109 | Newsticker automatically loads the respective package w3m, w3, or | |
110 | htmlr if this option is set." | |
2415d4c6 UJ |
111 | :type '(choice :tag "Function" |
112 | (const :tag "None" nil) | |
113 | (const :tag "w3" w3-region) | |
114 | (const :tag "w3m" w3m-region) | |
115 | (const :tag "htmlr" newsticker-htmlr-render)) | |
116 | :set 'newsticker--set-customvar-formatting | |
117 | :group 'newsticker-reader) | |
118 | ||
119 | (defcustom newsticker-date-format | |
120 | "(%A, %H:%M)" | |
121 | "Format for the date part in item and feed lines. | |
122 | See `format-time-string' for a list of valid specifiers." | |
123 | :type 'string | |
124 | :set 'newsticker--set-customvar-formatting | |
125 | :group 'newsticker-reader) | |
126 | ||
0d00764a UJ |
127 | (defgroup newsticker-faces nil |
128 | "Settings for the faces of the feed reader." | |
129 | :group 'newsticker-reader) | |
130 | ||
131 | (defface newsticker-feed-face | |
132 | '((((class color) (background dark)) | |
42c7e61e | 133 | (:family "sans" :bold t :height 1.2 :foreground "white")) |
0d00764a | 134 | (((class color) (background light)) |
42c7e61e | 135 | (:family "sans" :bold t :height 1.2 :foreground "black"))) |
0d00764a UJ |
136 | "Face for news feeds." |
137 | :group 'newsticker-faces) | |
138 | ||
139 | (defface newsticker-extra-face | |
140 | '((((class color) (background dark)) | |
141 | (:italic t :foreground "gray50" :height 0.8)) | |
142 | (((class color) (background light)) | |
143 | (:italic t :foreground "gray50" :height 0.8))) | |
144 | "Face for newsticker dates." | |
145 | :group 'newsticker-faces) | |
146 | ||
147 | (defface newsticker-enclosure-face | |
148 | '((((class color) (background dark)) | |
149 | (:bold t :background "orange")) | |
150 | (((class color) (background light)) | |
151 | (:bold t :background "orange"))) | |
152 | "Face for enclosed elements." | |
153 | :group 'newsticker-faces) | |
154 | ||
2415d4c6 UJ |
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)) | |
162 | (beg (point))) | |
163 | (when enclosure | |
164 | (let ((url (cdr (assoc 'url enclosure))) | |
165 | (length (string-to-number (or (cdr (assoc 'length enclosure)) | |
166 | "-1"))) | |
167 | (type (cdr (assoc 'type enclosure)))) | |
168 | (cond ((> length 1048576) | |
169 | (insert (format "Enclosed file (%s, %1.2f MBytes)" type | |
170 | (/ length 1048576)))) | |
171 | ((> length 1024) | |
172 | (insert (format "Enclosed file (%s, %1.2f KBytes)" type | |
173 | (/ length 1024)))) | |
174 | ((> length 0) | |
175 | (insert (format "Enclosed file (%s, %1.2f Bytes)" type | |
176 | length))) | |
177 | (t | |
178 | (insert (format "Enclosed file (%s, unknown size)" type)))) | |
179 | (add-text-properties beg (point) | |
180 | (list 'mouse-face 'highlight | |
181 | 'nt-link url | |
182 | 'help-echo (format | |
183 | "mouse-2: visit (%s)" url) | |
184 | 'keymap keymap | |
185 | 'nt-face 'enclosure | |
186 | 'nt-type 'desc)) | |
187 | (insert "\n"))))) | |
188 | ||
189 | (defun newsticker--print-extra-elements (item keymap) | |
190 | "Insert extra-elements of ITEM in a pretty form into the current buffer. | |
191 | KEYMAP is applied." | |
192 | (let ((ignored-elements '(items link title description content | |
193 | content:encoded dc:subject | |
194 | dc:date entry item guid pubDate | |
195 | published updated | |
196 | enclosure)) | |
197 | (left-column-width 1)) | |
198 | (mapc (lambda (extra-element) | |
199 | (when (listp extra-element) ;; take care of broken xml | |
200 | ;; data, 2007-05-25 | |
201 | (unless (memq (car extra-element) ignored-elements) | |
202 | (setq left-column-width (max left-column-width | |
203 | (length (symbol-name | |
204 | (car extra-element)))))))) | |
205 | (newsticker--extra item)) | |
206 | (mapc (lambda (extra-element) | |
207 | (when (listp extra-element) ;; take care of broken xml | |
208 | ;; data, 2007-05-25 | |
209 | (unless (memq (car extra-element) ignored-elements) | |
210 | (newsticker--do-print-extra-element extra-element | |
211 | left-column-width | |
212 | keymap)))) | |
213 | (newsticker--extra item)))) | |
214 | ||
215 | (defun newsticker--do-print-extra-element (extra-element width keymap) | |
216 | "Actually print an EXTRA-ELEMENT using the given WIDTH. | |
217 | KEYMAP is applied." | |
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) | |
224 | (mapc (lambda (i) | |
225 | (if (and (stringp i) | |
226 | (string-match "^http://.*" i)) | |
227 | (let ((pos (point))) | |
228 | (insert i " ") ; avoid self-reference from the | |
229 | ; nt-link thing | |
230 | (add-text-properties | |
231 | pos (point) | |
232 | (list 'mouse-face 'highlight | |
233 | 'nt-link i | |
234 | 'help-echo | |
235 | (format "mouse-2: visit (%s)" i) | |
236 | 'keymap keymap))) | |
237 | (insert (format "%s" i)))) | |
238 | contents)) | |
239 | (t | |
240 | (insert (format "%s" contents)))) | |
241 | (insert "\n"))) | |
242 | ||
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\). | |
247 | Return the image." | |
a59c6c51 | 248 | (let ((image-name (concat (newsticker--images-dir) |
2415d4c6 UJ |
249 | (symbol-name feed-name-symbol))) |
250 | (img nil)) | |
251 | (when (file-exists-p image-name) | |
252 | (condition-case error-data | |
253 | (setq img (create-image | |
254 | image-name nil nil | |
255 | :conversion (and newsticker-enable-logo-manipulations | |
256 | disabled | |
257 | 'disabled) | |
258 | :mask (and newsticker-enable-logo-manipulations | |
259 | 'heuristic) | |
260 | :ascent 70)) | |
261 | (error | |
262 | (message "Error: cannot create image for %s: %s" | |
263 | feed-name-symbol error-data)))) | |
264 | img)) | |
265 | ||
266 | ;; the functions we need for retrieval and display | |
267 | ;;;###autoload | |
268 | (defun newsticker-show-news () | |
269 | "Start reading news. You may want to bind this to a key." | |
270 | (interactive) | |
271 | (newsticker-start t) ;; will start only if not running | |
2ac2721a UJ |
272 | ;; Load the html rendering packages |
273 | (if newsticker-html-renderer | |
274 | (cond ((eq newsticker-html-renderer 'w3m-region) | |
275 | (require 'w3m)) | |
276 | ((eq newsticker-html-renderer 'w3-region) | |
277 | (require 'w3-auto)) | |
278 | ((eq newsticker-html-renderer 'newsticker-htmlr-render) | |
279 | (require 'htmlr)))) | |
2415d4c6 UJ |
280 | (funcall newsticker-frontend)) |
281 | ||
282 | ;; ====================================================================== | |
283 | ;;; Toolbar | |
284 | ;; ====================================================================== | |
2415d4c6 | 285 | |
62c4fff6 UJ |
286 | (defun newsticker-browse-url-item (feed item) |
287 | "Convert FEED ITEM to html and call `browse-url' on result." | |
288 | (interactive) | |
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\"> | |
295 | <body>") | |
296 | (insert "<h1>" feed ": " (newsticker--title item) "</h1>") | |
297 | (insert (format-time-string newsticker-date-format | |
298 | (newsticker--time item))) | |
299 | (insert "<br/>") | |
300 | (insert (or (newsticker--desc item) "[No Description]")) | |
301 | (when (newsticker--enclosure item) | |
302 | (insert "<br/><hr/><i>") | |
303 | (newsticker--insert-enclosure item nil) | |
304 | (insert "</i>")) | |
305 | (when (newsticker--extra item) | |
306 | (insert "<br/><hr/><tt>") | |
307 | (newsticker--print-extra-elements item nil) | |
308 | (insert "</tt>")) | |
309 | (insert "</body></html>")) | |
310 | (browse-url t-file))) | |
311 | ||
8e39154d | 312 | (provide 'newst-reader) |
041fa0d4 | 313 | |
2900b2d8 | 314 | ;;; newst-reader.el ends here |