[news.software.b] review of news programs/readers?

moraes@cs.toronto.edu (Mark Moraes) (03/14/90)

About your questions on nn:

As far as I know, nn is the only newsreader that needs a database.
(Threaded rn does too, I think) As a result, installation needs some
intervention from someone with root/news privileges.

As for size, the database isn't small:  It's 3275K for 35253K of news
spool.  I think the resulting speed worthwhile, especially since it is
amortised over all nn users on our systems.

The policy on unread articles is simple:  nn will show you the
articles that you select in the newsgroup menu -- those that you do
not select are implicitly rejected, and thus marked as read.  (The joy
of skipping newsgroups by hitting the space bar:-) Those that you
select and read are marked read, of course.  Good for people that make
one pass through news, and want to read very selectively.  I believe
6.4beta allows you to mark articles as unread for future reference.

[I've included ftp locations for gnus and gnews at the end of this note.
 Note that you need GNU Emacs to use them]

On Gnews and gnus:

leo@aai.uu.net (Leo Pinard) writes:
>I already use emacs a lot.  You mention powerful select and kill - is the user
>interface very similar or different than nn?  Could you say any more about the
>difference between gnews and gnus.  Are they different peoples version of the
>same functionality?  Or are they intended for different purposes?

I've included a description of nn and gnus kill-files below from a
local note on kill files.  Someone that actually uses Gnews/gnus and
likes them should comment.  (It is possible that no gnus/Gnews users
follow n.s.b, but I doubt it:-) Here's some more info on them, with
the disclaimer that I've only used them briefly and not read the large
manuals that each comes with.

gnus has an interface similar to Emacs mh mode -- a small window at the
top showing the author/subject of each message, and as you flip through
those, the article text is shown in the large window below it.  To
select between newsgroups, you have a list of newsgroups, which you
can move through with 'n' and 'p', and select one of them to read.
xrn's interface is similar.  (xrn is an X news reader, it uses NNTP)
You can browse through the small window of headers, and select articles
from there.

Gnews is more rn-like -- it prompts you in the minibuf for each
newsgroup, and when in a newsgroup, shows you the articles in the
editing window, and the minibuf contains an rn-like prompt.  You can
hit '=' to get a list of all articles, like rn.  The difference is that
you can keep that window around for future reference, sort it, select
from it.

I found gnus much easier to install - The installation directions are
more precise, there are fewer files to deal with.  It would be nice if
both were shipped with lisp files that could be invoked by emacs in
batch so us non-Emacs-dwellers could compiled them without having to
type lotsa commands at Emacs.  Maybe even a shell script or, (gasp!) a
Makefile.  (Something like emacs -batch -l compile.el -f compile-gnews
would be real handy -- then you wouldn't have to remember all the
instructions, the sequence one has to compile them in, etc)

On kill files:

 nn
 --

nn, unlike rn, will not show you an article unless you select it
first. It presents articles in a menu, much like the '=' command in
rn, and will allow you to select the ones you want, then shows you
those articles only. This makes "kill files" less necessary, since you
can avoid selecting articles by a specific person or on a specific
subject.

"kill files" in nn can be used for both automatic selection of
articles, and automatic avoidance. To do either of these, press K
(shift K) at any time. nn will prompt you about whether you wish to:

	Select or Kill?

	by Subject or Name?

	the string to use (if you type an ordinary string, it will be
	used directly (but case-insensitively), if you start the
	string with /, it will be treated as a regular expression) If
	you hit return, it will use the exact subject or person from
	the article you're presently reading. Regular expressions in nn
	are similar to those in the egrep command. See the manual page
	for egrep.

	This newsgroup or All newsgroups

	How long you want this kill to last (number of days or P for permanent)

nn does not kill on contents of the article, only on the From and
Subject headers.

To edit the nn kill file, start your editor on $HOME/.nn/kill (for
Unix systems -- I haven't a clue where it is on other systems)

The nn manual page has an excellent section on kill files and the
meaning of each question nn asks, in case it isn't obvious from the
prompt.

 GNUS
 ----

GNUS is a newsreader written in Emacs Lisp - it runs under GNU Emacs.
Obviously, you need to know Emacs to use it, so these instructions
assume a knowledge of Emacs.

M-k will edit the kill file of the current news group (C-c C-c ends).
This is the normal way of doing it (it won't take effect until the
NEXT time you enter the newsgroup).

You can add lines of the form

(gnus-kill "Subject" "foo")

to mark subjects with the string "foo" in them. In place of "foo", you
can have arbitrary Emacs regular expressions, like

(gnus-kill "Subject" "foo\\|bar")

These regular expressions are case-insensitive.

To avoid articles by a specific person, say personX,

(gnus-kill "From" "personX")

Finally, add the line

(gnus-Subject-delete-marked-with "X")

to actually delete all the marked articles. (gnus-kill only marks the
articles with X, it doesn't kill them)

gnus-kill only works on a subset of headers, including From and
Subject.

 ---

My thanks to Brian Glendenning <brian@radio.astro.toronto.edu> for
explaining how GNUS kill files worked.

 Some archive sites for newsreaders
 ----------------------------------

[Internet sites can access through anonymous ftp; Others will have to
 uucp from uunet or from osu-cis, which also has most of these in its
 archives someplace. The format is hostname:pathname -- if pathname
 ends in a /, it's a directory containing the relevant files. Remember
 to set binary mode when ftp'ing, and remember to ftp outside working
 hours.  People without nameservers will have to find out the
 addresses from somewhere -- don't ask me.]

lib.tmc.edu:public/rn/
uunet.uu.net:news/rn/

umn-cs.cs.umn.edu:pub/news/nn6.4beta.tar.Z,
dkuug.dk:pub/nn6.4beta.tar.Z, and
sol.cs.ruu.nl:pub/UNIX/nn6.4beta.tar.Z
terminator.cc.umich.edu:unix/nn/nn-6.3.7.tar
terminator.cc.umich.edu:unix/nn/nn-patch10
terminator.cc.umich.edu:unix/nn/nn-patch8
terminator.cc.umich.edu:unix/nn/nn-patch9
freja.diku.dk:misc/nn-* (most recent patches, but it's in Denmark)
uunet.uu.net:comp.sources.unix/volume19/nn/

[I believe gnus-3.12 is the most recent, on tut.cis.ohio-state.edu]
tut.cis.ohio-state.edu:pub/gnu/gnus
ucbvax.berkeley.edu:pub/news/nntp/clients/gnu-emacs/gnus-3.11-tar.Z
uunet.uu.net:gnu/gnus/
radio.astro.toronto.edu:news/gnus-3.11.tar.Z

tut.cis.ohio-state.edu:pub/gnu/gnews/gnews-2.0-tar.Z
ucbvax.berkeley.edu:pub/GNU/gnews-2.0-tar.Z
ucbvax.berkeley.edu:pub/news/nntp/clients/gnu-emacs/gnews-2.0-tar.Z
uunet.uu.net:gnu/gnews-2.0-tar.Z
radio.astro.toronto.edu:news/gnews-2.0-tar.Z

ebersman@software.org (Paul Ebersman) (03/14/90)

> 
> >As far as I know, nn is the only newsreader that needs a database.
> >(Threaded rn does too, I think) As a result, installation needs some
> >intervention from someone with root/news privileges.
> 

Not true. You simply have the nn programs running as setgid to the
group of the database. I have nn installed for myself, since the local
admins didn't want to install it, and I have it running with no setuid
or setgid priveleges with no problem.

 
-- 
                       Paul A. Ebersman @ U U N E T
                   uunet!ebersman or ebersman@uunet.uu.net
     ( The difference between practice and theory in practice is always
      greater than the difference between practice and theory in theory. )

boutilie@cell.mot.COM (Eric Boutilier) (03/14/90)

leo@aai.uu.net (Leo Pinard) writes:

>I had just downloaded 6.4beta and am just starting to play with it.  I need to
>print out and study the docs.  It's not as intuitive as rn...

Rn intuitive?! You've got to be kidding!

Eric Boutilier

UUCP: uunet!motcid!boutiliere
Internet: motcid!boutilie@uunet.uu.net

dsill@ophiuchi.nswc.navy.mil (Dave Sill) (03/15/90)

In article <1990Mar13.084110.1299@aai.uu.net>, leo@aai.uu.net (Leo
Pinard) writes:
> 
> What other news programs and readers should be added to the current list?
> What's your favorite and why?

Xrn is my favorite.  Unfortunately, it's not for everyone: you have
have X Windows and nntp.

I'm a big Emacs fan, but I found Gnews to be too slow for my liking.
If I *really* wanted an Emacs-based news reader, I'd look into GNUS.
I found xrn first, and stopped looking.

Xrn has three modes: one for subscribing/unsubscribing to groups, one
for selecting the newsgroup to read, and one for selecting and reading
articles.  The latter two divide the window into three areas: a
generally small (10 lines) scrollable list of newsgroups or article
headers, a button panel, and a large scrollable text area for
displaying article contents.

Typically, one clicks on a newsgroup with unread articles from
newsgroup selection mode to enter article mode.  Xrn uses the XHDR
nntp command to extract article header information efficiently--
without retrieving the entire article--and displays the headers in a
list at the top of the window.  The first article in the list is
automatically displayed in the area at the bottom of the screen.
Using buttons on the button panel, one can mark articles, read
articles, post, perform subject searches, scroll around the displayed
article, perform various kills, etc.

The article summaries at the top can be presorted into alphabetical
order, which makes it very easy to follow or skip threads.  Clicking
on a summary line causes the article to be displayed.

A small button-panel at the bottom of the window allows one to save
articles to a file (a pop-up window lets you enter the filename,
defaults to the previous filename, and lets you edit the name with
emacs-like commands), reply, forward, followup, cancel, rot-13, print,
and toggle the displayed header information.  (Xrn lets you configure
which header lines are displayed automatically.  I like getting only
the From, Subject, Summary, and Keywords lines.  Toggle-header lets me
see the others when I need to, like when I'm trying to detect a
forgery. :-)

Selecting one of Reply, Forward, or Followup invokes the editor of
your choice--or xrn's built-in emacs-like editor--filling in the
appropriate header, signature, and "> " quoted article contents.

Xrn is available via ftp.  From the README:

% ftp shambhala.berkeley.edu (128.32.132.54)
user: anonymous
password: guest
ftp> cd pub
ftp> binary
ftp> get xrn6-8.tar.Z
ftp> quit
% uncompress xrn6-8.tar.Z
% tar xf xrn6-8.tar

----
Dave Sill (dsill@relay.nswc.navy.mil)

"Americans buy (and throw away) 500 million disposable lighters every
year."

brad@looking.on.ca (Brad Templeton) (03/15/90)

Newsclip is not a reader, but an adjunct to one.  Eric Raymond and I designed
a protocol so that this could be a general class of programs, known as filters
or kill programs.

Effectively a reader starts up, and opens a pipe/stream/socket to the filter
program, which also starts.  The reader goes through and prepares to show
articles to the user, but it asks the filter program on each one to see if it
should go through.  This is how I read news, and it's actually quite efficient
on a server and not too bad on a client.  (On a client, usually you can filter
on just the header and it's not too bad, but if you have to filter on strings
in the body, you need to get the whole article before presenting it.)

I have added one command to RN to send commands to the filter program.
This way simple macros say things like "kill all threads started by this
user" or "I want to see more about this subject" to the filter program.

Since they work in parallel, it makes sense at some point to design a reader
that is presenting articles to be queried in the background while you're
reading.

Newsclip also can filter a .newsrc, but that's not a newsreading tool.
Here's the info on how it works.  You can find it in the file
~ftp/ClariNet/nc.tar.Z on uunet.  There's a small fee if you want to use it
on a regular basis.

-----
With NewsClip, you can control what is shown to you as finely as 
you desire, with all the tools of a powerful programming language 
at your disposal.  The programs you write are compiled, so they 
filter you news for you quickly -- often without any noticeable 
delay.

Your NewsClip programs accept, reject or *weight* articles based 
on C-like expressions you write to describe what you want or don't 
want to see.  You might reject all articles in "rec.humor" that 
are cross-posted to "talk.bizarre", unless they are posted by a 
user at your own site with:

	reject if is rec.humor && is talk.bizarre &&
			domain(from) != my_domain;


Your compiled programs can work in several ways.  With a few
small alterations to your newsreader (patches are provided
for the RN reader), your program will filter news as you read
it, usually with no delay.  You simply see the articles you
wish to see.  The modified RN reader can also send commands
to the filter program to interactively control filtering.

You can also arrange to filter news in the background, or at
night.  Your filter program will read your news subscription
file, scan all unread articles, and pre-mark undesired
articles as read, so that you never see them.  This works
with any system that uses a .newsrc file.

NewsClip programs can also filter a list of article filenames, 
such as a list of articles to be fed to another system.  This 
way you can fine tune the feeding of articles to other systems 
as precisely as you desire.  You can also arrange to feed other 
sites by creating a newsrc for the destination site, so that 
you don't need the "sys" file.

An important thing to remember is that with NewsClip, you are
not limited to describing what you don't want to see, as is
the case with RN KILL files.  You can also request what you
want to see, and eliminate all the rest.  Or you can combine
the two, or vary the rules from group to group or message to
message.

Here are some of the things you can do:

  o   Eliminate or request followup trees.  You can kill off
      or follow a topic or subtopic based on the subject or
      the "Message-id:"  and "References:"  lines.

  o   Control crossposting.  You can request to only see
      articles crossposted to multiple groups, or reject or
      accept articles based on what groups they are
      crossposted to.  You can even reject any article
      crossposted to too many groups.

  o   Eliminate a user, group of users or even a site.  You
      can arrange not only to not see the postings of certain
      users, but to not even see the followups to those
      postings.  You can thus eliminate unwanted users or
      classes of postings from *your* net -- you'll never
      even know they're there.

  o   Keyword match articles based on the presence of patterns 
      in header items or various sections of the article text.  
      You can ask to see articles that mention "unix" but don't 
      mention "ms-dos."

  o   Accept your own articles and give priority to followups
      to your own articles.

  o   Accept articles posted only to a local distribution,
      even if they're in a netwide group.  As shown above,
      you can arrange to accept articles from people on your
      own site, even if you might not normally see them.

  o   Reject articles with signatures that are too long, or
      which contain too much included text.

  o   Accept only original (non-followup) articles and
      followups to those articles that you have explicitly
      decided to track.  (It's like having a USENET 1/10th
      the volume of the current one.)

Anything that a computer program can figure out about an article can be 
used to decide whether you will see the article or not.  

			How NewsClip Works

The NewsClip compiler translates your filter program into a C program.
This C program is compiled by your local C compiler and linked with the
NewsClip library.   That library processes articles and handles the
interface to news readers and the real world.

The goal of your program is to decide whether to accept or reject an
article.  This can be done piece by piece (reject if *this*, accept if
*that*) or it can be done by giving a score to the article based on
conditional expressions.   You can add points to articles with things you
like, and take them away from articles with things you don't like.  At the
end, if the score is still positive, you see the article.

	if( lines > 200 )
		adjust 200-lines;

The language is C-like, but has data types that represent the kind of
things found in articles and article headers.   Perhaps most important is
the  "database" type, which is really an integer array that you can index
with string values.   You use databases to keep track of users, message-ids, 
patterns, subjects and other key items you might look for in articles.

Your NewsClip program can update databases on its own.  If an article
comes in that you really hate, you can automatically put its message-id
in a database that marks messages you don't want to see followups of.
To you, it's as if the message was never posted.

	if( from in badusers ) {
    		badmessages[message_id] = true;
    		reject;
    		}

Databases can be stored on disk, and a special feature allows you to
"expire" database records that have not been accessed in a while.

Your filter program can run in parallel with a newsreader like RN.  We
have developed a general protocol that any newsreader can use to talk to
a filter program.  This includes the ability to send commands to the
filter program, such as "kill all articles with this subject."

To examine an article, you mainly work with the header.  There are predefined
external variables for all the major headers, or you can custom-declare your
own:

	header string array keys : "keywords", ",";

(This gets you an array variable called "keys" whose elements will be
the comma-delimited keywords from the "Keywords:" header line.)

You can define your own procedures and functions in the NewsClip language,
or even import C functions from the C libraries or your own C programs.

	extern int strlen( string );

NewsClip contains a special *distribution* feature that lets you check
the distribution of an article and estimate how many machines it will go
to.  You can thus accept or reject articles based on their audience, as well
as their newsgroup.

You can split up articles into various regions when doing pattern matching
in the body.  The signature, main text, non-included text and whole body are
all regions that you can examine independently.

reject if line_count(signature) > 20
	|| newtext has "ron.*reagan";


		Sample Program

/* Sample NEWSCLIP program that shows what you can do */
/* This program is far more complex than a typical system, which
   would usually be quite short. */

/* Please folks, this is not the newsclip program that I use, and I
   don't advocate all the different filtering things here.  I am
   just using them as examples of how to do certain things net people
   have suggested they wanted done. */

	/* You can include pre-defined header lines */
	extern userid From;			/* the From: line */
	extern newsgroup array newsgroups;	/* the Newsgroups: line */
	extern int distribution_level;		/* max distr of article */
	extern string array references;		/* parent articles */
	extern string Subject;			/* subject line */
	extern int followup;			/* is it a followup? */
	extern int lines;			/* header variable */
	/* or define your own header lines */
	header string mess_id : "message-id";
	/* declare variables */
	int counter;
	/* some databases I will look things up in */
	database badmessages;			/* message-ids I don't want
						to see followsup to */
	database hated_users;			/* users I don't want to
						   see articles from */
	database my_articles;			/* message-ids that I
						want to see ALL followups to */
	/* declare external C functions from the Newsclip library or your
	   own C libraries */
	extern int strlen( string );

	/* you can define procedures and functions */

int
nice_group( newsgroup n )
{
	extern string left( string, int );
	/* you like all sci newsgroups and rec.humor.funny */
	return n == #rec.humor.funny || left(n,1) == "sci";
}

procedure
INIT() {
	extern procedure set_include_prefix(string);
	/* this code gets run when the program starts */
	set_include_prefix( "[:>]" );
	hated_users = read_database( "~./hatedusers" );
	my_articles = read_database( "~./myarticles" );
}

procedure
STARTGROUP() {
	/* This gets called when we begin to scan a new newsgroup */
	/* read in the database of bad message-ids for this group */
	badmessages = read_database( "~./kill/~n/killdb" );
}

procedure
ENDGROUP() {
	/* this gets called to end the newsgroup */
	extern datetime time_now;

	/* write out the bad message database, delete all entries that
	  are older than one month */
	write_database( badmessages, "~./kill/~n/killdb", time_now - month );
	free_database( badmessages );
}

	/* here is the main part.  The code that is executed for every
	   article to accept or reject it */

procedure
ARTICLE() {
	newsgroup n;
	extern string domain( string );
	extern string right( string, int );
	extern int dlevel( newsgroup );
	extern string my_domain;
	extern string my_mail_address;

	/* show me everything written by people at my own site */
	if( domain(From) == my_domain ) {
		/* Note my own articles in a database of good ones */
		if( From == my_mail_address )
			my_articles[mess_id] = true;
		accept;
		}
	 else if( domain(From) == "hated.domain.com" )
		reject;		/* never show me anything from THAT site */
	/* also show me anything posted only for citywide distribution */
	accept if distribution_level <= dlevel(#city);

	reject if count(newsgroups) > 6;	/* I hate crossposting */

	/* See if it's a followup to one of MY messages */
	accept if References in my_articles;

	/* See if any of the messages this is a followup of are in
	   our database of bad messages.  If so, reject it */
	reject if References in badmessages;

	/* and of course, kill the bad guys */
	reject if From in hated_users;

	/* Now do the newsgroup specific code */
	for( n in newsgroups ) switch( n ) {
		case #rec.humor:
			/* adjust the score of messages that are crossposted
				to groups you don't like */
			if( is talk.bizarre || is alt.flame )
				adjust -10;
			/* but I like local humour */
			accept if distribution_level <= dlevel(#country);
			break;

		case #news.groups:
			/* If you really don't like a user in a group,
			   arrange to store the message id of every
			   message he posts in your bad message database.
			   You won't even see the followups, and it
			   will be as though he didn't exist on the net. */
			if( From == "karl@ddsw1.mcs.com" ) {
				badmessages[mess_id] = true;
				reject;
				}
			break;
		case #sci.physics:
			/* I only want to see messages that are crossposted
			   to both sci.physics AND sci.astro, not just one
			   of them */
			reject if !is sci.astro;
			break;
		case #rec.arts.comics:
			/* I only want articles that mention watchmen in
				the subject */
			if( subject has "watchmen" )
				accept;
			 else
				reject;
		case #news.admin:
			/* bump the score of any article that mentions
			   my name */
			if( text has "brad.*templeton" || subject has "brad" )
				adjust 1000;
			break;
		case #talk.politics.misc:
			/* I hate long rebuttals.  If the article is mostly
			   lines that are included from another, then can it */
			if( followup && lines / (1+line_count(included)) < 2 )
				reject;
			/* I hate long signatures on short articles! */
			if( lines < 25 && line_count(signature) > 7 )
				reject;
			break;
		case #talk.politics.theory:
			/* search for libertarian only in non-included text */
			if( newtext has "libertarian" || newtext has "ncp" )
				accept;
			 else
				reject;
		case #comp.risks:
		case #rec.arts.sf-lovers:
			/* my favourite groups */
			adjust 20;
			break;
		default:
			if( nice_group(n) )
				adjust 15;
			break;

		}
	if( is alt.flame )
		adjust -5;		/* I would rather not see these */
	/* default is a score of 1, which means accept */
	/* here at the end, we accept if the score is greater than 0, or
	   if there was an explicit accept, of course */

}

procedure
TERMINATE() {
	extern datetime time_now;
	/* The program is done.  Write out global databases */
	write_database( my_articles, "~./my_articles", time_now - 3 * week );
}

-- 
Brad Templeton, ClariNet Communications Corp. -- Waterloo, Ontario 519/884-7473