]> git.eshelyaron.com Git - emacs.git/commitdiff
Newsticker: Add commands to rearrange treeview groups and document them. (Bug#12560)
authorUlf Jasper <ulf.jasper@web.de>
Wed, 24 Sep 2014 17:33:54 +0000 (19:33 +0200)
committerUlf Jasper <ulf.jasper@web.de>
Wed, 24 Sep 2014 17:33:54 +0000 (19:33 +0200)
2014-09-24  Ulf Jasper  <ulf.jasper@web.de>

* newsticker.texi: Reworked.  Document new treeview group
commands.  Remove VERSION, UPDATED, use EMACSVER instead.  Use
term 'feed reader'.

2014-09-24  Ulf Jasper  <ulf.jasper@web.de>

* automated/newsticker-tests.el
(newsticker--group-find-parent-group),
(newsticker--group-do-rename-group): New tests.

2014-09-24  Ulf Jasper  <ulf.jasper@web.de>

* net/newst-treeview.el (newsticker--treeview-do-get-node-by-id):
Renamed `newsticker--treeview-do-get-node' to
`newsticker--treeview-do-get-node-by-id'.
(newsticker--treeview-get-node-by-id): Renamed
`newsticker--treeview-get-node' to
`newsticker--treeview-get-node-by-id'.
(newsticker--treeview-get-current-node): Renamed `
`newsticker--treeview-get-node' to
`newsticker--treeview-get-node-by-id'.
(newsticker--treeview-buffer-init)
(newsticker--treeview-buffer-init): Disable buffer undo.
(newsticker--treeview-unfold-node): Adapted to modified
`newsticker--group-find-parent-group'.
(newsticker--group-do-find-group): Renamed
`newsticker--group-do-find-group-for-feed' to
`newsticker--group-do-find-group'.  Now works for both, groups and
feeds.
(newsticker--group-find-parent-group): Renamed
`newsticker--group-find-group-for-feed' to
`newsticker--group-find-parent-group'.  Now works for both, groups
and feeds.
(newsticker--group-do-get-parent-group)
(newsticker--group-get-parent-group): Removed.
(newsticker-group-add-group): Changed interactive prompts.
(newsticker-group-add-group): Finally jump to added group.
(newsticker-group-delete-group): Finally jump to current feed.
(newsticker--group-do-rename-group, newsticker-group-rename-group)
(newsticker--get-group-names, newsticker--group-names): New.
(newsticker-group-move-feed): Finally jump to moved feed.
(newsticker-group-shift-feed-down, newsticker-group-shift-feed-up)
(newsticker-group-shift-group-down)
(newsticker-group-shift-group-up, newsticker--group-shift): New
(newsticker--group-manage-orphan-feeds): Renamed
`newsticker--group-find-group-for-feed' to
`newsticker--group-find-parent-group'.
(newsticker-treeview-mode-map): New keybindings for new shift commands.
(newsticker-treeview-tree-do-click): Renamed
`newsticker--treeview-get-node' to
`newsticker--treeview-get-node-by-id'.

* net/newst-backend.el (newsticker--item-list)
(newsticker--item-position, newsticker--prev-message)
(newsticker--scrollable-text): Moved to newst-ticker.el.

* net/newst-ticker.el (newsticker--item-list)
(newsticker--item-position, newsticker--prev-message)
(newsticker--scrollable-text): Moved from newst-backend.el.

doc/misc/ChangeLog
doc/misc/newsticker.texi
lisp/ChangeLog
lisp/net/newst-backend.el
lisp/net/newst-ticker.el
lisp/net/newst-treeview.el
test/ChangeLog
test/automated/newsticker-tests.el

index 8b7bb7498c97381f4c889a62de33473a524e85ed..2963bde04e16ab60972ff31f7cf1bdf18e4b69b5 100644 (file)
@@ -1,3 +1,9 @@
+2014-09-24  Ulf Jasper  <ulf.jasper@web.de>
+
+       * newsticker.texi: Reworked.  Document new treeview group
+       commands.  Remove VERSION, UPDATED, use EMACSVER instead.  Use
+       term 'feed reader'.
+
 2014-09-04  Paul Eggert  <eggert@cs.ucla.edu>
 
        Less chatter in 'make' output.
index ec1236d531b445a017d2381a056cb69347e21b0e..c79b1d899ba29afd541242e5c326c7e2b6284b05 100644 (file)
@@ -1,8 +1,8 @@
 \input texinfo   @c -*-texinfo-*-
 @comment %**start of header
 @setfilename ../../info/newsticker.info
-@set VERSION 1.99
-@set UPDATED June 2008
+@include emacsver.texi
+@set VERSION @value{EMACSVER}
 @settitle Newsticker @value{VERSION}
 @syncodeindex vr cp
 @syncodeindex fn cp
@@ -11,7 +11,8 @@
 @comment %**end of header
 
 @copying
-This manual is for Newsticker (version @value{VERSION}, @value{UPDATED}).
+This manual documents Newsticker, a feed reader for Emacs.  It
+corresponds to Emacs version @value{EMACSVER}.
 
 @noindent
 Copyright @copyright{} 2004--2014 Free Software Foundation, Inc.
@@ -31,12 +32,11 @@ modify this GNU manual.''
 
 @dircategory Emacs network features
 @direntry
-* Newsticker: (newsticker).     A Newsticker for Emacs.
+* Newsticker: (newsticker).     A feed reader for Emacs.
 @end direntry
 
 @titlepage
-@title Newsticker---a Newsticker for Emacs
-@subtitle for version @value{VERSION}, @value{UPDATED}
+@title Newsticker---a feed reader for Emacs
 @author Ulf Jasper
 @author @email{ulf.jasper@@web.de}
 @author @uref{http://ulf.epplejasper.de/}
@@ -56,136 +56,419 @@ modify this GNU manual.''
 @end ifnottex
 
 @menu
-* Overview::        General description of newsticker.
-* Requirements::    Requirements for using newsticker.
-* Installation::    Installing newsticker on your system.
-* Usage::           Basic newsticker instructions.
-* Configuration::   Customizable newsticker settings.
-* Remarks::         Remarks about newsticker.
+* Overview::             What is Newsticker?
+* Installation::         Things to do before starting Newsticker the first time.
+* Retrieving News::      How Newsticker fetches headlines.
+* Headline Management::  How Newsticker stores headlines.
+* Reading News::         How to read RSS and Atom feeds with Newsticker.
+* Automatic Processing:: Automatically process news items.
+* Configuration::        Customize Newsticker to your liking.
+* Supported Formats::    RSS and Atom formats supported by Newsticker.
+
 * GNU Free Documentation License:: The license for this documentation.
-* Index::           Variable, function, and concept index.
+* Index::                          Variable, function, and concept index.
 @end menu
 
 @node Overview
 @chapter Overview
 
-Newsticker provides a newsticker for Emacs.  A newsticker is a thing
-that asynchronously retrieves headlines from a list of news sites,
-prepares these headlines for reading, and allows for loading the
-corresponding articles in a web browser.
+Newsticker provides a @b{Feed Reader} for Emacs.  It retrieves
+headlines from a list of news sites, processes them, and provides
+frontends for reading and managing them. (Standard headline formats
+are RSS and Atom which makes Newsticker an ``RSS Reader'', ``Atom
+Reader'' or ``Feed Aggregator''.)
 
+Headlines (or news items) consist of a title, (mostly) a description,
+and a link to the full story. The description may be a brief summary
+in plain text or a full HTML-formatted article.  A headline may carry
+enclosed data such as images, audio or video files, typically in the
+case of so ``podcast feeds''.
 
-Headlines consist of a title and (possibly) a small description.  They
-are contained in ``RSS'' (RDF Site Summary) or ``Atom'' files.  Newsticker
-works with the following RSS formats:
+Newsticker downloads headlines asynchronously at configurable times,
+processes and stores them so that you can read them later.  The list
+of subscribed feeds, the headline processing, the presentation of the
+headlines and almost all other aspects of Newsticker can be
+customized to your liking.
 
-@itemize
-@item RSS 0.91 (see @uref{http://backend.userland.com/rss091} or
-@uref{http://my.netscape.com/publish/formats/rss-spec-0.91.html}),
-@item RSS 0.92 (see @uref{http://backend.userland.com/rss092}),
-@item RSS 1.0 (see @uref{http://purl.org/rss/1.0/spec}
-@item RSS 2.0 (see @uref{http://blogs.law.harvard.edu/tech/rss}),
-@end itemize
-@itemize
-as well as the following Atom formats:
-@item Atom 0.3
-@item Atom 1.0 (see
-@uref{https://datatracker.ietf.org/doc/rfc4287/}).
-@end itemize
+@node Installation
+@chapter Installation
 
-That makes Newsticker.el an ``Atom aggregator'', ``RSS reader'', ``Feed
-aggregator'', or ``Feed reader''.
+As Newsticker is part of GNU Emacs there is no need to perform any
+installation steps in order to use it.
 
-Newsticker provides several commands for reading headlines, navigating
-through them, marking them as read/unread, hiding old headlines etc.
-Headlines can be displayed as plain text or as rendered HTML.
+Newsticker is highly customizable. All options have reasonable default
+values, so that (in most cases) it is not necessary to customize
+anything before you start Newsticker for the first time.
 
-Headlines can be displayed in the echo area, either scrolling like
-messages in a stock-quote ticker, or just changing.
-
-Newsticker allows for automatic processing of headlines by providing
-hooks and (sample) functions for automatically downloading images and
-enclosed files (as delivered by, e.g., podcasts).
-
-@ignore
-@ifhtml
-Here are screen shots of the @uref{newsticker-1.7.png, version 1.7
-(current version)} and some older screen shots:
-@uref{newsticker-1.6.png, version 1.6},
-@uref{newsticker-1.5.png, version 1.5},
-@uref{newsticker-1.4.png, version 1.4}
-@uref{newsticker-1.3.png, version 1.3},
-@uref{newsticker-1.0.png, version 1.0}.
-@end ifhtml
-@end ignore
-
-@node Requirements
-@chapter Requirements
-
-Newsticker can be used with
-@uref{http://www.gnu.org/software/emacs/emacs.html, GNU Emacs} version
-21.1 or later as well as @uref{http://www.xemacs.org, XEmacs}.  It
-requires an XML-parser (@file{xml.el}), which is part of GNU Emacs.  If
-you are using XEmacs you want to get the @file{net-utils} package
-which contains @file{xml.el} for XEmacs.
-
-Newsticker retrieves headlines either via Emacs's built-in retrieval
-functions, by an arbitrary external program that retrieves files via
-http and prints them to stdout (like
-@uref{http://www.gnu.org/software/wget/wget.html, wget}, or---on a
-per feed basis---via an arbitrary Lisp command.
+@node Retrieving News
+@chapter Retrieving News
 
+Newsticker downloads news periodically in the background.  This is
+triggered as soon as you start reading news (@ref{Reading News}).
 
-@node Installation
-@chapter Installation
+@findex newsticker-start
+@findex newsticker-stop
+Alternatively you may use the command @code{newsticker-start}
+(@code{newsticker-stop}) in order to start (stop) the periodic
+download of news without opening the reader.
 
-As Newsticker is part of GNU Emacs there is no need to perform any
-installation steps in order to use Newsticker.
+The following variables define which feeds are fetched and how this is
+done.
+
+@table @code
+@vindex newsticker-url-list-defaults
+@item newsticker-url-list-defaults
+You may select any number of feeds from this list of (sample) news feeds.
+
+@vindex newsticker-url-list
+@item newsticker-url-list
+All your personal news feeds are defined here.  Each feed is
+identified by its name and an URL.  You may set the start-time and the
+retrieval interval for each feed as well as the retrieval command
+arguments in case that the default values do not fit a certain feed.
+
+@vindex newsticker-retrieval-method
+@vindex newsticker-wget-name
+@vindex newsticker-wget-arguments
+@item newsticker-retrieval-method
+By default Newsticker uses Emacs's built-in download capabilities for
+fetching headlines.  You may change this to use an external tool like
+@code{wget}.  In this case you need to set @code{newsticker-wget-name}
+and possibly @code{newsticker-wget-arguments}.
+
+@vindex newsticker-retrieval-interval
+@item newsticker-retrieval-interval
+The number of seconds between headline retrievals.
+@end table
+
+@node Headline Management
+@chapter Headline Management
+
+@cindex Age
+@cindex Status
+
+Newsticker assigns a status (or ``age'') to each headline which you
+can modify manually.  This makes it easy to distinguish new headlines
+from old ones, to keep important headlines, to hide boring headlines
+etc.  An item is ``new'' when it has just arrived and has not been
+read.  You can mark it as ``old'' when you have read it or -- if you
+want to keep it -- you can mark it as ``immortal''.  You can do that
+manually and you can define filters which do that automatically, see
+below.  When a headline has vanished from the feed it is automatically
+marked as ``obsolete'' unless it has the status ``immortal''.
+``Obsolete'' headlines get removed automatically after a certain time.
+
+@table @code
+@cindex Filter
+@vindex newsticker-auto-mark-filter-list
+@item newsticker-auto-mark-filter-list
+You may define any number of filters for automatically marking newly
+arrived headlines as ``immortal'' or ``old''.  A filter looks for a
+regular expression in either the title or the description of a
+headline and then, if the expression matches, marks the headline as
+``immortal'' or as ``old''.  This is done only once, when a headline
+is fetched for the very first time.
+
+@vindex newsticker-keep-obsolete-items
+@vindex newsticker-obsolete-item-max-age
+@item newsticker-keep-obsolete-items
+Obsolete headlines are removed immediately unless
+@code{newsticker-keep-obsolete-items} is non-nil in which case they
+are kept until @code{newsticker-obsolete-item-max-age} is reached.
+
+@vindex newsticker-automatically-mark-items-as-old
+@item newsticker-automatically-mark-items-as-old
+If this is set to `t' then a ``new'' item becomes ``old'' as soon as
+it is retrieved a second time.
+
+@end table
+
+@node Reading News
+@chapter Reading News
+
+@findex newsticker-show-news
+Start Newsticker with the command @kbd{M-x newsticker-show-news}. This
+will start the asynchronous news download and displays all available
+headlines.
+
+@menu
+* Frontends::        Select the way headlines are displayed.
+* Navigation::       Move to the next unread headline etc.
+* Marking::          Mark important headlines.
+* More Actions::     Add new feeds etc..
+@end menu
+
+@node Frontends
+@section Frontends
+@cindex Frontends
+
+@vindex newsticker-frontend
+Newsticker provides two different @i{views} for browsing, marking and
+reading news.  The variable @code{newsticker-frontend} determines the
+actual headline reader.
+
+@subheading Treeview
+@cindex Treeview
+
+In this view separate windows are used for displaying feeds, headlines
+and their descriptions.  The feeds are shown as a tree on the left
+hand side, headlines of the currently selected feed are shown on the
+upper right side, and the full contents of the currently selected
+headline is shown on the lower right side.
+
+Feeds can be placed into groups, which themselves can be placed in
+groups and so on.  This results in the tree which is displayed on the
+left.  A node represents either a feed or a group of feeds holding a
+subtree.  The following commands allow for managing groups.
+
+@table @kbd
+@item M-a
+@kindex M-a
+@findex newsticker-group-add-group
+Add a new feed group. Name of the new group and of the parent group
+must be entered.  If The name of the parent group is the new group
+becomes a top-level group. (@code{newsticker-group-add-group})
+@item M-m
+@kindex M-m
+@findex newsticker-group-move-feed
+Moves a feed into a group. The name of the group must be
+entered. (@code{newsticker-group-move-feed})
+@end table
+
+The position of groups and feeds within the tree can be changed with these
+commands:
+
+@table @kbd
+@item M-up
+@itemx M-down
+@kindex M-up
+@kindex M-down
+@findex newsticker-group-shift-feed-up
+@findex newsticker-group-shift-feed-down
+Shift the currently selected feed up and down within its group.
+@item M-S-up
+@itemx M-S-down
+@kindex M-S-up
+@kindex M-S-down
+@findex newsticker-group-shift-group-up
+@findex newsticker-group-shift-group-down
+Shift the currently selected group up and down within its parent group.
+@end table
+
+The group settings are saved to a file either automatically when
+newsticker is being quit or manually when the following command is
+executed.
+
+@table @kbd
+@item s
+@kindex s
+@findex newsticker-treeview-save
+Save treeview group settings.
+@end table
+
+The Treeview is updated automatically as soon as new headlines have
+arrived.
+
+The Treeview is used when the variable @code{newsticker-frontend} is
+set to the value @code{newsticker-treeview}. (Alternatively it can be
+started with the command @code{newsticker-treeview}.)
+
+@subheading Plainview
+@cindex Plainview
 
-However, if you are using imenu, which allows for navigating with the
-help of a menu, you should add the following to your Emacs startup file
-(@file{~/.emacs}).
+In this view all headlines of all feeds are displayed in a single
+buffer (@file{*newsticker*}). The modeline in the @file{*newsticker*}
+buffer informs you whenever new headlines have arrived.
+
+You may want to use imenu with Plainview, which allows for navigating
+with the help of a menu. In this case add the following to your Emacs
+startup file (@file{~/.emacs}).
 
 @lisp
 (add-hook 'newsticker-mode-hook 'imenu-add-menubar-index)
 @end lisp
 
-That's it.
+(Note that preparing the Plainview takes significantly more time than
+starting the Treeview because all headlines are displayed in a single
+buffer.  When you have subscribed to a large amount of feeds you may
+find that Newsticker's efforts of minimizing rendering times, caching
+rendered items and so on  you may find However, when you have
+subscribed to a large amount of feeds you may want to give the
+Treeview a try.)
 
-@node Usage
-@chapter Usage
+The Plainview is used when the variable @code{newsticker-frontend} is
+set to the value @code{newsticker-plainview}. (Alternatively it can be
+started with the command @code{newsticker-plainview}.)
 
-@findex newsticker-show-news
-The command @code{newsticker-show-news} will display all available
-headlines.  It will also start the asynchronous download of headlines.
+@subheading Ticker
+@cindex Ticker
 
-You can choose between two different frontends for reading headlines:
-@itemize
-@item Newsticker's @emph{treeview} uses separate windows for the
-feeds (in tree form), a list of headlines for the current feed, and
-the content of the current headline.  Feeds can be placed into groups,
-which themselves can be placed in groups and so on.
-@item Newsticker's @emph{plainview} displays all headlines in a
-single buffer, called @file{*newsticker*}.  The modeline in the
-@file{*newsticker*} buffer informs you whenever new headlines have
-arrived.
-@end itemize
-In both views clicking mouse-button 2 or pressing @key{RET} on a
-headline will call @code{browse-url} to load the corresponding news
-story in your favorite web browser.
+Additionally, headlines can be displayed in the echo area in the style of a
+news ticker.
 
 @findex newsticker-start-ticker
 @findex newsticker-stop-ticker
-The scrolling, or flashing of headlines in the echo area, can be
+Headlines can be displayed in the echo area, either scrolling like
+messages in a stock-quote ticker, or just changing.  This can be
 started with the command @code{newsticker-start-ticker}.  It can be
 stopped with @code{newsticker-stop-ticker}.
 
-@findex newsticker-start
-@findex newsticker-stop
-If you just want to start the periodic download of headlines use the
-command @code{newsticker-start}.  Calling @code{newsticker-stop} will
-stop the periodic download, but will call
-@code{newsticker-stop-ticker} as well.
+
+@node Navigation
+@section Navigation
+@cindex Navigation
+
+Navigating through the list of feeds and headlines is rather
+straightforward.  You may do this either with the mouse or with the
+keyboard.  The following key bindings are provided in both, the
+Treeview as well as the Plainview.
+
+@table @kbd
+@item f
+@findex newsticker-next-feed
+@findex newsticker-treeview-next-feed
+Move to next feed (@code{newsticker-next-feed},
+@code{newsticker-treeview-next-feed}).
+@item F
+@findex newsticker-previous-feed
+@findex newsticker-treeview-prev-feed
+Move to previous feed (@code{newsticker-previous-feed},
+@code{newsticker-treeview-prev-feed}).
+@item n
+@findex newsticker-next-item
+@findex newsticker-treeview-next-item
+Move to next item (@code{newsticker-next-item},
+@code{newsticker-treeview-next-item}).
+@item N
+@findex newsticker-next-new-item
+@findex newsticker-treeview-next-new-item
+Move to next new item (possibly in another feed)
+(@code{newsticker-next-new-item},
+@code{newsticker-treeview-next-new-item}).
+@item p
+@findex newsticker-previous-item
+@findex newsticker-treeview-prev-item
+Move to previous item (@code{newsticker-previous-item},
+@code{newsticker-treeview-prev-item}).
+@item P
+@findex newsticker-previous-new-item
+@findex newsticker-treeview-prev-new-item
+Move to previous new item (possibly in another feed)
+(@code{newsticker-previous-new-item},
+@code{newsticker-treeview-prev-new-item}).
+@end table
+
+@subheading Treeview
+@table @kbd
+@item j
+@findex newsticker-treeview-jump
+Enter the name of a feed and jump to it
+(@code{newsticker-treeview-jump}).
+@end table
+
+
+@node Marking
+@section Marking
+@cindex Marking
+
+The following key bindings are provided in both, the Treeview as well
+as the Plainview.
+
+@table @kbd
+@item o
+@findex newsticker-mark-item-at-point-as-read
+@findex newsticker-treeview-mark-item-old
+Mark current item as old.
+(@code{newsticker-mark-item-at-point-as-read},
+@code{newsticker-treeview-mark-item-old}).
+@item i
+@findex newsticker-mark-item-at-point-as-immortal
+@findex newsticker-treeview-mark-item-immortal
+Mark current item as immortal.  Immortal items are kept forever.
+(@code{newsticker-mark-item-at-point-as-immortal},
+@code{newsticker-treeview-mark-item-immortal}).
+@end table
+
+@node More Actions
+@section More Actions
+@cindex More Actions
+
+@subheading View full article
+@table @kbd
+@cindex Get News
+@item v
+@itemx RET
+@itemx <mouse-1>
+@findex newsticker-treeview-browse-url
+Open the link to the full article (as contained in the current
+headline) in your web browser @code{newsticker-treeview-browse-url}).
+@end table
+
+@subheading Get News
+@cindex Get News
+
+You can force immediate download of news with the following commands.
+
+@table @kbd
+@item g
+@findex newsticker-treeview-get-news
+Get news for currently shown feed (@code{newsticker-treeview-get-news}).
+@item G
+@findex newsticker-get-all-news
+Get news for all feeds (@code{newsticker-get-all-news}).
+@end table
+
+@subheading Add More Feeds
+@cindex Add More Feeds
+
+@table @kbd
+@item a
+@findex newsticker-add-url
+The command @code{newsticker-add-url} prompts for an URL and a name of
+a new feed.  It then prepares a customization buffer where the details
+of the new feed can be set.
+@end table
+
+
+@node Automatic Processing
+@chapter Automatic Processing
+@cindex Automatic Processing
+
+Apart from automatic marking of headlines (by means of filters)
+Newsticker provides the possibility to fully process newly arrived
+headlines.  Instead of reading headlines yourself you can tell
+Newsticker to do that for you.
+
+@vindex newsticker-new-item-functions
+In order to do so write a function which takes three arguments
+
+@table @var
+@item FEED
+the name of the corresponding news feed,
+@item TITLE
+the title of the headline,
+@item DESC
+the decoded description of the headline.
+@end table
+
+and add it to @code{newsticker-new-item-functions}.  Each function
+contained in this list is called once for each new headline.
+Depending on the feed, the title and the description of a headline you
+can
+
+@itemize
+@item
+automatically download images referenced in HTML-formatted
+descriptions (for which a function already exists, see
+@code{newsticker-download-images}),
+@item
+automatically save enclosed audio and video files (for which another
+function exists as well, see @code{newsticker-download-images}),
+@item
+flash the screen while playing some sound,
+@item
+whatever you want.
+@end itemize
 
 @node Configuration
 @chapter Configuration
@@ -195,11 +478,8 @@ Emacs customization methods.  Call the command
 @code{customize-group} and enter @samp{newsticker} for the customization
 group.
 
-All Newsticker options have reasonable default values, so that in most
-cases it is not necessary to customize settings before starting Newsticker
-for the first time.
-
-The following list shows the available groups of newsticker options
+@noindent
+The following list shows the available groups of Newsticker options
 and some of the most important options.
 
 @itemize
@@ -296,13 +576,35 @@ treeview reader.
 
 @end itemize
 
+@noindent
 For the complete list of options please have a look at the
 customization buffers.
 
-@node Remarks
-@chapter Remarks
+@node Supported Formats
+@appendix Supported Formats
+@cindex Supported Formats
+
+Newsticker works with the standard RSS and Atom formats listed below
+(being lenient with feeds which break the specifications).
+
+@subheading RSS formats
+
+@itemize
+@item RSS 0.91 (see @uref{http://backend.userland.com/rss091} or
+@uref{http://my.netscape.com/publish/formats/rss-spec-0.91.html})
+@item RSS 0.92 (see @uref{http://backend.userland.com/rss092})
+@item RSS 1.0 (see @uref{http://purl.org/rss/1.0/spec})
+@item RSS 2.0 (see @uref{http://blogs.law.harvard.edu/tech/rss})
+@end itemize
+@itemize
+
+@subheading Atom formats
+
+@item Atom 0.3
+@item Atom 1.0 (see
+@uref{https://datatracker.ietf.org/doc/rfc4287/})
+@end itemize
 
-Byte-compiling newsticker.el is recommended.
 
 @node GNU Free Documentation License
 @appendix GNU Free Documentation License
@@ -310,7 +612,7 @@ Byte-compiling newsticker.el is recommended.
 
 @node Index
 @unnumbered Index
-
 @printindex cp
 
+
 @bye
index 271be39eea991dc0beeadb9baf365ada8298ca2b..937d0a40b3037e67888c989479e43fc56745f7bb 100644 (file)
@@ -1,3 +1,54 @@
+2014-09-24  Ulf Jasper  <ulf.jasper@web.de>
+
+       * net/newst-treeview.el (newsticker--treeview-do-get-node-by-id):
+       Renamed `newsticker--treeview-do-get-node' to
+       `newsticker--treeview-do-get-node-by-id'.
+       (newsticker--treeview-get-node-by-id): Renamed
+       `newsticker--treeview-get-node' to
+       `newsticker--treeview-get-node-by-id'.
+       (newsticker--treeview-get-current-node): Renamed `
+       `newsticker--treeview-get-node' to
+       `newsticker--treeview-get-node-by-id'.
+       (newsticker--treeview-buffer-init)
+       (newsticker--treeview-buffer-init): Disable buffer undo.
+       (newsticker--treeview-unfold-node): Adapted to modified
+       `newsticker--group-find-parent-group'.
+       (newsticker--group-do-find-group): Renamed
+       `newsticker--group-do-find-group-for-feed' to
+       `newsticker--group-do-find-group'.  Now works for both, groups and
+       feeds.
+       (newsticker--group-find-parent-group): Renamed
+       `newsticker--group-find-group-for-feed' to
+       `newsticker--group-find-parent-group'.  Now works for both, groups
+       and feeds.
+       (newsticker--group-do-get-parent-group)
+       (newsticker--group-get-parent-group): Removed.
+       (newsticker-group-add-group): Changed interactive prompts.
+       (newsticker-group-add-group): Finally jump to added group.
+       (newsticker-group-delete-group): Finally jump to current feed.
+       (newsticker--group-do-rename-group, newsticker-group-rename-group)
+       (newsticker--get-group-names, newsticker--group-names): New.
+       (newsticker-group-move-feed): Finally jump to moved feed.
+       (newsticker-group-shift-feed-down, newsticker-group-shift-feed-up)
+       (newsticker-group-shift-group-down)
+       (newsticker-group-shift-group-up, newsticker--group-shift): New
+       (newsticker--group-manage-orphan-feeds): Renamed
+       `newsticker--group-find-group-for-feed' to
+       `newsticker--group-find-parent-group'.
+       (newsticker-treeview-mode-map): New keybindings for new shift commands.
+       (newsticker-treeview-tree-do-click): Renamed
+       `newsticker--treeview-get-node' to
+       `newsticker--treeview-get-node-by-id'.
+
+       * net/newst-backend.el (newsticker--item-list)
+       (newsticker--item-position, newsticker--prev-message)
+       (newsticker--scrollable-text): Moved to newst-ticker.el.
+
+       * net/newst-ticker.el (newsticker--item-list)
+       (newsticker--item-position, newsticker--prev-message)
+       (newsticker--scrollable-text): Moved from newst-backend.el.
+
+
 2014-09-22  Kan-Ru Chen  <kanru@kanru.info>
 
        * window.el (fit-window-to-buffer): When counting buffer width,
index f67baccda7ce7c1877dbdbf147d51a86c7a66b83..ac862268b589cd1d26624a4bcdf0b5bdbb4bba0e 100644 (file)
@@ -6,7 +6,7 @@
 ;; Filename:    newst-backend.el
 ;; URL:         http://www.nongnu.org/newsticker
 ;; Keywords:    News, RSS, Atom
-;; Time-stamp:  "13. Mai 2011, 20:47:05 (ulf)"
+;; Time-stamp:  "23. September 2014, 19:51:10 (ulf)"
 ;; Package:     newsticker
 
 ;; ======================================================================
@@ -483,14 +483,6 @@ that can be added."
 ;; ======================================================================
 ;;; Internal variables
 ;; ======================================================================
-(defvar newsticker--item-list nil
-  "List of newsticker items.")
-(defvar newsticker--item-position 0
-  "Actual position in list of newsticker items.")
-(defvar newsticker--prev-message "There was no previous message yet!"
-  "Last message that the newsticker displayed.")
-(defvar newsticker--scrollable-text ""
-  "The text which is scrolled smoothly in the echo area.")
 (defvar newsticker--buffer-uptodate-p nil
   "Tells whether the newsticker buffer is up to date.")
 (defvar newsticker--latest-update-time (current-time)
index bf0e3981824921ff9536945be69511225904f32f..7e6021bcca09022dd4237c2f8a729aa9f1ba4eca 100644 (file)
@@ -6,7 +6,7 @@
 ;; Filename:    newst-ticker.el
 ;; URL:         http://www.nongnu.org/newsticker
 ;; Keywords:    News, RSS, Atom
-;; Time-stamp:  "6. Dezember 2009, 19:16:00 (ulf)"
+;; Time-stamp:  "24. September 2014, 19:07:25 (ulf)"
 ;; Package:     newsticker
 
 ;; ======================================================================
 
 (require 'newst-backend)
 
+(defvar newsticker--item-list nil
+  "List of newsticker items.")
+(defvar newsticker--item-position 0
+  "Actual position in list of newsticker items.")
+(defvar newsticker--prev-message "There was no previous message yet!"
+  "Last message that the newsticker displayed.")
+(defvar newsticker--scrollable-text ""
+  "The text which is scrolled smoothly in the echo area.")
 (defvar newsticker--ticker-timer nil
   "Timer for newsticker ticker.")
 
index acca575877a1b55e684ac2492f1ef464cdaa7011..05a476696cd9404df694c451c8623df323706689 100644 (file)
@@ -238,23 +238,23 @@ their id stays constant."
     (newsticker--treeview-do-get-node-of-feed feed-name
                                               newsticker--treeview-vfeed-tree)))
 
-(defun newsticker--treeview-do-get-node (id startnode)
+(defun newsticker--treeview-do-get-node-by-id (id startnode)
    "Recursively search node with ID starting from STARTNODE."
    (if (newsticker--treeview-ids-eq id (widget-get startnode :nt-id))
        (throw 'found startnode)
      (let ((children (widget-get startnode :children)))
        (dolist (w children)
-         (newsticker--treeview-do-get-node id w)))))
+         (newsticker--treeview-do-get-node-by-id id w)))))
 
-(defun newsticker--treeview-get-node (id)
+(defun newsticker--treeview-get-node-by-id (id)
   "Return node with ID in newsticker treeview tree."
   (catch 'found
-    (newsticker--treeview-do-get-node id newsticker--treeview-feed-tree)
-    (newsticker--treeview-do-get-node id newsticker--treeview-vfeed-tree)))
+    (newsticker--treeview-do-get-node-by-id id newsticker--treeview-feed-tree)
+    (newsticker--treeview-do-get-node-by-id id newsticker--treeview-vfeed-tree)))
 
 (defun newsticker--treeview-get-current-node ()
   "Return current node in newsticker treeview tree."
-  (newsticker--treeview-get-node newsticker--treeview-current-node-id))
+  (newsticker--treeview-get-node-by-id newsticker--treeview-current-node-id))
 
 ;; ======================================================================
 
@@ -1166,12 +1166,14 @@ Arguments IGNORE are ignored."
 
   (unless newsticker--selection-overlay
     (with-current-buffer (newsticker--treeview-list-buffer)
+      (setq buffer-undo-list t)
       (setq newsticker--selection-overlay (make-overlay (point-min)
                                                         (point-max)))
       (overlay-put newsticker--selection-overlay 'face
                    'newsticker-treeview-selection-face)))
   (unless newsticker--tree-selection-overlay
     (with-current-buffer (newsticker--treeview-tree-buffer)
+      (setq buffer-undo-list t)
       (setq newsticker--tree-selection-overlay (make-overlay (point-min)
                                                              (point-max)))
       (overlay-put newsticker--tree-selection-overlay 'face
@@ -1218,7 +1220,7 @@ Note: does not update the layout."
   (newsticker-treeview-save))
 
 (defun newsticker-treeview-save ()
-  "Save newsticker data including treeview settings."
+  "Save treeview group settings."
   (interactive)
   (let ((coding-system-for-write 'utf-8)
         (buf (find-file-noselect (concat newsticker-dir "/groups"))))
@@ -1598,10 +1600,8 @@ Return t if a new feed was activated, nil otherwise."
   "Recursively show subtree above the node that represents FEED-NAME."
   (let ((node (newsticker--treeview-get-node-of-feed feed-name)))
     (unless node
-      (let* ((group-name (or (car (newsticker--group-find-group-for-feed
-                                   feed-name))
-                             (newsticker--group-get-parent-group
-                              feed-name))))
+      (let* ((group-name (car (newsticker--group-find-parent-group
+                               feed-name))))
         (newsticker--treeview-unfold-node group-name))
       (setq node (newsticker--treeview-get-node-of-feed feed-name)))
     (when node
@@ -1625,20 +1625,31 @@ Return t if a new feed was activated, nil otherwise."
 ;; ======================================================================
 ;;; Groups
 ;; ======================================================================
-(defun newsticker--group-do-find-group-for-feed (feed-name node)
-  "Recursively find FEED-NAME in NODE."
-  (if (member feed-name (cdr node))
-      (throw 'found node)
-    (mapc (lambda (n)
-            (if (listp n)
-                (newsticker--group-do-find-group-for-feed feed-name n)))
-          (cdr node))))
-
-(defun newsticker--group-find-group-for-feed (feed-name)
-  "Find group containing FEED-NAME."
+(defun newsticker--group-do-find-group (feed-or-group-name parent-node node)
+  "Recursively find FEED-OR-GROUP-NAME in PARENT-NODE or NODE."
+  (cond ((stringp node)
+         (when (string= feed-or-group-name node)
+           (throw 'found parent-node)))
+        ((listp node)
+         (cond ((string= feed-or-group-name (car node))
+                (throw 'found parent-node))
+               ((member feed-or-group-name (cdr node))
+                (throw 'found node))
+               (t
+                (mapc (lambda (n)
+                        (if (listp n)
+                            (newsticker--group-do-find-group
+                             feed-or-group-name node n)))
+                      (cdr node)))))))
+
+(defun newsticker--group-find-parent-group (feed-or-group-name)
+  "Find group containing FEED-OR-GROUP-NAME."
   (catch 'found
-    (newsticker--group-do-find-group-for-feed feed-name
-                                              newsticker-groups)
+    (mapc (lambda (n)
+            (newsticker--group-do-find-group feed-or-group-name
+                                             newsticker-groups
+                                             n))
+          newsticker-groups)
     nil))
 
 (defun newsticker--group-do-get-group (name node)
@@ -1659,26 +1670,6 @@ Return t if a new feed was activated, nil otherwise."
           newsticker-groups)
     nil))
 
-(defun newsticker--group-do-get-parent-group (name node parent)
-  "Recursively find parent group for NAME from NODE which is a child of PARENT."
-  (if (string= name (car node))
-      (throw 'found parent)
-    (mapc (lambda (n)
-            (if (listp n)
-                (newsticker--group-do-get-parent-group name n (car node))))
-          (cdr node))))
-
-(defun newsticker--group-get-parent-group (name)
-  "Find parent group for group named NAME."
-  (catch 'found
-    (mapc (lambda (n)
-            (if (listp n)
-                (newsticker--group-do-get-parent-group
-                 name n (car newsticker-groups))))
-          newsticker-groups)
-    nil))
-
-
 (defun newsticker--group-get-subgroups (group &optional recursive)
   "Return list of subgroups for GROUP.
 If RECURSIVE is non-nil recursively get subgroups and return a nested list."
@@ -1714,9 +1705,9 @@ return a nested list."
 (defun newsticker-group-add-group (name parent)
   "Add group NAME to group PARENT."
   (interactive
-   (list (read-string "Group Name: ")
+   (list (read-string "Name of new group: ")
          (let ((completion-ignore-case t))
-           (completing-read "Parent Group: " (newsticker--group-all-groups)
+           (completing-read "Name of parent group (optional): " (newsticker--group-all-groups)
                             nil t))))
   (if (newsticker--group-get-group name)
       (error "Group %s exists already" name))
@@ -1726,46 +1717,154 @@ return a nested list."
     (unless p
       (error "Parent %s does not exist" parent))
     (setcdr p (cons (list name) (cdr p))))
-  (newsticker--treeview-tree-update))
+  (newsticker--treeview-tree-update)
+  (newsticker-treeview-jump newsticker--treeview-current-feed))
+
+(defun newsticker-group-delete-group (name)
+  "Delete group NAME."
+  (interactive
+   (list (let ((completion-ignore-case t))
+           (completing-read "Delete group: "
+                            (newsticker--group-names)
+                            nil t (car (newsticker--group-find-parent-group
+                                        newsticker--treeview-current-feed))))))
+  (let ((parent-group (newsticker--group-find-parent-group name)))
+    (unless parent-group
+      (error "Parent %s does not exist" parent-group))
+    (setcdr parent-group (cl-delete-if (lambda (g)
+                                         (and (listp g)
+                                              (string= name (car g))))
+                                       (cdr parent-group)))
+    (newsticker--group-manage-orphan-feeds)
+    (newsticker--treeview-tree-update)
+    (newsticker-treeview-update)
+    (newsticker-treeview-jump newsticker--treeview-current-feed)))
+
+(defun newsticker--group-do-rename-group (old-name new-name)
+  "Actually rename group OLD-NAME to NEW-NAME."
+  (let ((parent-group (newsticker--group-find-parent-group old-name)))
+    (unless parent-group
+      (error "Parent of %s does not exist" old-name))
+    (mapcar (lambda (elt)
+              (cond ((and (listp elt)
+                          (string= old-name (car elt)))
+                     (cons new-name (cdr elt)))
+                    (t
+                     elt))) parent-group)))
+
+(defun newsticker-group-rename-group (old-name new-name)
+  "Rename group OLD-NAME to NEW-NAME."
+  (interactive
+   (list (let* ((completion-ignore-case t))
+           (completing-read "Rename group: "
+                            (newsticker--group-names)
+                            nil t (car (newsticker--group-find-parent-group
+                                        newsticker--treeview-current-feed))))
+         (read-string "Rename to: ")))
+  (setq newsticker-groups (newsticker--group-do-rename-group old-name new-name))
+  (newsticker--group-manage-orphan-feeds)
+  (newsticker--treeview-tree-update)
+  (newsticker-treeview-update)
+  (newsticker-treeview-jump newsticker--treeview-current-feed))
+
+(defun newsticker--get-group-names (lst)
+  "Do get the group names from LST."
+  (delete nil (cons (car lst)
+                    (apply 'append
+                           (mapcar (lambda (e)
+                                     (cond ((listp e)
+                                            (newsticker--get-group-names e))
+                                           (t
+                                            nil)))
+                                   (cdr lst))))))
+
+(defun newsticker--group-names ()
+  "Get names of all newsticker groups."
+  (newsticker--get-group-names newsticker-groups))
 
 (defun newsticker-group-move-feed (name group-name &optional no-update)
   "Move feed NAME to group GROUP-NAME.
 Update treeview afterwards unless NO-UPDATE is non-nil."
   (interactive
    (let ((completion-ignore-case t))
-     (list (completing-read "Feed Name: "
-                            (mapcar 'car newsticker-url-list)
+     (list (completing-read "Name of feed or group to move: "
+                            (append (mapcar 'car newsticker-url-list)
+                                    (newsticker--group-names))
                             nil t newsticker--treeview-current-feed)
-           (completing-read "Group Name: " (newsticker--group-all-groups)
+           (completing-read "Name of new parent group: " (newsticker--group-names)
                             nil t))))
-  (let ((group (if (and group-name (not (string= group-name "")))
-                   (newsticker--group-get-group group-name)
-                 newsticker-groups)))
+  (let* ((group (if (and group-name (not (string= group-name "")))
+                    (newsticker--group-get-group group-name)
+                  newsticker-groups))
+         (moving-group-p (member name (newsticker--group-names)))
+         (moved-thing (if moving-group-p
+                          (newsticker--group-get-group name)
+                        name)))
     (unless group
       (error "Group %s does not exist" group-name))
     (while (let ((old-group
-                  (newsticker--group-find-group-for-feed name)))
+                  (newsticker--group-find-parent-group name)))
              (when old-group
-               (delete name old-group))
+               (delete moved-thing old-group))
              old-group))
-    (setcdr group (cons name (cdr group)))
+    (setcdr group (cons moved-thing (cdr group)))
     (unless no-update
       (newsticker--treeview-tree-update)
-      (newsticker-treeview-update))))
+      (newsticker-treeview-update)
+      (newsticker-treeview-jump name))))
 
-(defun newsticker-group-delete-group (name)
-  "Remove group NAME."
-  (interactive
-   (let ((completion-ignore-case t))
-     (list (completing-read "Group Name: " (newsticker--group-all-groups)
-                            nil t))))
-  (let* ((g (newsticker--group-get-group name))
-         (p (or (newsticker--group-get-parent-group name)
-                newsticker-groups)))
-    (unless g
-      (error "Group %s does not exist" name))
-    (delete g p))
-  (newsticker--treeview-tree-update))
+(defun newsticker-group-shift-feed-down ()
+  "Shift current feed down in its group."
+  (interactive)
+  (newsticker--group-shift 1))
+
+(defun newsticker-group-shift-feed-up ()
+  "Shift current feed down in its group."
+  (interactive)
+  (newsticker--group-shift -1))
+
+(defun newsticker-group-shift-group-down ()
+  "Shift current group down in its group."
+  (interactive)
+  (newsticker--group-shift 1 t))
+
+(defun newsticker-group-shift-group-up ()
+  "Shift current group down in its group."
+  (interactive)
+  (newsticker--group-shift -1 t))
+
+(defun newsticker--group-shift (delta &optional move-group)
+  "Shift current feed or group within its parent group.
+DELTA is an integer which specifies the direction and the amount
+of the shift.  If MOVE-GROUP is nil the currently selected feed
+`newsticker--treeview-current-feed' is shifted, if it is t then
+the current feed's parent group is shifted.."
+  (let* ((cur-feed newsticker--treeview-current-feed)
+         (thing (if move-group
+                    (newsticker--group-find-parent-group cur-feed)
+                  cur-feed))
+         (parent-group (newsticker--group-find-parent-group
+                        (if move-group (car thing) thing))))
+    (unless parent-group
+      (error "Group not found!"))
+    (let* ((siblings (cdr parent-group))
+           (pos (cl-position thing siblings :test 'equal))
+           (tpos (+ pos delta ))
+           (new-pos (max 0 (min (length siblings) tpos)))
+           (beg (cl-subseq siblings 0 (min pos new-pos)))
+           (end (cl-subseq siblings (+ 1 (max pos new-pos))))
+           (p (elt siblings new-pos)))
+      (when (not (= pos new-pos))
+        (setcdr parent-group
+                (cl-concatenate 'list
+                                beg
+                                (if (> delta 0)
+                                    (list p thing)
+                                  (list thing p))
+                                end))
+        (newsticker--treeview-tree-update)
+        (newsticker-treeview-update)
+        (newsticker-treeview-jump cur-feed)))))
 
 (defun newsticker--count-groups (group)
   "Recursively count number of subgroups of GROUP."
@@ -1812,7 +1911,7 @@ Return t if groups have changed, nil otherwise."
   (let ((new-feed nil)
         (grouped-feeds (newsticker--count-grouped-feeds newsticker-groups)))
     (mapc (lambda (f)
-            (unless (newsticker--group-find-group-for-feed (car f))
+            (unless (newsticker--group-find-parent-group (car f))
               (setq new-feed t)
               (newsticker-group-move-feed (car f) nil t)))
           (append newsticker-url-list-defaults newsticker-url-list))
@@ -1914,6 +2013,12 @@ Return t if groups have changed, nil otherwise."
     ;;(define-key map "\C-m" 'newsticker-treeview-scroll-item)
     (define-key map "\M-m" 'newsticker-group-move-feed)
     (define-key map "\M-a" 'newsticker-group-add-group)
+    (define-key map "\M-d" 'newsticker-group-delete-group)
+    (define-key map "\M-r" 'newsticker-group-rename-group)
+    (define-key map [M-down] 'newsticker-group-shift-feed-down)
+    (define-key map [M-up] 'newsticker-group-shift-feed-up)
+    (define-key map [M-S-down] 'newsticker-group-shift-group-down)
+    (define-key map [M-S-up] 'newsticker-group-shift-group-up)
     map)
   "Mode map for newsticker treeview.")
 
@@ -1972,10 +2077,10 @@ POS gives the position where EVENT occurred."
            (newsticker-treeview-show-item))
           (t
            ;; click in tree buffer
-           (let ((w (newsticker--treeview-get-node nt-id)))
+           (let ((w (newsticker--treeview-get-node-by-id nt-id)))
              (when w
                (newsticker--treeview-tree-update-tag w t t)
-               (setq w (newsticker--treeview-get-node nt-id))
+               (setq w (newsticker--treeview-get-node-by-id nt-id))
                (widget-put w :nt-selected t)
                (widget-apply w :action event)
                (newsticker--treeview-set-current-node w))))))
index bcfde995332b1821327fa8c01eb20ccb0a2afe17..6d64da10a33afe9eaf1e498b93831fa20810f2ec 100644 (file)
@@ -1,3 +1,9 @@
+2014-09-24  Ulf Jasper  <ulf.jasper@web.de>
+
+       * automated/newsticker-tests.el
+       (newsticker--group-find-parent-group),
+       (newsticker--group-do-rename-group): New tests.
+
 2014-09-09  Eli Zaretskii  <eliz@gnu.org>
 
        * automated/fns-tests.el (fns-tests-collate-sort): Bind
index 2dbb850c407de43421b6559bab5a963a8da26f33..5f9ec0492461a801cef964a11b23671d95a6d50c 100644 (file)
@@ -143,6 +143,26 @@ Signals an error if something goes wrong."
     (should (equal '("Feeds" "feed3" "feed2" "feed1")
                    newsticker-groups))))
 
+(ert-deftest newsticker--group-find-parent-group ()
+  "Test `newsticker--group-find-parent-group'."
+  (let ((newsticker-groups '("g1" "f1a" ("g2" "f2" ("g3" "f3a" "f3b")) "f1b")))
+    ;; feeds
+    (should (equal "g1" (car (newsticker--group-find-parent-group "f1a"))))
+    (should (equal "g1" (car (newsticker--group-find-parent-group "f1b"))))
+    (should (equal "g2" (car (newsticker--group-find-parent-group "f2"))))
+    (should (equal "g3" (car (newsticker--group-find-parent-group "f3b"))))
+    ;; groups
+    (should (equal "g1" (car (newsticker--group-find-parent-group "g2"))))
+    (should (equal "g2" (car (newsticker--group-find-parent-group "g3"))))))
+
+(ert-deftest newsticker--group-do-rename-group ()
+  "Test `newsticker--group-do-rename-group'."
+  (let ((newsticker-groups '("g1" "f1a" ("g2" "f2" ("g3" "f3a" "f3b")) "f1b")))
+    (should (equal '("g1" "f1a" ("h2" "f2" ("g3" "f3a" "f3b")) "f1b")
+                   (newsticker--group-do-rename-group "g2" "h2")))
+    ))
+
+
 (provide 'newsticker-tests)
 
 ;;; newsticker-tests.el ends here