code: plan9front

ref: 2eadf1fa1703e5da4a98ba9c1a2bdc23bd140d8c
dir: /rc/bin/newt/

View raw version
#!/bin/rc
# NEWT, their six-year-old daughter, yells from the back...
# use with nntpfs
rfork en
ramfs
argv0=$0
if(~ $#editor 0)
	editor=hold
if(~ $#pager 0)
	pager=cat
group=alt/test
maxposts=30
mnt=/mnt/news
if(~ $#newtname 0)
	newtname=newt@dont-email.me
fn e{
	{
		echo From: $"newtname
		echo Newsgroups: `{echo $group | sed 's/\//\./g'}
		echo Subject: $"subject
		echo
	} >/tmp/post
	eval $editor /tmp/post
	yn send
	if(~ $yn y)
		cat /tmp/post >$mnt/$group/post
}
fn fmtd{
	date=`{cat}
	if(! ~ $date(1) [0-9]*)
		date=`{nshift $date}
	da=$date(1)
	if(~ $da [0-9])
		da=0^$da
	switch($date(2)){
	case Jan;	mo=1
	case Feb;	mo=2
	case Mar;	mo=3
	case Apr;	mo=4
	case May;	mo=5
	case Jun;	mo=6
	case Jul;	mo=7
	case Aug;	mo=8
	case Sep;	mo=9
	case Oct;	mo=10
	case Nov;	mo=11
	case Dec;	mo=12
	}
	if(! ~ $date(3) `{date | awk '{print $6;}'})
		ti=$date(3)
	if not
		ti=`{echo $date(4) | awk '{print substr($0,0,5);}'}
	if(! ~ $#mo 0 && ! ~ $#da 0 && ! ~ $#ti 0)
		echo $mo/$da $ti
	if not
		echo nil
}
fn geth{
	for(i in $*){
		from=`{awk -F '	' '{print $3;}' $rposts($i)^/xover >[2]/dev/null}
		if(! ~ $#from 0 && ! ~ $#from 1){
			nfrom=`{
				for(i in $from){
					if(~ $i *@*)
						echo $i | sed 's/(<|>)//g'
				}
			}
			if(! ~ $#nfrom 0)
				from=$nfrom
		}
		if(~ $#from 0)
			from=nil
		date=`{awk -F '	' '{print $4;}' $rposts($i)^/xover >[2]/dev/null | fmtd}
		if(~ $#date 0)
			date=nil
		subject=`{awk -F '	' '{print substr($2,0,50);}' $rposts($i)^/xover >[2]/dev/null}
		if(~ $#subject 0)
			subject=nil
		# unicode 00a0 divides message number from headline.
		# command input ignores everything after unicode 00a0.
		# these lines may be selected and sent to the prompt.
		echo '  '$"i' '$"date' '$"from'		'$"subject
	}
}
fn getposts{ ls | grep -e '^[0-9]+$' | sort -n | tail -$maxposts }
fn getr{
	switch($*){
	case ,;	echo $posts
	case ,*;	seq 1 `{echo $* | sed 's/,//g'}
	case *,;	seq `{echo $* | sed 's/,//g'} $posts($#posts)
	case *,*;	seq `{echo $* | sed 's/,/ /g'}
	case *;	echo $*
	}
}
fn h{ sed -n $1^p /tmp/h }
fn k{
	kmnt=`{echo $mnt | sed 's/\//\\\//g'}
	walk $mnt/$* |
		grep -v -e '\/([0-9]+|article|body|header|post|xover)$' |
		sed 's/^'$"kmnt'\//  g	/g' |
		sort |
		eval $pager
}
fn nshift{ shift; echo $* }
fn printhelp{
echo 'Commands are of the form [<range>] <command> [args]
<range> := <addr> | <addr>','<addr>
<command> :=
b		print the next ten headers
e		enter message
g ...		go to specified group
h		print message headline (,h for all)
help		print this help message
k ...		list sub-groups under specified group
kf ...		grep $home/lib/newsgroups for regexp
p		print message with minimal headers
P		print message with full headers
q		quit
r		reply to message
y		synchronize message list with server
"		print message in quoted form, suitable for reply
|cmd		pipe message body to a command
||cmd		pipe raw message to a command
!cmd		run a command
?		print debug information'
}
fn np{
	if(test $1 -le $#rposts && test -f $mnt/$group/$rposts($1)^/body){
		{ # don't stutter
			grep -e '(^From|^Newsgroups|^Subject|^Date)' $rposts($1)^/header
			echo
			cat $rposts($1)^/body
		} >/tmp/p
		eval $pager /tmp/p
	}
	echo
	go=1
	r=$1
	post=$1
	prompt=$group/$1
}
fn P{
	if(test $1 -le $#rposts && test -f $mnt/$group/$rposts($1)^/article)
		eval $pager $rposts($1)^/article
	echo
	go=1
	r=$1
	post=$1
	prompt=$group/$1
}
fn r{
	if(test $1 -le $#rposts && test -f $mnt/$group/$rposts($1)^/header){
		subject=`{grep -e '^Subject: ' $mnt/$group/$rposts($1)^/header | sed 's/^Subject: //g'}
		if(! ~ $subject RE:* Re:* re:*)
			subject=(Re: $subject)
		e
	}
	if not
		echo !message missing
}
fn y{
	go=()
	r=$post
	if(! ~ $q 1){
		rposts=`{getposts}
		posts=`{seq 1 $#rposts}
		post=$posts(1)
		prompt=$post
		geth $posts >/tmp/h
		echo $#posts messages
	}
}
fn yn{
	echo
	echo -n $* ' (y, n) '
	yn=`{read}
	switch($yn){
	case y n
		;
	case *
		yn
	}
}
fn '"' {{p $1 | sed 1d | sed 's/^/> /g' | sed 's/^> >/>>/g' | sed '$d'; echo}}
fn usage{
	echo usage: $argv0 '[ -f newsgroup ] [ -m mountpoint ] [ -p maxposts ]' >[1=2]
	exit usage
}
while(~ $1 -*){
	switch($1){
	case -f
		group=`{echo $2 | sed 's/\./\//g'}
		shift
	case -m
		mnt=$2
		shift
	case -p
		maxposts=$2
		shift
	case *
		usage
	}
	shift
}
if(! ~ $#* 0)
	usage
prompt=$group
if(! test -d $mnt/$group){
	echo !$mnt/$group does not exist >[1=2]
	exit
}
builtin cd $mnt/$group
y
while(){
	echo -n $"prompt': '
	# command input ignores everything after unicode 00a0.
	rcmd=`{read | sed 's/[ ].*$//g' | sed 's/^([0-9]+)?(,)?([0-9]+)?/& /g'}
	switch($rcmd){
	case ,* [0-9]*
		r=`{getr $rcmd(1)}
		cmd=`{nshift $rcmd}
		if(~ $#cmd 0)
			cmd=p
	case *
		r=$post
		cmd=$rcmd
	}
	switch($cmd){
	case b
		r=`{seq $r(1) `{echo $r(1)^+10|bc}}
		if(test $r($#r) -gt $posts($#posts))
			r=`{seq $r(1) $posts($#posts)}
		if(! ~ $#r 0 && test $r(1) -le $posts($#posts)){
			sed -n $r(1)^,$r($#r)^p /tmp/h
			post=$r($#r)
			prompt=$post
		}
		if not
			echo !address
	case e
		subject=() e
	case g' '*
		ngroup=`{nshift $cmd | sed 's/\./\//g'}
		if(test -d $mnt/$ngroup){
			if(grep -s -e '^[0-9]+$' <{ls -p $mnt/$ngroup}){
				group=$ngroup
				builtin cd $mnt/$group
				y
			}
			if not
				echo !$ngroup contains no messages
		}
		if not
			echo !$ngroup does not exist
	case h
		{
			for(i in $r)
				h $i
		} | eval $pager
		post=$r($#r)
		prompt=$post
	case help
		printhelp
	case k
		k $group
	case k' '*
		k `{nshift $cmd | sed 's/\./\//g'}
	case kf' '*
		grep -e `{nshift $cmd} $home/lib/newsgroups |
			sed 's/^/  g	/g' |
			eval $pager
	case p
		for(i in $r)
			np $i
	case P
		for(i in $r)
			P $i
	case q
		q=1 y # BUP STOP
		exit
	case r
		for(i in $r)
			r $i
		post=$r($#r)
		prompt=$post
	case y
		y
	case '"'
		for(i in $r)
			'"' $i
		post=$r($#r)
		prompt=$post
	case '||'*
		cmd=`{echo $"cmd | sed 's/^\|\|//g'}
		cat $mnt/$group/^$rposts($post)^/article | eval $cmd
	case '|'*
		cmd=`{echo $"cmd | sed 's/^\|//g'}
		cat $mnt/$group/^$rposts($post)^/body | eval $cmd
	case '!'*
		eval `{echo $"cmd | sed 's/^\!//g'}
	case '?'
		echo editor: $editor
		echo pager: $pager
		echo mnt: $mnt
		echo group: $group
		echo maxposts: $maxposts
		echo '#go': $#go
		echo rposts: $rposts
		echo 'rposts(r):' $rposts($r)
		echo posts: $posts
		echo post: $post
		echo r: $r
	case *
		if(~ $post $posts(1) && ~ $#go 0)
			np $post
		if not if(! ~ $post $posts($#posts)){
			post=`{echo $post^+1 | bc}
			if(test $post -gt $posts($#posts))
				post=$posts($#posts)
			np $post
		}
	}	
}