[alt.sources] newsorder -- re-order your .newsrc by preference

lee@sq.sq.com (Liam R. E. Quin) (06/10/91)

I've been meaning to post this for ages...  And then last week someone posted
something similar, so here goes!

This awk script (you need the "new" awk or nawk/gawk/mawk) reads a template
file (~/.newsorder), and sorts your .newsrc based on what it sees there.
Here's some of mine, with annottions.  There's a smaller smaple in the
distribution itself.


    # This file is read by newsorder as a template for sorting
    # my .newsrc file.
    sq.*		# I want to see local newsgroups first...
    comp.text.sgml	# then SGML cos that's our business :-) :-)
    comp.text*, !comp.text.tex
			# all the rest of the text groups except the tex one
    *.frp
    *.magick		# now some relaxation...
    *.pagan
    *.rpg
    comp.font*		# more work:
    comp.text.tex
    comp.archives
    *windows*
    *sources* !*.d !*.wanted	# some sources groups
    #new newsgroups:
    /^.*:$/		# this pattern matches new newsgroups, so if
			# rm adds them to my .newsrc, I can run newsorder
			# and they all end up here where I see them.

    # All other newsgroups go here, in the order in which they appear
    # in my .newsrc...


: To unbundle, sh this file  ---- cut here ---- cut here ---- snip! ---- ow!
echo x - Makefile 1>&2
sed 's/^X//' >Makefile <<'@@@End of Makefile'
X# Makefile for newsorder
X# Liam Quin, 1991
X# $Id: Makefile,v 1.6 91/02/07 17:58:40 lee Exp $
X
XBINDIR=/home/lee/scripts
XMAKE=make
XCLEAN=clean
X
XMANDIR=/usr/man/man1
XMANSECTION=1L
Xnewsorder: newsorder.sh
X	cp newsorder.sh newsorder
X	chmod 755 newsorder
X
Xinstall: newsorder
X	-rm -f $(BINDIR)/newsorder
X	cp newsorder $(BINDIR)/newsorder
X	chmod 555 $(BINDIR)/newsorder
X	# -rm -f $(MANDIR)/newsorder.${MANSECTION}
X	# sed -e 's/ 1L / $(MANSECTION) /' newsorder.man \
X	#       > $(MANDIR)/newsorder.$(MANSECTION)
X	$(MAKE) $(CLEAN)
X
Xclean:
X	-rm -f newsorder .newsorder shar core *.o *.out
X	@: delete files that are stored in RCS format and unchanged:
X	-for i in * ; do \
X	    test -f RCS/$$i,v && rcsdiff $$i && rm $$i ; \
X	done
X	@: remind me that there are still files here...
X	-/bin/ls -l
X
Xshar: Makefile newsorder.sh .newsorder
X	-rm -f shar
X	bundle $? > shar
X
XMakefile:: RCS/Makefile,v
X	co -u Makefile
X
Xnewsorder.sh:: RCS/newsorder.sh,v
X	co -u newsorder.sh
X
X.newsorder:: RCS/.newsorder,v
X	co -u .newsorder
@@@End of Makefile
echo x - newsorder.man 1>&2
sed 's/^X//' >newsorder.man <<'@@@End of newsorder.man'
X.\" @(#)$Id: newsorder.man,v 1.5 91/02/07 17:49:03 lee Exp $
X.TH NEWSORDER 1L
X.SH NAME
Xnewsorder \- sort netnews .newsrc files by specified template
X.SH SYNOPSIS
X.B newsorder
X[
X.I inut-file
X] 
X.SH DESCRIPTION
X.I newsorder
Xreads the file
X.I "$HOME/.newsorder"
Xand uses it as a basis to sort your
X.I \&.newsrc
Xfile.
XIf a filename option is given, this is sorted instead of your
X.I .newsrc
Xfile.
XThe filename \- is taken to be standard input.
X.PP
XEach line in the template file names a group or hierarchy of news-groups.
XFor example:
X.sp 0.5
X.RS
X# newsorder file for Liam
X.br
Xsq.*  # SoftQuad local groups first
X.br
X*frp  # anything that ends in frp
X.br
Xcomp.text* !comp.text.scribe # all the comp.text groups except one
X.br
Xcomp.lang*, !comp.lang.postscript, !*.intercal
X.sp 0.5
X.RE
X.LP
XNote that there is a difference between .* and * \- in particular,
X`comp.text.*' would not match the `comp.text' newsgroup.
X.PP
XAny lines in your
X.I \&.newsrc
Xfile that don't match any of the patterns will end up at the end of the new
Xfile, in the order in which they were found.  Hence,
X.I \&newsorder
Xhas the effect of selecting certain groups and moving them to the front,
Xso that the news-readers will present them first.
X.PP
X.I Newsorder
Xwill prompt you asking whether or not to overwrite your
X.I \&.newsrc
Xfile.  The resulting file is left in
X.IR ~/.newsrc-sorted ,
Xand optionally copied onto
X.I ~/.newsrc
Xitself.
XIn any case a copy of your original unsorted
X.I .newsrc
Xis made in
X.IR ~/.newsrc-unsorted .
X.SH AUTHOR
XLiam Quin, after an idea by Bob Gibson.
X.SH BUGS
XCould be more enthusiastic about looking for your
X.I \&.newsrc
Xfile.
X.br
XThe name
X.I newsorder
Xis probably a little long for System V users.
X.
X.\" $Log:	newsorder.man,v $
X.\" Revision 1.5  91/02/07  17:49:03  lee
X.\" Fixed documentation of argument.
X.\" 
X.\" Revision 1.4  91/02/07  17:26:35  lee
X.\" Put all filenames into italic, and changed the section from V to L.
X.\" 
X.\" Revision 1.3  91/02/07  17:12:44  lee
X.\" Documented filename - as stdin and the backup of the .newsrc file.
X.\" 
X.\" Revision 1.2  91/01/31  20:47:15  lee
X.\" fixed a typo in the BUGS section!
X.\" 
X.\" Revision 1.1  91/01/31  20:45:47  lee
X.\" Initial revision
X.\" 
X.\" 
@@@End of newsorder.man
echo x - newsorder.sh 1>&2
sed 's/^X//' >newsorder.sh <<'@@@End of newsorder.sh'
X#! /bin/sh
X# $Id: newsorder.sh,v 1.7 91/04/23 15:43:27 lee Exp $
X# Liam Quin, 1991
X
X# newssort -- sort .newsrc ino order based on template
X
XTemplateFile="$HOME/.newsorder"
X
X# determine echo variant for prompts...
XN=-n; C=''; if test `echo 'hello\c'` = 'hello'; then N=''; C='\c'; fi
Xexport N C
X
XCMDNAME=${CMDNAME-"`basename $0`"}
Xexport CMDNAME
X
Xif test x"$1" = x""
Xthen
X    InputFile="$HOME/.newsrc"
Xelif test -f "$1"
Xthen
X    InputFile="$1"
Xelif test x"$1" = x"-"
Xthen
X    InputFile="-"
Xelse
X    echo "Usage: `basename $0` [input-file (default is $HOME/.newsrc)]" 1>&2
X    exit 1
Xfi
X
Xcat "$InputFile" > $HOME/.newsrc-unsorted
X
Xcat "$InputFile" |
Xnawk '
X
XBEGIN {
X    # FORMAT is how the lines are printed.   The first number is the weighting
X    # for sorting -- lower numbers go higher up in .newsrc -- the 2nd is the
X    # input line number, so that the sort is stable.
X    FORMAT = "%d %d %s\n"
X
X    # read the template file
X    while (getline < "'"$TemplateFile"'") {
X	gsub(/[ 	]*#.*$/, "") # delete comments
X	if ($0 ~ /^[ 	]*$/) {
X	    # ignore blank lines
X	    continue
X	}
X	if ($0 ~ /^\/.*\//) {
X	    Line = $0
X	    sub(/^\//, "")
X	    sub(/\/[^\/]*$/, "")
X	    Patterns[++PatCount] = $0
X	    MatchField[PatCount] = 0 # match on the entire line
X	    $0 = Line
X	    sub(/^\/.*\//, "") # to allow (literal) inclusions and exclusions
X	} else {
X	    gsub(/,/, " ") # turn , into space
X	    gsub(/[.]/, "\\.")
X	    gsub(/[*]/, ".*")
X	    Patterns[++PatCount] = "^" $1 "[:!]*$"
X	    MatchField[PatCount] = 1 # match on the newsgroup name only
X	}
X	# Uncommment the next 2 lines to see the patterns...
X	printf "PatCount %d Pattern /%s/\n",
X		PatCount, Patterns[PatCount] > "/dev/tty"
X
X	# deal with exclusions:
X
X	for (i = 2; i <= NF; i++) {
X	    if ($i ~ /^!/) {
X		sub(/[!]/, "", $i)
X		j = ++HasExclusions[PatCount]
X		Exclusions[PatCount,j] = "^" $i "[:!]*$"
X	    } else {
X		printf "'"${CMDNAME}"': '"${TemplateFile}"': %d: %s",PatCount,
X			"Exclusion patterns mst start with a !\n" | "cat 1>&2"
X		exit 1
X	    }
X	}
X    }
X}
X
X# Now go through .newsrc and assign a priority to each line
X
X/^[ 	]*$/ { next }
X/^[oO]ptions:/ { printf FORMAT, 0, NR, $0; next }
X
X{
X    # Pattern 0 is used for the Options: line which must come first,
X    # so we loop from 1 to PatCount...
X    for (i = 1; i <= PatCount; i++) {
X	if ($(MatchField[i]) ~ Patterns[i]) {
X	    Wanted = 1
X	    if (i in HasExclusions) {
X		# see if it matches any of the exclusion patterns:
X		for (j = 1; j <= HasExclusions[i]; j++) {
X		    if ($1 ~ Exclusions[i,j]) {
X			# Aha!  Not wanted here...
X			Wanted = 0
X			break
X		    }
X		}
X	    }
X	    if (Wanted) {
X		printf FORMAT, i, NR, $0
X		if (!(i in Matched)) {
X		    PatUsedCount++ # Used a pattern for the first time
X		}
X		Matched[i]++
X		next
X	    }
X	}
X    }
X    printf FORMAT, i, NR, $0
X    next
X}
X
XEND {
X    # display information about which patterns worked:
X    printf "'"${CMDNAME}"': Used %d out of %d patterns from template \"%s\"\n",
X		    PatUsedCount, PatCount, "'"${TemplateFile}"'" | "cat 1>&2"
X    for (i = 1; i <= PatCount; i++) {
X	if (!(i in Matched)) {
X	    printf "'"$0"': Unused: %d: /%s/\n",
X		    i, Patterns[i] | "cat 1>&2"
X	}
X    }
X}
X' |sort +0n +1n |sed -e 's/^[0-9][0-9]* [0-9][0-9]* //' > $HOME/.newsrc-sorted
X
Xwait # in case the cat hasn't finished from within awk
X
Xecho $N "Overwrite $HOME/.newsrc with sorted version? $C" 1>&2
Xread ans
X
Xcase "$ans" in
X[yY]*)	cp $HOME/.newsrc-sorted $HOME/.newsrc || exit 1 ;;
X*)	echo "Sorted output left in $HOME/.newsrc-sorted" 1>&2 ;;
Xesac
X
Xexit $?
X
X#
X# $Log:	newsorder.sh,v $
X# Revision 1.7  91/04/23  15:43:27  lee
X# Now recognises a pattern like /.../ in the 1st field as an expression to
X# match over the entire input line, so you can use /:$/ to match new
X# newsgroups.
X# 
X# Revision 1.6  91/02/07  17:09:55  lee
X# Improved the arguments to sort after Bob Gibson (rgj@sq.com) found a bug
X# 
X# Revision 1.5  91/01/31  20:44:35  lee
X# Improved error-checking and replaced "cp -i" with an explicit test.
X# 
X# Revision 1.4  91/01/30  19:28:01  lee
X# Improved error message slightly.
X# 
X# Revision 1.3  91/01/30  19:25:47  lee
X# Added exclusion patterns, so you can do
X# comp.text*, !comp.text.tex
X# if you like.
X# 
X# Comments (introduced with a #) and blank lines are now ignored.
X# 
X# Revision 1.2  91/01/30  16:49:38  lee
X# Added summary statistics.
X# 
X# Revision 1.1  91/01/29  23:10:45  lee
X# Initial revision
X# 
X#
@@@End of newsorder.sh
echo End of archive
exit 0
-- 
Liam Quin, lee@sq.com, SoftQuad, Toronto, +1 416 963 8337
the barefoot programmer