Mercurial > emacs
annotate lisp/net/newsticker-plainview.el @ 95685:ed883167b994
Autoload cookies for newsticker.
author | Ulf Jasper <ulf.jasper@web.de> |
---|---|
date | Sun, 08 Jun 2008 18:44:20 +0000 |
parents | 4ab45b5c92cd |
children | 528d24d928b8 |
rev | line source |
---|---|
95676 | 1 ;;; newsticker-plainview.el --- Single buffer frontend for newsticker. |
2 | |
3 ;; Copyright (C) 2008 Free Software Foundation, Inc. | |
4 | |
5 ;; This file is part of GNU Emacs. | |
6 | |
7 ;; Author: Ulf Jasper <ulf.jasper@web.de> | |
8 ;; Filename: newsticker-plainview.el | |
9 ;; URL: http://www.nongnu.org/newsticker | |
95685
ed883167b994
Autoload cookies for newsticker.
Ulf Jasper <ulf.jasper@web.de>
parents:
95684
diff
changeset
|
10 ;; Time-stamp: "8. Juni 2008, 20:39:46 (ulf)" |
ed883167b994
Autoload cookies for newsticker.
Ulf Jasper <ulf.jasper@web.de>
parents:
95684
diff
changeset
|
11 ;; CVS-Version: $Id: newsticker-plainview.el,v 1.2 2008/06/08 18:09:06 miles Exp $ |
95676 | 12 |
13 ;; ====================================================================== | |
14 | |
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 | |
36 (require 'newsticker-ticker) | |
37 (require 'newsticker-reader) | |
38 (require 'derived) | |
39 (require 'xml) | |
40 | |
41 ;; Silence warnings | |
42 (defvar tool-bar-map) | |
43 (defvar w3-mode-map) | |
44 (defvar w3m-minor-mode-map) | |
45 | |
46 ;; ====================================================================== | |
47 ;;; Customization | |
48 ;; ====================================================================== | |
49 (defgroup newsticker-plainview nil | |
50 "Settings for the simple plain view reader. | |
51 See also `newsticker-plainview-hooks'." | |
52 :group 'newsticker-reader) | |
53 | |
54 | |
55 (defun newsticker--set-customvar-buffer (symbol value) | |
56 "Set newsticker-variable SYMBOL value to VALUE. | |
57 Calls all actions which are necessary in order to make the new | |
58 value effective." | |
59 (if (or (not (boundp symbol)) | |
60 (equal (symbol-value symbol) value)) | |
61 (set symbol value) | |
62 ;; something must have changed | |
63 (set symbol value) | |
64 (newsticker--buffer-set-uptodate nil))) | |
65 | |
66 (defun newsticker--set-customvar-sorting (symbol value) | |
67 "Set newsticker-variable SYMBOL value to VALUE. | |
68 Calls all actions which are necessary in order to make the new | |
69 value effective." | |
70 (if (or (not (boundp symbol)) | |
71 (equal (symbol-value symbol) value)) | |
72 (set symbol value) | |
73 ;; something must have changed | |
74 (set symbol value) | |
75 (message "Applying new sort method...") | |
76 (when (fboundp 'newsticker--cache-sort) (newsticker--cache-sort)) | |
77 (when (fboundp 'newsticker--buffer-set-uptodate) | |
78 (newsticker--buffer-set-uptodate nil)) | |
79 (message "Applying new sort method...done"))) | |
80 | |
81 (defcustom newsticker-sort-method | |
82 'sort-by-original-order | |
83 "Sort method for news items. | |
84 The following sort methods are available: | |
85 * `sort-by-original-order' keeps the order in which the items | |
86 appear in the headline file (please note that for immortal items, | |
87 which have been removed from the news feed, there is no original | |
88 order), | |
89 * `sort-by-time' looks at the time at which an item has been seen | |
90 the first time. The most recent item is put at top, | |
91 * `sort-by-title' will put the items in an alphabetical order." | |
92 :type '(choice | |
93 (const :tag "Keep original order" sort-by-original-order) | |
94 (const :tag "Sort by time" sort-by-time) | |
95 (const :tag "Sort by title" sort-by-title)) | |
96 :set 'newsticker--set-customvar-sorting | |
97 :group 'newsticker-plainview) | |
98 | |
99 (defcustom newsticker-heading-format | |
100 "%l | |
101 %t %d %s" | |
102 "Format string for feed headings. | |
103 The following printf-like specifiers can be used: | |
104 %d The date the feed was retrieved. See `newsticker-date-format'. | |
105 %l The logo (image) of the feed. Most news feeds provide a small | |
106 image as logo. Newsticker can display them, if Emacs can -- | |
107 see `image-types' for a list of supported image types. | |
108 %L The logo (image) of the feed. If the logo is not available | |
109 the title of the feed is used. | |
110 %s The statistical data of the feed. See `newsticker-statistics-format'. | |
111 %t The title of the feed, i.e. its name." | |
112 :type 'string | |
113 :set 'newsticker--set-customvar-formatting | |
114 :group 'newsticker-plainview) | |
115 | |
116 (defcustom newsticker-item-format | |
117 "%t %d" | |
118 "Format string for news item headlines. | |
119 The following printf-like specifiers can be used: | |
120 %d The date the item was (first) retrieved. See `newsticker-date-format'. | |
121 %l The logo (image) of the feed. Most news feeds provide a small | |
122 image as logo. Newsticker can display them, if Emacs can -- | |
123 see `image-types' for a list of supported image types. | |
124 %L The logo (image) of the feed. If the logo is not available | |
125 the title of the feed is used. | |
126 %t The title of the item." | |
127 :type 'string | |
128 :set 'newsticker--set-customvar-formatting | |
129 :group 'newsticker-plainview) | |
130 | |
131 (defcustom newsticker-desc-format | |
132 "%d %c" | |
133 "Format string for news descriptions (contents). | |
134 The following printf-like specifiers can be used: | |
135 %c The contents (description) of the item. | |
136 %d The date the item was (first) retrieved. See | |
137 `newsticker-date-format'." | |
138 :type 'string | |
139 :set 'newsticker--set-customvar-formatting | |
140 :group 'newsticker-plainview) | |
141 | |
142 (defcustom newsticker-statistics-format | |
143 "[%n + %i + %o + %O = %a]" | |
144 "Format for the statistics part in feed lines. | |
145 The following printf-like specifiers can be used: | |
146 %a The number of all items in the feed. | |
147 %i The number of immortal items in the feed. | |
148 %n The number of new items in the feed. | |
149 %o The number of old items in the feed. | |
150 %O The number of obsolete items in the feed." | |
151 :type 'string | |
152 :set 'newsticker--set-customvar-formatting | |
153 :group 'newsticker-plainview) | |
154 | |
155 | |
156 ;; ====================================================================== | |
157 ;; faces | |
158 (defgroup newsticker-faces nil | |
159 "Settings for the faces of the feed reader." | |
160 :group 'newsticker-plainview) | |
161 | |
162 (defface newsticker-feed-face | |
163 '((((class color) (background dark)) | |
164 (:family "helvetica" :bold t :height 1.2 :foreground "misty rose")) | |
165 (((class color) (background light)) | |
166 (:family "helvetica" :bold t :height 1.2 :foreground "black"))) | |
167 "Face for news feeds." | |
168 :group 'newsticker-faces) | |
169 | |
170 (defface newsticker-new-item-face | |
171 '((((class color) (background dark)) | |
172 (:family "helvetica" :bold t)) | |
173 (((class color) (background light)) | |
174 (:family "helvetica" :bold t))) | |
175 "Face for new news items." | |
176 :group 'newsticker-faces) | |
177 | |
178 (defface newsticker-old-item-face | |
179 '((((class color) (background dark)) | |
180 (:family "helvetica" :bold t :foreground "orange3")) | |
181 (((class color) (background light)) | |
182 (:family "helvetica" :bold t :foreground "red4"))) | |
183 "Face for old news items." | |
184 :group 'newsticker-faces) | |
185 | |
186 (defface newsticker-immortal-item-face | |
187 '((((class color) (background dark)) | |
188 (:family "helvetica" :bold t :italic t :foreground "orange")) | |
189 (((class color) (background light)) | |
190 (:family "helvetica" :bold t :italic t :foreground "blue"))) | |
191 "Face for immortal news items." | |
192 :group 'newsticker-faces) | |
193 | |
194 (defface newsticker-obsolete-item-face | |
195 '((((class color) (background dark)) | |
196 (:family "helvetica" :bold t :strike-through t)) | |
197 (((class color) (background light)) | |
198 (:family "helvetica" :bold t :strike-through t))) | |
199 "Face for old news items." | |
200 :group 'newsticker-faces) | |
201 | |
202 (defface newsticker-date-face | |
203 '((((class color) (background dark)) | |
204 (:family "helvetica" :italic t :height 0.8)) | |
205 (((class color) (background light)) | |
206 (:family "helvetica" :italic t :height 0.8))) | |
207 "Face for newsticker dates." | |
208 :group 'newsticker-faces) | |
209 | |
210 (defface newsticker-statistics-face | |
211 '((((class color) (background dark)) | |
212 (:family "helvetica" :italic t :height 0.8)) | |
213 (((class color) (background light)) | |
214 (:family "helvetica" :italic t :height 0.8))) | |
215 "Face for newsticker dates." | |
216 :group 'newsticker-faces) | |
217 | |
218 (defface newsticker-enclosure-face | |
219 '((((class color) (background dark)) | |
220 (:bold t :background "orange")) | |
221 (((class color) (background light)) | |
222 (:bold t :background "orange"))) | |
223 "Face for enclosed elements." | |
224 :group 'newsticker-faces) | |
225 | |
226 (defface newsticker-extra-face | |
227 '((((class color) (background dark)) | |
228 (:italic t :foreground "gray50" :height 0.8)) | |
229 (((class color) (background light)) | |
230 (:italic t :foreground "gray50" :height 0.8))) | |
231 "Face for newsticker dates." | |
232 :group 'newsticker-faces) | |
233 | |
234 (defface newsticker-default-face | |
235 '((((class color) (background dark)) | |
236 (:inherit default)) | |
237 (((class color) (background light)) | |
238 (:inherit default))) | |
239 "Face for the description of news items." | |
240 ;;:set 'newsticker--set-customvar | |
241 :group 'newsticker-faces) | |
242 | |
243 (defcustom newsticker-hide-old-items-in-newsticker-buffer | |
244 nil | |
245 "Decides whether to automatically hide old items in the *newsticker* buffer. | |
246 If set to t old items will be completely folded and only new | |
247 items will show up in the *newsticker* buffer. Otherwise old as | |
248 well as new items will be visible." | |
249 :type 'boolean | |
250 :set 'newsticker--set-customvar-buffer | |
251 :group 'newsticker-plainview) | |
252 | |
253 (defcustom newsticker-show-descriptions-of-new-items | |
254 t | |
255 "Whether to automatically show descriptions of new items in *newsticker*. | |
256 If set to t old items will be folded and new items will be | |
257 unfolded. Otherwise old as well as new items will be folded." | |
258 :type 'boolean | |
259 :set 'newsticker--set-customvar-buffer | |
260 :group 'newsticker-plainview) | |
261 | |
262 (defcustom newsticker-show-all-news-elements | |
263 nil | |
264 "Show all news elements." | |
265 :type 'boolean | |
266 ;;:set 'newsticker--set-customvar | |
267 :group 'newsticker-plainview) | |
268 | |
269 ;; ====================================================================== | |
270 ;; hooks | |
271 (defgroup newsticker-plainview-hooks nil | |
272 "Settings for newsticker hooks which apply to plainview only." | |
273 :group 'newsticker-hooks) | |
274 | |
275 (defcustom newsticker-select-item-hook | |
276 'newsticker--buffer-make-item-completely-visible | |
277 "List of functions run after a headline has been selected. | |
278 Each function is called after one of `newsticker-next-item', | |
279 `newsticker-next-new-item', `newsticker-previous-item', | |
280 `newsticker-previous-new-item' has been called. | |
281 | |
282 The default value 'newsticker--buffer-make-item-completely-visible | |
283 assures that the current item is always completely visible." | |
284 :type 'hook | |
285 :options '(newsticker--buffer-make-item-completely-visible) | |
286 :group 'newsticker-plainview-hooks) | |
287 | |
288 (defcustom newsticker-select-feed-hook | |
289 'newsticker--buffer-make-item-completely-visible | |
290 "List of functions run after a feed has been selected. | |
291 Each function is called after one of `newsticker-next-feed', and | |
292 `newsticker-previous-feed' has been called. | |
293 | |
294 The default value 'newsticker--buffer-make-item-completely-visible | |
295 assures that the current feed is completely visible." | |
296 :type 'hook | |
297 :options '(newsticker--buffer-make-item-completely-visible) | |
298 :group 'newsticker-plainview-hooks) | |
299 | |
300 (defcustom newsticker-buffer-change-hook | |
301 'newsticker-w3m-show-inline-images | |
302 "List of functions run after the newsticker buffer has been updated. | |
303 Each function is called after `newsticker-buffer-update' has been called. | |
304 | |
305 The default value '`newsticker-w3m-show-inline-images' loads inline | |
306 images." | |
307 :type 'hook | |
308 :group 'newsticker-plainview-hooks) | |
309 | |
310 (defcustom newsticker-narrow-hook | |
311 'newsticker-w3m-show-inline-images | |
312 "List of functions run after narrowing in newsticker buffer has changed. | |
313 Each function is called after | |
314 `newsticker-toggle-auto-narrow-to-feed' or | |
315 `newsticker-toggle-auto-narrow-to-item' has been called. | |
316 | |
317 The default value '`newsticker-w3m-show-inline-images' loads inline | |
318 images." | |
319 :type 'hook | |
320 :group 'newsticker-plainview-hooks) | |
321 | |
322 ;; ====================================================================== | |
323 ;;; Toolbar | |
324 ;; ====================================================================== | |
325 | |
326 (defvar newsticker--plainview-tool-bar-map | |
327 (if (featurep 'xemacs) | |
328 nil | |
329 (let ((tool-bar-map (make-sparse-keymap))) | |
330 (define-key tool-bar-map [newsticker-sep-1] | |
331 (list 'menu-item "--double-line")) | |
332 (define-key tool-bar-map [newsticker-browse-url] | |
333 (list 'menu-item "newsticker-browse-url" 'newsticker-browse-url | |
334 :visible t | |
335 :help "Browse URL for item at point" | |
336 :image newsticker--browse-image)) | |
337 (define-key tool-bar-map [newsticker-buffer-force-update] | |
338 (list 'menu-item "newsticker-buffer-force-update" | |
339 'newsticker-buffer-force-update | |
340 :visible t | |
341 :help "Update newsticker buffer" | |
342 :image newsticker--update-image | |
343 :enable '(not newsticker--buffer-uptodate-p))) | |
344 (define-key tool-bar-map [newsticker-get-all-news] | |
345 (list 'menu-item "newsticker-get-all-news" 'newsticker-get-all-news | |
346 :visible t | |
347 :help "Get news for all feeds" | |
348 :image newsticker--get-all-image)) | |
349 (define-key tool-bar-map [newsticker-mark-item-at-point-as-read] | |
350 (list 'menu-item "newsticker-mark-item-at-point-as-read" | |
351 'newsticker-mark-item-at-point-as-read | |
352 :visible t | |
353 :image newsticker--mark-read-image | |
354 :help "Mark current item as read" | |
355 :enable '(newsticker-item-not-old-p))) | |
356 (define-key tool-bar-map [newsticker-mark-item-at-point-as-immortal] | |
357 (list 'menu-item "newsticker-mark-item-at-point-as-immortal" | |
358 'newsticker-mark-item-at-point-as-immortal | |
359 :visible t | |
360 :image newsticker--mark-immortal-image | |
361 :help "Mark current item as immortal" | |
362 :enable '(newsticker-item-not-immortal-p))) | |
363 (define-key tool-bar-map [newsticker-toggle-auto-narrow-to-feed] | |
364 (list 'menu-item "newsticker-toggle-auto-narrow-to-feed" | |
365 'newsticker-toggle-auto-narrow-to-feed | |
366 :visible t | |
367 :help "Toggle visibility of other feeds" | |
368 :image newsticker--narrow-image)) | |
369 (define-key tool-bar-map [newsticker-next-feed] | |
370 (list 'menu-item "newsticker-next-feed" 'newsticker-next-feed | |
371 :visible t | |
372 :help "Go to next feed" | |
373 :image newsticker--next-feed-image | |
374 :enable '(newsticker-next-feed-available-p))) | |
375 (define-key tool-bar-map [newsticker-next-item] | |
376 (list 'menu-item "newsticker-next-item" 'newsticker-next-item | |
377 :visible t | |
378 :help "Go to next item" | |
379 :image newsticker--next-item-image | |
380 :enable '(newsticker-next-item-available-p))) | |
381 (define-key tool-bar-map [newsticker-previous-item] | |
382 (list 'menu-item "newsticker-previous-item" 'newsticker-previous-item | |
383 :visible t | |
384 :help "Go to previous item" | |
385 :image newsticker--previous-item-image | |
386 :enable '(newsticker-previous-item-available-p))) | |
387 (define-key tool-bar-map [newsticker-previous-feed] | |
388 (list 'menu-item "newsticker-previous-feed" 'newsticker-previous-feed | |
389 :visible t | |
390 :help "Go to previous feed" | |
391 :image newsticker--previous-feed-image | |
392 :enable '(newsticker-previous-feed-available-p))) | |
393 ;; standard icons / actions | |
394 (tool-bar-add-item "close" | |
395 'newsticker-close-buffer | |
396 'newsticker-close-buffer | |
397 :help "Close newsticker buffer") | |
398 (tool-bar-add-item "preferences" | |
399 'newsticker-customize | |
400 'newsticker-customize | |
401 :help "Customize newsticker") | |
402 tool-bar-map))) | |
403 | |
404 ;; ====================================================================== | |
405 ;;; Newsticker mode | |
406 ;; ====================================================================== | |
407 | |
408 (define-derived-mode newsticker-mode fundamental-mode | |
409 "NewsTicker" | |
410 "Viewing news feeds in Emacs." | |
411 (set (make-local-variable 'tool-bar-map) newsticker--plainview-tool-bar-map) | |
412 (set (make-local-variable 'imenu-sort-function) nil) | |
413 (set (make-local-variable 'scroll-conservatively) 999) | |
414 (setq imenu-create-index-function 'newsticker--imenu-create-index) | |
415 (setq imenu-default-goto-function 'newsticker--imenu-goto) | |
416 (setq buffer-read-only t) | |
417 (auto-fill-mode -1) ;; turn auto-fill off! | |
418 (font-lock-mode -1) ;; turn off font-lock!! | |
419 (set (make-local-variable 'font-lock-defaults) nil) | |
420 (set (make-local-variable 'line-move-ignore-invisible) t) | |
421 (setq mode-line-format | |
422 (list "-" | |
423 'mode-line-mule-info | |
424 'mode-line-modified | |
425 'mode-line-frame-identification | |
426 " Newsticker (" | |
427 '(newsticker--buffer-uptodate-p | |
428 "up to date" | |
429 "NEED UPDATE") | |
430 ") " | |
431 '(:eval (format "[%d]" (length newsticker--process-ids))) | |
432 " -- " | |
433 '(:eval (newsticker--buffer-get-feed-title-at-point)) | |
434 ": " | |
435 '(:eval (newsticker--buffer-get-item-title-at-point)) | |
436 " %-")) | |
437 (add-to-invisibility-spec 't) | |
438 (unless newsticker-show-all-news-elements | |
439 (add-to-invisibility-spec 'extra)) | |
440 (newsticker--buffer-set-uptodate nil)) | |
441 | |
442 ;; refine its mode-map | |
443 (define-key newsticker-mode-map "sO" 'newsticker-show-old-items) | |
444 (define-key newsticker-mode-map "hO" 'newsticker-hide-old-items) | |
445 (define-key newsticker-mode-map "sa" 'newsticker-show-all-desc) | |
446 (define-key newsticker-mode-map "ha" 'newsticker-hide-all-desc) | |
447 (define-key newsticker-mode-map "sf" 'newsticker-show-feed-desc) | |
448 (define-key newsticker-mode-map "hf" 'newsticker-hide-feed-desc) | |
449 (define-key newsticker-mode-map "so" 'newsticker-show-old-item-desc) | |
450 (define-key newsticker-mode-map "ho" 'newsticker-hide-old-item-desc) | |
451 (define-key newsticker-mode-map "sn" 'newsticker-show-new-item-desc) | |
452 (define-key newsticker-mode-map "hn" 'newsticker-hide-new-item-desc) | |
453 (define-key newsticker-mode-map "se" 'newsticker-show-entry) | |
454 (define-key newsticker-mode-map "he" 'newsticker-hide-entry) | |
455 (define-key newsticker-mode-map "sx" 'newsticker-show-extra) | |
456 (define-key newsticker-mode-map "hx" 'newsticker-hide-extra) | |
457 | |
458 (define-key newsticker-mode-map " " 'scroll-up) | |
459 (define-key newsticker-mode-map "q" 'newsticker-close-buffer) | |
460 (define-key newsticker-mode-map "p" 'newsticker-previous-item) | |
461 (define-key newsticker-mode-map "P" 'newsticker-previous-new-item) | |
462 (define-key newsticker-mode-map "F" 'newsticker-previous-feed) | |
463 (define-key newsticker-mode-map "\t" 'newsticker-next-item) | |
464 (define-key newsticker-mode-map "n" 'newsticker-next-item) | |
465 (define-key newsticker-mode-map "N" 'newsticker-next-new-item) | |
466 (define-key newsticker-mode-map "f" 'newsticker-next-feed) | |
467 (define-key newsticker-mode-map "M" 'newsticker-mark-all-items-as-read) | |
468 (define-key newsticker-mode-map "m" | |
469 'newsticker-mark-all-items-at-point-as-read-and-redraw) | |
470 (define-key newsticker-mode-map "o" | |
471 'newsticker-mark-item-at-point-as-read) | |
472 (define-key newsticker-mode-map "O" | |
473 'newsticker-mark-all-items-at-point-as-read) | |
474 (define-key newsticker-mode-map "G" 'newsticker-get-all-news) | |
475 (define-key newsticker-mode-map "g" 'newsticker-get-news-at-point) | |
476 (define-key newsticker-mode-map "u" 'newsticker-buffer-update) | |
477 (define-key newsticker-mode-map "U" 'newsticker-buffer-force-update) | |
478 (define-key newsticker-mode-map "a" 'newsticker-add-url) | |
479 | |
480 (define-key newsticker-mode-map "i" | |
481 'newsticker-mark-item-at-point-as-immortal) | |
482 | |
483 (define-key newsticker-mode-map "xf" | |
484 'newsticker-toggle-auto-narrow-to-feed) | |
485 (define-key newsticker-mode-map "xi" | |
486 'newsticker-toggle-auto-narrow-to-item) | |
487 | |
488 ;; maps for the clickable portions | |
489 (defvar newsticker--url-keymap (make-sparse-keymap) | |
490 "Key map for click-able headings in the newsticker buffer.") | |
491 (define-key newsticker--url-keymap [mouse-1] | |
492 'newsticker-mouse-browse-url) | |
493 (define-key newsticker--url-keymap [mouse-2] | |
494 'newsticker-mouse-browse-url) | |
495 (define-key newsticker--url-keymap "\n" | |
496 'newsticker-browse-url) | |
497 (define-key newsticker--url-keymap "\C-m" | |
498 'newsticker-browse-url) | |
499 (define-key newsticker--url-keymap [(control return)] | |
500 'newsticker-handle-url) | |
501 | |
502 ;; newsticker menu | |
503 (defvar newsticker-menu (make-sparse-keymap "Newsticker")) | |
504 | |
505 (define-key newsticker-menu [newsticker-browse-url] | |
506 '("Browse URL for item at point" . newsticker-browse-url)) | |
507 (define-key newsticker-menu [newsticker-separator-1] | |
508 '("--")) | |
509 (define-key newsticker-menu [newsticker-buffer-update] | |
510 '("Update buffer" . newsticker-buffer-update)) | |
511 (define-key newsticker-menu [newsticker-separator-2] | |
512 '("--")) | |
513 (define-key newsticker-menu [newsticker-get-all-news] | |
514 '("Get news from all feeds" . newsticker-get-all-news)) | |
515 (define-key newsticker-menu [newsticker-get-news-at-point] | |
516 '("Get news from feed at point" . newsticker-get-news-at-point)) | |
517 (define-key newsticker-menu [newsticker-separator-3] | |
518 '("--")) | |
519 (define-key newsticker-menu [newsticker-mark-all-items-as-read] | |
520 '("Mark all items as read" . newsticker-mark-all-items-as-read)) | |
521 (define-key newsticker-menu [newsticker-mark-all-items-at-point-as-read] | |
522 '("Mark all items in feed at point as read" . | |
523 newsticker-mark-all-items-at-point-as-read)) | |
524 (define-key newsticker-menu [newsticker-mark-item-at-point-as-read] | |
525 '("Mark item at point as read" . | |
526 newsticker-mark-item-at-point-as-read)) | |
527 (define-key newsticker-menu [newsticker-mark-item-at-point-as-immortal] | |
528 '("Toggle immortality for item at point" . | |
529 newsticker-mark-item-at-point-as-immortal)) | |
530 (define-key newsticker-menu [newsticker-separator-4] | |
531 '("--")) | |
532 (define-key newsticker-menu [newsticker-toggle-auto-narrow-to-item] | |
533 '("Narrow to single item" . newsticker-toggle-auto-narrow-to-item)) | |
534 (define-key newsticker-menu [newsticker-toggle-auto-narrow-to-feed] | |
535 '("Narrow to single news feed" . newsticker-toggle-auto-narrow-to-feed)) | |
536 (define-key newsticker-menu [newsticker-hide-old-items] | |
537 '("Hide old items" . newsticker-hide-old-items)) | |
538 (define-key newsticker-menu [newsticker-show-old-items] | |
539 '("Show old items" . newsticker-show-old-items)) | |
540 (define-key newsticker-menu [newsticker-next-item] | |
541 '("Go to next item" . newsticker-next-item)) | |
542 (define-key newsticker-menu [newsticker-previous-item] | |
543 '("Go to previous item" . newsticker-previous-item)) | |
544 | |
545 ;; bind menu to mouse | |
546 (define-key newsticker-mode-map [down-mouse-3] newsticker-menu) | |
547 ;; Put menu in menu-bar | |
548 (define-key newsticker-mode-map [menu-bar Newsticker] | |
549 (cons "Newsticker" newsticker-menu)) | |
550 | |
551 | |
552 ;; ====================================================================== | |
553 ;;; User fun | |
554 ;; ====================================================================== | |
95685
ed883167b994
Autoload cookies for newsticker.
Ulf Jasper <ulf.jasper@web.de>
parents:
95684
diff
changeset
|
555 ;;;###autoload |
95676 | 556 (defun newsticker-plainview () |
557 "Start newsticker plainview." | |
558 (interactive) | |
559 (newsticker-buffer-update t) | |
560 (switch-to-buffer "*newsticker*")) | |
561 | |
562 (defun newsticker-buffer-force-update () | |
563 "Update the newsticker buffer, even if not necessary." | |
564 (interactive) | |
565 (newsticker-buffer-update t)) | |
566 | |
567 (defun newsticker-buffer-update (&optional force) | |
568 "Update the *newsticker* buffer. | |
569 Unless FORCE is t this is done only if necessary, i.e. when the | |
570 *newsticker* buffer is not up-to-date." | |
571 (interactive) | |
572 ;; bring cache data into proper order.... | |
573 (newsticker--cache-sort) | |
574 ;; fill buffer | |
575 (save-excursion | |
576 (let ((buf (get-buffer "*newsticker*"))) | |
577 (if buf | |
578 (switch-to-buffer buf) | |
579 (switch-to-buffer (get-buffer-create "*newsticker*")) | |
580 (newsticker--buffer-set-uptodate nil))) | |
581 (when (or force | |
582 (not newsticker--buffer-uptodate-p)) | |
583 (message "Preparing newsticker buffer...") | |
584 (setq buffer-undo-list t) | |
585 (let ((inhibit-read-only t)) | |
586 (set-buffer-modified-p nil) | |
587 (erase-buffer) | |
588 (newsticker-mode) | |
589 ;; Emacs 21.3.50 does not care if we turn off auto-fill in the | |
590 ;; definition of newsticker-mode, so we do it here (again) | |
591 (auto-fill-mode -1) | |
592 | |
593 (set-buffer-file-coding-system 'utf-8) | |
594 | |
595 (if newsticker-use-full-width | |
596 (set (make-local-variable 'fill-column) (1- (window-width)))) | |
597 (newsticker--buffer-insert-all-items) | |
598 | |
599 ;; FIXME: needed for methods buffer in ecb | |
600 ;; (set-visited-file-name "*newsticker*") | |
601 | |
602 (set-buffer-modified-p nil) | |
603 (newsticker-hide-all-desc) | |
604 (if newsticker-hide-old-items-in-newsticker-buffer | |
605 (newsticker-hide-old-items)) | |
606 (if newsticker-show-descriptions-of-new-items | |
607 (newsticker-show-new-item-desc)) | |
608 ) | |
609 (message "")) | |
610 (newsticker--buffer-set-uptodate t) | |
611 (run-hooks 'newsticker-buffer-change-hook))) | |
612 | |
613 (defun newsticker-get-news-at-point () | |
614 "Launch retrieval of news for the feed point is in. | |
615 This does NOT start the retrieval timers." | |
616 (interactive) | |
617 ;; launch retrieval of news | |
618 (let ((feed (get-text-property (point) 'feed))) | |
619 (when feed | |
620 (newsticker--debug-msg "Getting news for %s" (symbol-name feed)) | |
621 (newsticker-get-news (symbol-name feed))))) | |
622 | |
623 (defun newsticker-w3m-show-inline-images () | |
624 "Show inline images in visible text ranges. | |
625 In-line images in invisible text ranges are hidden. This function | |
626 calls `w3m-toggle-inline-image'. It works only if | |
627 `newsticker-html-renderer' is set to `w3m-region'." | |
628 (interactive) | |
629 (if (eq newsticker-html-renderer 'w3m-region) | |
630 (let ((inhibit-read-only t)) | |
631 (save-excursion | |
632 (save-restriction | |
633 (widen) | |
634 (goto-char (point-min)) | |
635 (let ((pos (point))) | |
636 (while pos | |
637 (setq pos (next-single-property-change pos 'w3m-image)) | |
638 (when pos | |
639 (goto-char pos) | |
640 (when (get-text-property pos 'w3m-image) | |
641 (let ((invis (newsticker--lists-intersect-p | |
642 (get-text-property (1- (point)) | |
643 'invisible) | |
644 buffer-invisibility-spec))) | |
645 (unless (car (get-text-property (1- (point)) | |
646 'display)) | |
647 (unless invis | |
648 (w3m-toggle-inline-image t))))))))))))) | |
649 | |
650 ;; ====================================================================== | |
651 ;;; Keymap stuff | |
652 ;; ====================================================================== | |
653 (defun newsticker-close-buffer () | |
654 "Close the newsticker buffer." | |
655 (interactive) | |
656 (newsticker--cache-update t) | |
657 (bury-buffer)) | |
658 | |
659 (defun newsticker-next-new-item (&optional do-not-wrap-at-eob) | |
660 "Go to next new news item. | |
661 If no new item is found behind point, search is continued at | |
662 beginning of buffer unless optional argument DO-NOT-WRAP-AT-EOB | |
663 is non-nil." | |
664 (interactive) | |
665 (widen) | |
666 (let ((go-ahead t)) | |
667 (while go-ahead | |
668 (unless (newsticker--buffer-goto '(item) 'new) | |
669 ;; found nothing -- wrap | |
670 (unless do-not-wrap-at-eob | |
671 (goto-char (point-min)) | |
672 (newsticker-next-new-item t)) | |
673 (setq go-ahead nil)) | |
674 (unless (newsticker--lists-intersect-p | |
675 (get-text-property (point) 'invisible) | |
676 buffer-invisibility-spec) | |
677 ;; this item is invisible -- continue search | |
678 (setq go-ahead nil)))) | |
679 (run-hooks 'newsticker-select-item-hook) | |
680 (point)) | |
681 | |
682 (defun newsticker-previous-new-item (&optional do-not-wrap-at-bob) | |
683 "Go to previous new news item. | |
684 If no new item is found before point, search is continued at | |
685 beginning of buffer unless optional argument DO-NOT-WRAP-AT-BOB | |
686 is non-nil." | |
687 (interactive) | |
688 (widen) | |
689 (let ((go-ahead t)) | |
690 (while go-ahead | |
691 (unless (newsticker--buffer-goto '(item) 'new t) | |
692 (unless do-not-wrap-at-bob | |
693 (goto-char (point-max)) | |
694 (newsticker--buffer-goto '(item) 'new t))) | |
695 (unless (newsticker--lists-intersect-p | |
696 (get-text-property (point) 'invisible) | |
697 buffer-invisibility-spec) | |
698 (setq go-ahead nil)))) | |
699 (run-hooks 'newsticker-select-item-hook) | |
700 (point)) | |
701 | |
702 (defun newsticker-next-item (&optional do-not-wrap-at-eob) | |
703 "Go to next news item. | |
704 Return new buffer position. | |
705 If no item is found below point, search is continued at beginning | |
706 of buffer unless optional argument DO-NOT-WRAP-AT-EOB is | |
707 non-nil." | |
708 (interactive) | |
709 (widen) | |
710 (let ((go-ahead t) | |
711 (search-list '(item))) | |
712 (if newsticker--auto-narrow-to-item | |
713 (setq search-list '(item feed))) | |
714 (while go-ahead | |
715 (unless (newsticker--buffer-goto search-list) | |
716 ;; found nothing -- wrap | |
717 (unless do-not-wrap-at-eob | |
718 (goto-char (point-min))) | |
719 (setq go-ahead nil)) | |
720 (unless (newsticker--lists-intersect-p | |
721 (get-text-property (point) 'invisible) | |
722 buffer-invisibility-spec) | |
723 (setq go-ahead nil)))) | |
724 (run-hooks 'newsticker-select-item-hook) | |
725 (force-mode-line-update) | |
726 (point)) | |
727 | |
728 (defun newsticker-next-item-same-feed () | |
729 "Go to next news item in the same feed. | |
730 Return new buffer position. If no item is found below point or if | |
731 auto-narrow-to-item is enabled, nil is returned." | |
732 (interactive) | |
733 (if newsticker--auto-narrow-to-item | |
734 nil | |
735 (let ((go-ahead t) | |
736 (current-pos (point)) | |
737 (end-of-feed (save-excursion (newsticker--buffer-end-of-feed)))) | |
738 (while go-ahead | |
739 (unless (newsticker--buffer-goto '(item)) | |
740 (setq go-ahead nil)) | |
741 (unless (newsticker--lists-intersect-p | |
742 (get-text-property (point) 'invisible) | |
743 buffer-invisibility-spec) | |
744 (setq go-ahead nil))) | |
745 (if (and (> (point) current-pos) | |
746 (< (point) end-of-feed)) | |
747 (point) | |
748 (goto-char current-pos) | |
749 nil)))) | |
750 | |
751 (defun newsticker-previous-item (&optional do-not-wrap-at-bob) | |
752 "Go to previous news item. | |
753 Return new buffer position. | |
754 If no item is found before point, search is continued at | |
755 beginning of buffer unless optional argument DO-NOT-WRAP-AT-BOB | |
756 is non-nil." | |
757 (interactive) | |
758 (widen) | |
759 (let ((go-ahead t) | |
760 (search-list '(item))) | |
761 (if newsticker--auto-narrow-to-item | |
762 (setq search-list '(item feed))) | |
763 (when (bobp) | |
764 (unless do-not-wrap-at-bob | |
765 (goto-char (point-max)))) | |
766 (while go-ahead | |
767 (if (newsticker--buffer-goto search-list nil t) | |
768 (unless (newsticker--lists-intersect-p | |
769 (get-text-property (point) 'invisible) | |
770 buffer-invisibility-spec) | |
771 (setq go-ahead nil)) | |
772 (goto-char (point-min)) | |
773 (setq go-ahead nil)))) | |
774 (run-hooks 'newsticker-select-item-hook) | |
775 (force-mode-line-update) | |
776 (point)) | |
777 | |
778 (defun newsticker-next-feed () | |
779 "Go to next news feed. | |
780 Return new buffer position." | |
781 (interactive) | |
782 (widen) | |
783 (newsticker--buffer-goto '(feed)) | |
784 (run-hooks 'newsticker-select-feed-hook) | |
785 (force-mode-line-update) | |
786 (point)) | |
787 | |
788 (defun newsticker-previous-feed () | |
789 "Go to previous news feed. | |
790 Return new buffer position." | |
791 (interactive) | |
792 (widen) | |
793 (newsticker--buffer-goto '(feed) nil t) | |
794 (run-hooks 'newsticker-select-feed-hook) | |
795 (force-mode-line-update) | |
796 (point)) | |
797 | |
798 (defun newsticker-mark-all-items-at-point-as-read-and-redraw () | |
799 "Mark all items as read and clear ticker contents." | |
800 (interactive) | |
801 (when (or newsticker--buffer-uptodate-p | |
802 (y-or-n-p | |
803 "Buffer is not up to date -- really mark items as read? ")) | |
804 (newsticker-mark-all-items-of-feed-as-read | |
805 (get-text-property (point) 'feed)))) | |
806 | |
807 (defun newsticker-mark-all-items-of-feed-as-read (feed) | |
808 "Mark all items of FEED as read, clear ticker, and redraw buffer." | |
809 (when feed | |
810 (let ((pos (point))) | |
811 (message "Marking all items as read for %s" (symbol-name feed)) | |
812 (newsticker--cache-replace-age newsticker--cache feed 'new 'old) | |
813 (newsticker--cache-replace-age newsticker--cache feed 'obsolete | |
814 'old) | |
815 (newsticker--cache-update) | |
816 (newsticker--buffer-set-uptodate nil) | |
817 (newsticker--ticker-text-setup) | |
818 (newsticker-buffer-update) | |
819 ;; go back to where we came frome | |
820 (goto-char pos) | |
821 (end-of-line) | |
822 (newsticker--buffer-goto '(feed) nil t)))) | |
823 | |
824 (defun newsticker-mark-all-items-at-point-as-read () | |
825 "Mark all items as read and clear ticker contents." | |
826 (interactive) | |
827 (when (or newsticker--buffer-uptodate-p | |
828 (y-or-n-p | |
829 "Buffer is not up to date -- really mark items as read? ")) | |
830 (newsticker--do-mark-item-at-point-as-read t) | |
831 (while (newsticker-next-item-same-feed) | |
832 (newsticker--do-mark-item-at-point-as-read t)) | |
833 (newsticker-next-item t))) | |
834 | |
835 (defun newsticker-mark-item-at-point-as-read (&optional respect-immortality) | |
836 "Mark item at point as read and move to next item. | |
837 If optional argument RESPECT-IMMORTALITY is not nil immortal items do | |
838 not get changed." | |
839 (interactive) | |
840 (when (or newsticker--buffer-uptodate-p | |
841 (y-or-n-p | |
842 "Buffer is not up to date -- really mark this item as read? ")) | |
843 (newsticker--do-mark-item-at-point-as-read respect-immortality) | |
844 ;; move forward | |
845 (newsticker-next-item t))) | |
846 | |
847 (defun newsticker--do-mark-item-at-point-as-read (&optional respect-immortality) | |
848 "Mark item at point as read. | |
849 If optional argument RESPECT-IMMORTALITY is not nil immortal items do | |
850 not get changed." | |
851 (let ((feed (get-text-property (point) 'feed))) | |
852 (when feed | |
853 (save-excursion | |
854 (newsticker--buffer-beginning-of-item) | |
855 (let ((inhibit-read-only t) | |
856 (age (get-text-property (point) 'nt-age)) | |
857 (title (get-text-property (point) 'nt-title)) | |
858 (guid (get-text-property (point) 'nt-guid)) | |
859 (nt-desc (get-text-property (point) 'nt-desc)) | |
860 (pos (save-excursion (newsticker--buffer-end-of-item))) | |
861 item) | |
862 (when (or (eq age 'new) | |
863 (eq age 'obsolete) | |
864 (and (eq age 'immortal) | |
865 (not respect-immortality))) | |
866 ;; find item | |
867 (setq item (newsticker--cache-contains newsticker--cache | |
868 feed title nt-desc | |
869 nil nil guid)) | |
870 ;; mark as old | |
871 (when item | |
872 (setcar (nthcdr 4 item) 'old) | |
873 (newsticker--do-forget-preformatted item)) | |
874 ;; clean up ticker | |
875 (if (or (and (eq age 'new) | |
876 newsticker-hide-immortal-items-in-echo-area) | |
877 (and (memq age '(old immortal)) | |
878 (not | |
879 (eq newsticker-hide-old-items-in-newsticker-buffer | |
880 newsticker-hide-immortal-items-in-echo-area)))) | |
881 (newsticker--ticker-text-remove feed title)) | |
882 ;; set faces etc. | |
883 (save-excursion | |
884 (save-restriction | |
885 (widen) | |
886 (put-text-property (point) pos 'nt-age 'old) | |
887 (newsticker--buffer-set-faces (point) pos))) | |
888 (set-buffer-modified-p nil))))))) | |
889 | |
890 (defun newsticker-mark-item-at-point-as-immortal () | |
891 "Mark item at point as read." | |
892 (interactive) | |
893 (when (or newsticker--buffer-uptodate-p | |
894 (y-or-n-p | |
895 "Buffer is not up to date -- really mark this item as read? ")) | |
896 (let ((feed (get-text-property (point) 'feed)) | |
897 (item nil)) | |
898 (when feed | |
899 (save-excursion | |
900 (newsticker--buffer-beginning-of-item) | |
901 (let ((inhibit-read-only t) | |
902 (oldage (get-text-property (point) 'nt-age)) | |
903 (title (get-text-property (point) 'nt-title)) | |
904 (guid (get-text-property (point) 'nt-guid)) | |
905 (pos (save-excursion (newsticker--buffer-end-of-item)))) | |
906 (let ((newage 'immortal)) | |
907 (if (eq oldage 'immortal) | |
908 (setq newage 'old)) | |
909 (setq item (newsticker--cache-contains newsticker--cache | |
910 feed title nil nil nil | |
911 guid)) | |
912 ;; change age | |
913 (when item | |
914 (setcar (nthcdr 4 item) newage) | |
915 (newsticker--do-forget-preformatted item)) | |
916 (if (or (and (eq newage 'immortal) | |
917 newsticker-hide-immortal-items-in-echo-area) | |
918 (and (eq newage 'obsolete) | |
919 newsticker-hide-obsolete-items-in-echo-area) | |
920 (and (eq oldage 'immortal) | |
921 (not | |
922 (eq newsticker-hide-old-items-in-newsticker-buffer | |
923 newsticker-hide-immortal-items-in-echo-area)))) | |
924 (newsticker--ticker-text-remove feed title) | |
925 (newsticker--ticker-text-setup)) | |
926 (save-excursion | |
927 (save-restriction | |
928 (widen) | |
929 (put-text-property (point) pos 'nt-age newage) | |
930 (if (eq newage 'immortal) | |
931 (put-text-property (point) pos 'nt-age 'immortal) | |
932 (put-text-property (point) pos 'nt-age 'old)) | |
933 (newsticker--buffer-set-faces (point) pos)))))) | |
934 (if item | |
935 (newsticker-next-item t)))))) | |
936 | |
937 (defun newsticker-mark-all-items-as-read () | |
938 "Mark all items as read and clear ticker contents." | |
939 (interactive) | |
940 (when (or newsticker--buffer-uptodate-p | |
941 (y-or-n-p | |
942 "Buffer is not up to date -- really mark items as read? ")) | |
943 (newsticker--cache-replace-age newsticker--cache 'any 'new 'old) | |
944 (newsticker--buffer-set-uptodate nil) | |
945 (newsticker--ticker-text-setup) | |
946 (newsticker--cache-update) | |
947 (newsticker-buffer-update))) | |
948 | |
949 (defun newsticker-hide-extra () | |
950 "Hide the extra elements of items." | |
951 (interactive) | |
952 (newsticker--buffer-hideshow 'extra nil) | |
953 (newsticker--buffer-redraw)) | |
954 | |
955 (defun newsticker-show-extra () | |
956 "Show the extra elements of items." | |
957 (interactive) | |
958 (newsticker--buffer-hideshow 'extra t) | |
959 (newsticker--buffer-redraw)) | |
960 | |
961 (defun newsticker-hide-old-item-desc () | |
962 "Hide the description of old items." | |
963 (interactive) | |
964 (newsticker--buffer-hideshow 'desc-old nil) | |
965 (newsticker--buffer-redraw)) | |
966 | |
967 (defun newsticker-show-old-item-desc () | |
968 "Show the description of old items." | |
969 (interactive) | |
970 (newsticker--buffer-hideshow 'item-old t) | |
971 (newsticker--buffer-hideshow 'desc-old t) | |
972 (newsticker--buffer-redraw)) | |
973 | |
974 (defun newsticker-hide-new-item-desc () | |
975 "Hide the description of new items." | |
976 (interactive) | |
977 (newsticker--buffer-hideshow 'desc-new nil) | |
978 (newsticker--buffer-hideshow 'desc-immortal nil) | |
979 (newsticker--buffer-hideshow 'desc-obsolete nil) | |
980 (newsticker--buffer-redraw)) | |
981 | |
982 (defun newsticker-show-new-item-desc () | |
983 "Show the description of new items." | |
984 (interactive) | |
985 (newsticker--buffer-hideshow 'desc-new t) | |
986 (newsticker--buffer-hideshow 'desc-immortal t) | |
987 (newsticker--buffer-hideshow 'desc-obsolete t) | |
988 (newsticker--buffer-redraw)) | |
989 | |
990 (defun newsticker-hide-feed-desc () | |
991 "Hide the description of feeds." | |
992 (interactive) | |
993 (newsticker--buffer-hideshow 'desc-feed nil) | |
994 (newsticker--buffer-redraw)) | |
995 | |
996 (defun newsticker-show-feed-desc () | |
997 "Show the description of old items." | |
998 (interactive) | |
999 (newsticker--buffer-hideshow 'desc-feed t) | |
1000 (newsticker--buffer-redraw)) | |
1001 | |
1002 (defun newsticker-hide-all-desc () | |
1003 "Hide the descriptions of feeds and all items." | |
1004 (interactive) | |
1005 (newsticker--buffer-hideshow 'desc-feed nil) | |
1006 (newsticker--buffer-hideshow 'desc-immortal nil) | |
1007 (newsticker--buffer-hideshow 'desc-obsolete nil) | |
1008 (newsticker--buffer-hideshow 'desc-new nil) | |
1009 (newsticker--buffer-hideshow 'desc-old nil) | |
1010 (newsticker--buffer-redraw)) | |
1011 | |
1012 (defun newsticker-show-all-desc () | |
1013 "Show the descriptions of feeds and all items." | |
1014 (interactive) | |
1015 (newsticker--buffer-hideshow 'desc-feed t) | |
1016 (newsticker--buffer-hideshow 'desc-immortal t) | |
1017 (newsticker--buffer-hideshow 'desc-obsolete t) | |
1018 (newsticker--buffer-hideshow 'desc-new t) | |
1019 (newsticker--buffer-hideshow 'desc-old t) | |
1020 (newsticker--buffer-redraw)) | |
1021 | |
1022 (defun newsticker-hide-old-items () | |
1023 "Hide old items." | |
1024 (interactive) | |
1025 (newsticker--buffer-hideshow 'desc-old nil) | |
1026 (newsticker--buffer-hideshow 'item-old nil) | |
1027 (newsticker--buffer-redraw)) | |
1028 | |
1029 (defun newsticker-show-old-items () | |
1030 "Show old items." | |
1031 (interactive) | |
1032 (newsticker--buffer-hideshow 'item-old t) | |
1033 (newsticker--buffer-redraw)) | |
1034 | |
1035 (defun newsticker-hide-entry () | |
1036 "Hide description of entry at point." | |
1037 (interactive) | |
1038 (save-excursion | |
1039 (let* (pos1 pos2 | |
1040 (inhibit-read-only t) | |
1041 inv-prop org-inv-prop | |
1042 is-invisible) | |
1043 (newsticker--buffer-beginning-of-item) | |
1044 (newsticker--buffer-goto '(desc)) | |
1045 (setq pos1 (max (point-min) (1- (point)))) | |
1046 (newsticker--buffer-goto '(extra feed item nil)) | |
1047 (setq pos2 (max (point-min) (1- (point)))) | |
1048 (setq inv-prop (get-text-property pos1 'invisible)) | |
1049 (setq org-inv-prop (get-text-property pos1 'org-invisible)) | |
1050 (cond ((eq inv-prop t) | |
1051 ;; do nothing | |
1052 ) | |
1053 ((eq org-inv-prop nil) | |
1054 (add-text-properties pos1 pos2 | |
1055 (list 'invisible (list t) | |
1056 'org-invisible inv-prop))) | |
1057 (t | |
1058 ;; toggle | |
1059 (add-text-properties pos1 pos2 | |
1060 (list 'invisible org-inv-prop)) | |
1061 (remove-text-properties pos1 pos2 '(org-invisible)))))) | |
1062 (newsticker--buffer-redraw)) | |
1063 | |
1064 (defun newsticker-show-entry () | |
1065 "Show description of entry at point." | |
1066 (interactive) | |
1067 (save-excursion | |
1068 (let* (pos1 pos2 | |
1069 (inhibit-read-only t) | |
1070 inv-prop org-inv-prop | |
1071 is-invisible) | |
1072 (newsticker--buffer-beginning-of-item) | |
1073 (newsticker--buffer-goto '(desc)) | |
1074 (setq pos1 (max (point-min) (1- (point)))) | |
1075 (newsticker--buffer-goto '(extra feed item)) | |
1076 (setq pos2 (max (point-min) (1- (point)))) | |
1077 (setq inv-prop (get-text-property pos1 'invisible)) | |
1078 (setq org-inv-prop (get-text-property pos1 'org-invisible)) | |
1079 (cond ((eq org-inv-prop nil) | |
1080 (add-text-properties pos1 pos2 | |
1081 (list 'invisible nil | |
1082 'org-invisible inv-prop))) | |
1083 (t | |
1084 ;; toggle | |
1085 (add-text-properties pos1 pos2 | |
1086 (list 'invisible org-inv-prop)) | |
1087 (remove-text-properties pos1 pos2 '(org-invisible)))))) | |
1088 (newsticker--buffer-redraw)) | |
1089 | |
1090 (defun newsticker-toggle-auto-narrow-to-feed () | |
1091 "Toggle narrowing to current news feed. | |
1092 If auto-narrowing is active, only news item of the current feed | |
1093 are visible." | |
1094 (interactive) | |
1095 (newsticker-set-auto-narrow-to-feed | |
1096 (not newsticker--auto-narrow-to-feed))) | |
1097 | |
1098 (defun newsticker-set-auto-narrow-to-feed (value) | |
1099 "Turn narrowing to current news feed on or off. | |
1100 If VALUE is nil, auto-narrowing is turned off, otherwise it is turned on." | |
1101 (interactive) | |
1102 (setq newsticker--auto-narrow-to-item nil) | |
1103 (setq newsticker--auto-narrow-to-feed value) | |
1104 (widen) | |
1105 (newsticker--buffer-make-item-completely-visible) | |
1106 (run-hooks 'newsticker-narrow-hook)) | |
1107 | |
1108 (defun newsticker-toggle-auto-narrow-to-item () | |
1109 "Toggle narrowing to current news item. | |
1110 If auto-narrowing is active, only one item of the current feed | |
1111 is visible." | |
1112 (interactive) | |
1113 (newsticker-set-auto-narrow-to-item | |
1114 (not newsticker--auto-narrow-to-item))) | |
1115 | |
1116 (defun newsticker-set-auto-narrow-to-item (value) | |
1117 "Turn narrowing to current news item on or off. | |
1118 If VALUE is nil, auto-narrowing is turned off, otherwise it is turned on." | |
1119 (interactive) | |
1120 (setq newsticker--auto-narrow-to-feed nil) | |
1121 (setq newsticker--auto-narrow-to-item value) | |
1122 (widen) | |
1123 (newsticker--buffer-make-item-completely-visible) | |
1124 (run-hooks 'newsticker-narrow-hook)) | |
1125 | |
1126 (defun newsticker-next-feed-available-p () | |
1127 "Return t if position is before last feed, nil otherwise." | |
1128 (save-excursion | |
1129 (let ((p (point))) | |
1130 (newsticker--buffer-goto '(feed)) | |
1131 (not (= p (point)))))) | |
1132 | |
1133 (defun newsticker-previous-feed-available-p () | |
1134 "Return t if position is behind first feed, nil otherwise." | |
1135 (save-excursion | |
1136 (let ((p (point))) | |
1137 (newsticker--buffer-goto '(feed) nil t) | |
1138 (not (= p (point)))))) | |
1139 | |
1140 (defun newsticker-next-item-available-p () | |
1141 "Return t if position is before last feed, nil otherwise." | |
1142 (save-excursion | |
1143 (catch 'result | |
1144 (while (< (point) (point-max)) | |
1145 (unless (newsticker--buffer-goto '(item)) | |
1146 (throw 'result nil)) | |
1147 (unless (newsticker--lists-intersect-p | |
1148 (get-text-property (point) 'invisible) | |
1149 buffer-invisibility-spec) | |
1150 (throw 'result t)))))) | |
1151 | |
1152 (defun newsticker-previous-item-available-p () | |
1153 "Return t if position is behind first item, nil otherwise." | |
1154 (save-excursion | |
1155 (catch 'result | |
1156 (while (> (point) (point-min)) | |
1157 (unless (newsticker--buffer-goto '(item) nil t) | |
1158 (throw 'result nil)) | |
1159 (unless (newsticker--lists-intersect-p | |
1160 (get-text-property (point) 'invisible) | |
1161 buffer-invisibility-spec) | |
1162 (throw 'result t)))))) | |
1163 | |
1164 (defun newsticker-item-not-old-p () | |
1165 "Return t if there is an item at point which is not old, nil otherwise." | |
1166 (when (get-text-property (point) 'feed) | |
1167 (save-excursion | |
1168 (newsticker--buffer-beginning-of-item) | |
1169 (let ((age (get-text-property (point) 'nt-age))) | |
1170 (and (memq age '(new immortal obsolete)) t))))) | |
1171 | |
1172 (defun newsticker-item-not-immortal-p () | |
1173 "Return t if there is an item at point which is not immortal, nil otherwise." | |
1174 (when (get-text-property (point) 'feed) | |
1175 (save-excursion | |
1176 (newsticker--buffer-beginning-of-item) | |
1177 (let ((age (get-text-property (point) 'nt-age))) | |
1178 (and (memq age '(new old obsolete)) t))))) | |
1179 | |
1180 ;; ====================================================================== | |
1181 ;;; Imenu stuff | |
1182 ;; ====================================================================== | |
1183 (defun newsticker--imenu-create-index () | |
1184 "Scan newsticker buffer and return an index for imenu." | |
1185 (save-excursion | |
1186 (goto-char (point-min)) | |
1187 (let ((index-alist nil) | |
1188 (feed-list nil) | |
1189 (go-ahead t)) | |
1190 (while go-ahead | |
1191 (let ((type (get-text-property (point) 'nt-type)) | |
1192 (title (get-text-property (point) 'nt-title))) | |
1193 (cond ((eq type 'feed) | |
1194 ;; we're on a feed heading | |
1195 (when feed-list | |
1196 (if index-alist | |
1197 (nconc index-alist (list feed-list)) | |
1198 (setq index-alist (list feed-list)))) | |
1199 (setq feed-list (list title))) | |
1200 (t | |
1201 (nconc feed-list | |
1202 (list (cons title (point))))))) | |
1203 (setq go-ahead (newsticker--buffer-goto '(item feed)))) | |
1204 (if index-alist | |
1205 (nconc index-alist (list feed-list)) | |
1206 (setq index-alist (list feed-list))) | |
1207 index-alist))) | |
1208 | |
1209 (defun newsticker--imenu-goto (name pos &rest args) | |
1210 "Go to item NAME at position POS and show item. | |
1211 ARGS are ignored." | |
1212 (goto-char pos) | |
1213 ;; show headline | |
1214 (newsticker--buffer-goto '(desc extra feed item)) | |
1215 (let* ((inhibit-read-only t) | |
1216 (pos1 (max (point-min) (1- pos))) | |
1217 (pos2 (max pos1 (1- (point)))) | |
1218 (inv-prop (get-text-property pos 'invisible)) | |
1219 (org-inv-prop (get-text-property pos 'org-invisible))) | |
1220 (when (eq org-inv-prop nil) | |
1221 (add-text-properties pos1 pos2 (list 'invisible nil | |
1222 'org-invisible inv-prop)))) | |
1223 ;; show desc | |
1224 (newsticker-show-entry)) | |
1225 | |
1226 ;; ====================================================================== | |
1227 ;;; Buffer stuff | |
1228 ;; ====================================================================== | |
1229 (defun newsticker--buffer-set-uptodate (value) | |
1230 "Set the uptodate-status of the newsticker buffer to VALUE. | |
1231 The mode-line is changed accordingly." | |
1232 (setq newsticker--buffer-uptodate-p value) | |
1233 (let ((b (get-buffer "*newsticker*"))) | |
1234 (when b | |
1235 (save-excursion | |
1236 (set-buffer b) | |
1237 (if value | |
1238 (setq mode-name "Newsticker -- up to date -- ") | |
1239 (setq mode-name "Newsticker -- NEED UPDATE -- "))) | |
1240 (force-mode-line-update 0)))) | |
1241 | |
1242 (defun newsticker--buffer-redraw () | |
1243 "Redraw the newsticker window." | |
1244 (if (fboundp 'force-window-update) | |
1245 (force-window-update (current-buffer)) | |
1246 (redraw-frame (selected-frame))) | |
1247 (run-hooks 'newsticker-buffer-change-hook) | |
1248 (sit-for 0)) | |
1249 | |
1250 (defun newsticker--buffer-insert-all-items () | |
1251 "Insert all cached newsticker items into the current buffer. | |
1252 Keeps order of feeds as given in `newsticker-url-list' and | |
1253 `newsticker-url-list-defaults'." | |
1254 (goto-char (point-min)) | |
1255 (mapc (lambda (url-item) | |
1256 (let* ((feed-name (car url-item)) | |
1257 (feed-name-symbol (intern feed-name)) | |
1258 (feed (assoc feed-name-symbol newsticker--cache)) | |
1259 (items (cdr feed)) | |
1260 (pos (point))) | |
1261 (when feed | |
1262 ;; insert the feed description | |
1263 (mapc (lambda (item) | |
1264 (when (eq (newsticker--age item) 'feed) | |
1265 (newsticker--buffer-insert-item item | |
1266 feed-name-symbol))) | |
1267 items) | |
1268 ;;insert the items | |
1269 (mapc (lambda (item) | |
1270 (if (memq (newsticker--age item) '(new immortal old | |
1271 obsolete)) | |
1272 (newsticker--buffer-insert-item item | |
1273 feed-name-symbol))) | |
1274 items) | |
1275 (put-text-property pos (point) 'feed (car feed)) | |
1276 | |
1277 ;; insert empty line between feeds | |
1278 (let ((p (point))) | |
1279 (insert "\n") | |
1280 (put-text-property p (point) 'hard t))))) | |
1281 (append newsticker-url-list newsticker-url-list-defaults)) | |
1282 | |
1283 (newsticker--buffer-set-faces (point-min) (point-max)) | |
1284 (newsticker--buffer-set-invisibility (point-min) (point-max)) | |
1285 (goto-char (point-min))) | |
1286 | |
1287 (defun newsticker--buffer-insert-item (item &optional feed-name-symbol) | |
1288 "Insert a news item in the current buffer. | |
1289 Insert a formatted representation of the ITEM. The optional parameter | |
1290 FEED-NAME-SYMBOL determines how the item is formatted and whether the | |
1291 item-retrieval time is added as well." | |
1292 ;; insert headline | |
1293 (if (eq (newsticker--age item) 'feed) | |
1294 (newsticker--buffer-do-insert-text item 'feed feed-name-symbol) | |
1295 (newsticker--buffer-do-insert-text item 'item feed-name-symbol)) | |
1296 ;; insert the description | |
1297 (newsticker--buffer-do-insert-text item 'desc feed-name-symbol)) | |
1298 | |
1299 (defun newsticker--buffer-do-insert-text (item type feed-name-symbol) | |
1300 "Actually insert contents of news item, format it, render it and all that. | |
1301 ITEM is a news item, TYPE tells which part of the item shall be inserted, | |
1302 FEED-NAME-SYMBOL tells to which feed this item belongs." | |
1303 (let* ((pos (point)) | |
1304 (format newsticker-desc-format) | |
1305 (pos-date-start nil) | |
1306 (pos-date-end nil) | |
1307 (pos-stat-start nil) | |
1308 (pos-stat-end nil) | |
1309 (pos-text-start nil) | |
1310 (pos-text-end nil) | |
1311 (pos-extra-start nil) | |
1312 (pos-extra-end nil) | |
1313 (pos-enclosure-start nil) | |
1314 (pos-enclosure-end nil) | |
1315 (age (newsticker--age item)) | |
1316 (preformatted-contents (newsticker--preformatted-contents item)) | |
1317 (preformatted-title (newsticker--preformatted-title item))) | |
1318 (cond ((and preformatted-contents | |
1319 (not (eq (aref preformatted-contents 0) ?\n));; we must | |
1320 ;; NOT have a line | |
1321 ;; break! | |
1322 (eq type 'desc)) | |
1323 (insert preformatted-contents)) | |
1324 ((and preformatted-title | |
1325 (not (eq (aref preformatted-title 0) ?\n));; we must NOT have a | |
1326 ;; line break! | |
1327 (eq type 'item)) | |
1328 (insert preformatted-title)) | |
1329 (t | |
1330 ;; item was not formatted before. | |
1331 ;; Let's go. | |
1332 (if (eq type 'item) | |
1333 (setq format newsticker-item-format) | |
1334 (if (eq type 'feed) | |
1335 (setq format newsticker-heading-format))) | |
1336 | |
1337 (while (> (length format) 0) | |
1338 (let ((prefix (if (> (length format) 1) | |
1339 (substring format 0 2) | |
1340 ""))) | |
1341 (cond ((string= "%c" prefix) | |
1342 ;; contents | |
1343 (when (newsticker--desc item) | |
1344 (setq pos-text-start (point-marker)) | |
1345 (insert (newsticker--desc item)) | |
1346 (setq pos-text-end (point-marker))) | |
1347 (setq format (substring format 2))) | |
1348 ((string= "%d" prefix) | |
1349 ;; date | |
1350 (setq pos-date-start (point-marker)) | |
1351 (if (newsticker--time item) | |
1352 (insert (format-time-string newsticker-date-format | |
1353 (newsticker--time item)))) | |
1354 (setq pos-date-end (point-marker)) | |
1355 (setq format (substring format 2))) | |
1356 ((string= "%l" prefix) | |
1357 ;; logo | |
1358 (let ((disabled (cond ((eq (newsticker--age item) 'feed) | |
1359 (= (newsticker--stat-num-items | |
1360 feed-name-symbol 'new) 0)) | |
1361 (t | |
1362 (not (eq (newsticker--age item) | |
1363 'new)))))) | |
1364 (let ((img (newsticker--image-read feed-name-symbol | |
1365 disabled))) | |
1366 (when img | |
1367 (newsticker--insert-image img (car item))))) | |
1368 (setq format (substring format 2))) | |
1369 ((string= "%L" prefix) | |
1370 ;; logo or title | |
1371 (let ((disabled (cond ((eq (newsticker--age item) 'feed) | |
1372 (= (newsticker--stat-num-items | |
1373 feed-name-symbol 'new) 0)) | |
1374 (t | |
1375 (not (eq (newsticker--age item) | |
1376 'new)))))) | |
1377 (let ((img (newsticker--image-read feed-name-symbol | |
1378 disabled))) | |
1379 (if img | |
1380 (newsticker--insert-image img (car item)) | |
1381 (when (car item) | |
1382 (setq pos-text-start (point-marker)) | |
1383 (if (eq (newsticker--age item) 'feed) | |
1384 (insert (newsticker--title item)) | |
1385 ;; FIXME: This is not the "real" title! | |
1386 (insert (format "%s" | |
1387 (car (newsticker--cache-get-feed | |
1388 feed-name-symbol))))) | |
1389 (setq pos-text-end (point-marker)))))) | |
1390 (setq format (substring format 2))) | |
1391 ((string= "%s" prefix) | |
1392 ;; statistics | |
1393 (setq pos-stat-start (point-marker)) | |
1394 (if (eq (newsticker--age item) 'feed) | |
1395 (insert (newsticker--buffer-statistics | |
1396 feed-name-symbol))) | |
1397 (setq pos-stat-end (point-marker)) | |
1398 (setq format (substring format 2))) | |
1399 ((string= "%t" prefix) | |
1400 ;; title | |
1401 (when (car item) | |
1402 (setq pos-text-start (point-marker)) | |
1403 (insert (car item)) | |
1404 (setq pos-text-end (point-marker))) | |
1405 (setq format (substring format 2))) | |
1406 ((string-match "%." prefix) | |
1407 ;; unknown specifier! | |
1408 (insert prefix) | |
1409 (setq format (substring format 2))) | |
1410 ((string-match "^\\([^%]*\\)\\(.*\\)" format) ;; FIXME! | |
1411 ;; everything else | |
1412 (let ((p (point))) | |
1413 (insert (substring format | |
1414 (match-beginning 1) (match-end 1))) | |
1415 ;; in case that the format string contained newlines | |
1416 (put-text-property p (point) 'hard t)) | |
1417 (setq format (substring format (match-beginning 2))))))) | |
1418 | |
1419 ;; decode HTML if possible... | |
1420 (let ((is-rendered-HTML nil)) | |
1421 (when (and newsticker-html-renderer pos-text-start pos-text-end) | |
1422 (condition-case error-data | |
1423 (save-excursion | |
1424 ;; check whether it is necessary to call html renderer | |
1425 ;; (regexp inspired by htmlr.el) | |
1426 (goto-char pos-text-start) | |
1427 (when (re-search-forward | |
1428 "</?[A-Za-z1-6]*\\|&#?[A-Za-z0-9]+;" pos-text-end t) | |
1429 ;; (message "%s" (newsticker--title item)) | |
1430 (let ((w3m-fill-column (if newsticker-use-full-width | |
1431 -1 fill-column)) | |
1432 (w3-maximum-line-length | |
1433 (if newsticker-use-full-width nil fill-column))) | |
1434 (save-excursion | |
1435 (funcall newsticker-html-renderer pos-text-start | |
1436 pos-text-end))) | |
1437 (cond ((eq newsticker-html-renderer 'w3m-region) | |
1438 (add-text-properties pos (point-max) | |
1439 (list 'keymap | |
1440 w3m-minor-mode-map))) | |
1441 ((eq newsticker-html-renderer 'w3-region) | |
1442 (add-text-properties pos (point-max) | |
1443 (list 'keymap w3-mode-map)))) | |
1444 (setq is-rendered-HTML t))) | |
1445 (error | |
1446 (message "Error: HTML rendering failed: %s, %s" | |
1447 (car error-data) (cdr error-data))))) | |
1448 ;; After html rendering there might be chunks of blank | |
1449 ;; characters between rendered text and date, statistics or | |
1450 ;; whatever. Remove it | |
1451 (when (and (eq type 'item) is-rendered-HTML) | |
1452 (goto-char pos) | |
1453 (while (re-search-forward "[ \t]*\n[ \t]*" nil t) | |
1454 (replace-match " " nil nil)) | |
1455 (goto-char (point-max))) | |
1456 (when (and newsticker-justification | |
1457 (memq type '(item desc)) | |
1458 (not is-rendered-HTML)) | |
1459 (condition-case nil | |
1460 (let ((use-hard-newlines t)) | |
1461 (fill-region pos (point-max) newsticker-justification)) | |
1462 (error nil)))) | |
1463 | |
1464 ;; remove leading and trailing newlines | |
1465 (goto-char pos) | |
1466 (unless (= 0 (skip-chars-forward " \t\r\n")) | |
1467 (delete-region pos (point))) | |
1468 (goto-char (point-max)) | |
1469 (let ((end (point))) | |
1470 (unless (= 0 (skip-chars-backward " \t\r\n" (1+ pos))) | |
1471 (delete-region (point) end))) | |
1472 (goto-char (point-max)) | |
1473 ;; closing newline | |
1474 (unless nil ;;(eq pos (point)) | |
1475 (insert "\n") | |
1476 (put-text-property (1- (point)) (point) 'hard t)) | |
1477 | |
1478 ;; insert enclosure element | |
1479 (when (eq type 'desc) | |
1480 (setq pos-enclosure-start (point)) | |
1481 (newsticker--insert-enclosure item newsticker--url-keymap) | |
1482 (setq pos-enclosure-end (point))) | |
1483 | |
1484 ;; show extra elements | |
1485 (when (eq type 'desc) | |
1486 (goto-char (point-max)) | |
1487 (setq pos-extra-start (point)) | |
1488 (newsticker--print-extra-elements item newsticker--url-keymap) | |
1489 (setq pos-extra-end (point))) | |
1490 | |
1491 ;; text properties | |
1492 (when (memq type '(feed item)) | |
1493 (add-text-properties pos (1- (point)) | |
1494 (list 'mouse-face 'highlight | |
1495 'nt-link (newsticker--link item) | |
1496 'help-echo | |
1497 (format "mouse-2: visit item (%s)" | |
1498 (newsticker--link item)) | |
1499 'keymap newsticker--url-keymap)) | |
1500 (add-text-properties pos (point) | |
1501 (list 'nt-title (newsticker--title item) | |
1502 'nt-desc (newsticker--desc item)))) | |
1503 | |
1504 (add-text-properties pos (point) | |
1505 (list 'nt-type type | |
1506 'nt-face type | |
1507 'nt-age age | |
1508 'nt-guid (newsticker--guid item))) | |
1509 (when (and pos-date-start pos-date-end) | |
1510 (put-text-property pos-date-start pos-date-end 'nt-face 'date)) | |
1511 (when (and pos-stat-start pos-stat-end) | |
1512 (put-text-property pos-stat-start pos-stat-end 'nt-face 'stat)) | |
1513 (when (and pos-extra-start pos-extra-end) | |
1514 (put-text-property pos-extra-start pos-extra-end | |
1515 'nt-face 'extra) | |
1516 (put-text-property pos-extra-start pos-extra-end | |
1517 'nt-type 'extra)) | |
1518 (when (and pos-enclosure-start pos-enclosure-end | |
1519 (> pos-enclosure-end pos-enclosure-start)) | |
1520 (put-text-property pos-enclosure-start (1- pos-enclosure-end) | |
1521 'nt-face 'enclosure)) | |
1522 | |
1523 ;; left margin | |
1524 ;;(unless (memq type '(feed item)) | |
1525 ;;(set-left-margin pos (1- (point)) 1)) | |
1526 | |
1527 ;; save rendered stuff | |
1528 (cond ((eq type 'desc) | |
1529 ;; preformatted contents | |
1530 (newsticker--cache-set-preformatted-contents | |
1531 item (buffer-substring pos (point)))) | |
1532 ((eq type 'item) | |
1533 ;; preformatted title | |
1534 (newsticker--cache-set-preformatted-title | |
1535 item (buffer-substring pos (point))))))))) | |
1536 | |
1537 (defun newsticker--buffer-statistics (feed-name-symbol) | |
1538 "Return a statistic string for the feed given by FEED-NAME-SYMBOL. | |
1539 See `newsticker-statistics-format'." | |
1540 (let ((case-fold-search nil)) | |
1541 (replace-regexp-in-string | |
1542 "%a" | |
1543 (format "%d" (newsticker--stat-num-items feed-name-symbol)) | |
1544 (replace-regexp-in-string | |
1545 "%i" | |
1546 (format "%d" (newsticker--stat-num-items feed-name-symbol 'immortal)) | |
1547 (replace-regexp-in-string | |
1548 "%n" | |
1549 (format "%d" (newsticker--stat-num-items feed-name-symbol 'new)) | |
1550 (replace-regexp-in-string | |
1551 "%o" | |
1552 (format "%d" (newsticker--stat-num-items feed-name-symbol 'old)) | |
1553 (replace-regexp-in-string | |
1554 "%O" | |
1555 (format "%d" (newsticker--stat-num-items feed-name-symbol 'obsolete)) | |
1556 newsticker-statistics-format))))))) | |
1557 | |
1558 (defun newsticker--buffer-set-faces (start end) | |
1559 "Add face properties according to mark property. | |
1560 Scans the buffer between START and END." | |
1561 (save-excursion | |
1562 (put-text-property start end 'face 'newsticker-default-face) | |
1563 (goto-char start) | |
1564 (let ((pos1 start) | |
1565 (pos2 1) | |
1566 (nt-face (get-text-property start 'nt-face)) | |
1567 (nt-age (get-text-property start 'nt-age))) | |
1568 (when nt-face | |
1569 (setq pos2 (next-single-property-change (point) 'nt-face)) | |
1570 (newsticker--set-face-properties pos1 pos2 nt-face nt-age) | |
1571 (setq nt-face (get-text-property pos2 'nt-face)) | |
1572 (setq pos1 pos2)) | |
1573 (while (and (setq pos2 (next-single-property-change pos1 'nt-face)) | |
1574 (<= pos2 end) | |
1575 (> pos2 pos1)) | |
1576 (newsticker--set-face-properties pos1 pos2 nt-face nt-age) | |
1577 (setq nt-face (get-text-property pos2 'nt-face)) | |
1578 (setq nt-age (get-text-property pos2 'nt-age)) | |
1579 (setq pos1 pos2))))) | |
1580 | |
1581 (defun newsticker--buffer-set-invisibility (start end) | |
1582 "Add invisibility properties according to nt-type property. | |
1583 Scans the buffer between START and END. Sets the 'invisible | |
1584 property to '(<nt-type>-<nt-age> <nt-type> <nt-age>)." | |
1585 (save-excursion | |
1586 ;; reset invisibility settings | |
1587 (put-text-property start end 'invisible nil) | |
1588 ;; let's go | |
1589 (goto-char start) | |
1590 (let ((pos1 start) | |
1591 (pos2 1) | |
1592 (nt-type (get-text-property start 'nt-type)) | |
1593 (nt-age (get-text-property start 'nt-age))) | |
1594 (when nt-type | |
1595 (setq pos2 (next-single-property-change (point) 'nt-type)) | |
1596 (put-text-property (max (point-min) pos1) (1- pos2) | |
1597 'invisible | |
1598 (list (intern | |
1599 (concat | |
1600 (symbol-name | |
1601 (if (eq nt-type 'extra) 'desc nt-type)) | |
1602 "-" | |
1603 (symbol-name nt-age))) | |
1604 nt-type | |
1605 nt-age)) | |
1606 (setq nt-type (get-text-property pos2 'nt-type)) | |
1607 (setq pos1 pos2)) | |
1608 (while (and (setq pos2 (next-single-property-change pos1 'nt-type)) | |
1609 (<= pos2 end) | |
1610 (> pos2 pos1)) | |
1611 ;; must shift one char to the left in order to handle inivisible | |
1612 ;; newlines, motion in invisible text areas and all that correctly | |
1613 (put-text-property (1- pos1) (1- pos2) | |
1614 'invisible | |
1615 (list (intern | |
1616 (concat | |
1617 (symbol-name | |
1618 (if (eq nt-type 'extra) 'desc nt-type)) | |
1619 "-" | |
1620 (symbol-name nt-age))) | |
1621 nt-type | |
1622 nt-age)) | |
1623 (setq nt-type (get-text-property pos2 'nt-type)) | |
1624 (setq nt-age (get-text-property pos2 'nt-age)) | |
1625 (setq pos1 pos2))))) | |
1626 | |
1627 (defun newsticker--set-face-properties (pos1 pos2 nt-face age) | |
1628 "Set the face for the text between the positions POS1 and POS2. | |
1629 The face is chosen according the values of NT-FACE and AGE." | |
1630 (let ((face (cond ((eq nt-face 'feed) | |
1631 'newsticker-feed-face) | |
1632 ((eq nt-face 'item) | |
1633 (cond ((eq age 'new) | |
1634 'newsticker-new-item-face) | |
1635 ((eq age 'old) | |
1636 'newsticker-old-item-face) | |
1637 ((eq age 'immortal) | |
1638 'newsticker-immortal-item-face) | |
1639 ((eq age 'obsolete) | |
1640 'newsticker-obsolete-item-face))) | |
1641 ((eq nt-face 'date) | |
1642 'newsticker-date-face) | |
1643 ((eq nt-face 'stat) | |
1644 'newsticker-statistics-face) | |
1645 ((eq nt-face 'extra) | |
1646 'newsticker-extra-face) | |
1647 ((eq nt-face 'enclosure) | |
1648 'newsticker-enclosure-face)))) | |
1649 (when face | |
1650 (put-text-property pos1 (max pos1 pos2) 'face face)))) | |
1651 | |
1652 ;; ====================================================================== | |
1653 ;;; Functions working on the *newsticker* buffer | |
1654 ;; ====================================================================== | |
1655 (defun newsticker--buffer-make-item-completely-visible () | |
1656 "Scroll buffer until current item is completely visible." | |
1657 (when newsticker--auto-narrow-to-feed | |
1658 (let* ((min (or (save-excursion (newsticker--buffer-beginning-of-feed)) | |
1659 (point-min))) | |
1660 (max (or (save-excursion (newsticker--buffer-end-of-feed)) | |
1661 (point-max)))) | |
1662 (narrow-to-region min max))) | |
1663 (when newsticker--auto-narrow-to-item | |
1664 (let* ((min (or (save-excursion (newsticker--buffer-beginning-of-item)) | |
1665 (point-min))) | |
1666 (max (or (save-excursion (newsticker--buffer-end-of-item)) | |
1667 (point-max)))) | |
1668 (narrow-to-region min max))) | |
1669 (sit-for 0) | |
1670 ;; do not count lines and stuff because that does not work when images | |
1671 ;; are displayed. Do it the simple way: | |
1672 (save-excursion | |
1673 (newsticker--buffer-end-of-item) | |
1674 (unless (pos-visible-in-window-p) | |
1675 (recenter -1))) | |
1676 (unless (pos-visible-in-window-p) | |
1677 (recenter 0))) | |
1678 | |
1679 (defun newsticker--buffer-get-feed-title-at-point () | |
1680 "Return feed symbol of headline at point." | |
1681 (format "%s" (or (get-text-property (point) 'feed) " "))) | |
1682 | |
1683 (defun newsticker--buffer-get-item-title-at-point () | |
1684 "Return feed symbol of headline at point." | |
1685 (format "%s" (or (get-text-property (point) 'nt-title) " "))) | |
1686 | |
1687 (defun newsticker--buffer-goto (types &optional age backwards) | |
1688 "Search next occurrence of TYPES in current buffer. | |
1689 TYPES is a list of symbols. If TYPES is found point is moved, if | |
1690 not point is left unchanged. If optional parameter AGE is not | |
1691 nil, the type AND the age must match. If BACKWARDS is t, search | |
1692 backwards." | |
1693 (let ((pos (save-excursion | |
1694 (save-restriction | |
1695 (widen) | |
1696 (catch 'found | |
1697 (let ((tpos (point))) | |
1698 (while (setq tpos | |
1699 (if backwards | |
1700 (if (eq tpos (point-min)) | |
1701 nil | |
1702 (or (previous-single-property-change | |
1703 tpos 'nt-type) | |
1704 (point-min))) | |
1705 (next-single-property-change | |
1706 tpos 'nt-type))) | |
1707 (and (memq (get-text-property tpos 'nt-type) types) | |
1708 (or (not age) | |
1709 (eq (get-text-property tpos 'nt-age) age)) | |
1710 (throw 'found tpos))))))))) | |
1711 (when pos | |
1712 (goto-char pos)) | |
1713 pos)) | |
1714 | |
1715 (defun newsticker--buffer-hideshow (mark-age onoff) | |
1716 "Hide or show items of type MARK-AGE. | |
1717 If ONOFF is nil the item is hidden, otherwise it is shown." | |
1718 (if onoff | |
1719 (remove-from-invisibility-spec mark-age) | |
1720 (add-to-invisibility-spec mark-age))) | |
1721 | |
1722 (defun newsticker--buffer-beginning-of-item () | |
1723 "Move point to the beginning of the item at point. | |
1724 Return new position." | |
1725 (if (bobp) | |
1726 (point) | |
1727 (let ((type (get-text-property (point) 'nt-type)) | |
1728 (typebefore (get-text-property (1- (point)) 'nt-type))) | |
1729 (if (and (memq type '(item feed)) | |
1730 (not (eq type typebefore))) | |
1731 (point) | |
1732 (newsticker--buffer-goto '(item feed) nil t) | |
1733 (point))))) | |
1734 | |
1735 (defun newsticker--buffer-beginning-of-feed () | |
1736 "Move point to the beginning of the feed at point. | |
1737 Return new position." | |
1738 (if (bobp) | |
1739 (point) | |
1740 (let ((type (get-text-property (point) 'nt-type)) | |
1741 (typebefore (get-text-property (1- (point)) 'nt-type))) | |
1742 (if (and (memq type '(feed)) | |
1743 (not (eq type typebefore))) | |
1744 (point) | |
1745 (newsticker--buffer-goto '(feed) nil t) | |
1746 (point))))) | |
1747 | |
1748 (defun newsticker--buffer-end-of-item () | |
1749 "Move point to the end of the item at point. | |
1750 Take care: end of item is at the end of its last line!" | |
1751 (when (newsticker--buffer-goto '(item feed nil)) | |
1752 (point))) | |
1753 | |
1754 (defun newsticker--buffer-end-of-feed () | |
1755 "Move point to the end of the last item of the feed at point. | |
1756 Take care: end of item is at the end of its last line!" | |
1757 (when (newsticker--buffer-goto '(feed nil)) | |
1758 (backward-char 1) | |
1759 (point))) | |
1760 | |
1761 ;; ====================================================================== | |
1762 ;;; misc | |
1763 ;; ====================================================================== | |
1764 | |
1765 (defun newsticker-mouse-browse-url (event) | |
1766 "Call `browse-url' for the link of the item at which the EVENT occurred." | |
1767 (interactive "e") | |
1768 (save-excursion | |
1769 (switch-to-buffer (window-buffer (posn-window (event-end event)))) | |
1770 (let ((url (get-text-property (posn-point (event-end event)) | |
1771 'nt-link))) | |
1772 (when url | |
1773 (browse-url url) | |
1774 (save-excursion | |
1775 (goto-char (posn-point (event-end event))) | |
1776 (if newsticker-automatically-mark-visited-items-as-old | |
1777 (newsticker-mark-item-at-point-as-read t))))))) | |
1778 | |
1779 (defun newsticker-browse-url () | |
1780 "Call `browse-url' for the link of the item at point." | |
1781 (interactive) | |
1782 (let ((url (get-text-property (point) 'nt-link))) | |
1783 (when url | |
1784 (browse-url url) | |
1785 (if newsticker-automatically-mark-visited-items-as-old | |
1786 (newsticker-mark-item-at-point-as-read t))))) | |
1787 | |
1788 (defvar newsticker-open-url-history | |
1789 '("wget" "xmms" "realplay") | |
1790 "...") | |
1791 | |
1792 (defun newsticker-handle-url () | |
1793 "Ask for a program to open the link of the item at point." | |
1794 (interactive) | |
1795 (let ((url (get-text-property (point) 'nt-link))) | |
1796 (when url | |
1797 (let ((prog (read-string "Open url with: " nil | |
1798 'newsticker-open-url-history))) | |
1799 (when prog | |
1800 (message "%s %s" prog url) | |
1801 (start-process prog prog prog url) | |
1802 (if newsticker-automatically-mark-visited-items-as-old | |
1803 (newsticker-mark-item-at-point-as-read t))))))) | |
1804 | |
1805 | |
1806 ;; ====================================================================== | |
1807 ;;; Misc | |
1808 ;; ====================================================================== | |
1809 | |
1810 (defun newsticker--cache-sort () | |
1811 "Sort the newsticker cache data." | |
1812 (let ((sort-fun (cond ((eq newsticker-sort-method 'sort-by-time) | |
1813 'newsticker--cache-item-compare-by-time) | |
1814 ((eq newsticker-sort-method 'sort-by-title) | |
1815 'newsticker--cache-item-compare-by-title) | |
1816 ((eq newsticker-sort-method 'sort-by-original-order) | |
1817 'newsticker--cache-item-compare-by-position)))) | |
1818 (mapc (lambda (feed-list) | |
1819 (setcdr feed-list (sort (cdr feed-list) | |
1820 sort-fun))) | |
1821 newsticker--cache))) | |
1822 | |
1823 (provide 'newsticker-plainview) | |
95684 | 1824 |
1825 ;; arch-tag: 4e48b683-d48b-48dd-a13e-fe45baf41184 | |
95676 | 1826 ;;; newsticker-plainview.el ends here |