newt: implement ned-style address ranges and overhaul h command to suit
This commit is contained in:
parent
4616c93e8d
commit
6213e137ff
2 changed files with 169 additions and 91 deletions
214
rc/bin/newt
214
rc/bin/newt
|
@ -1,5 +1,6 @@
|
||||||
#!/bin/rc
|
#!/bin/rc
|
||||||
# bloated, featureful usenet reader for use with nntpfs
|
# NEWT, their six-year-old daughter, yells from the back...
|
||||||
|
# use with nntpfs
|
||||||
rfork en
|
rfork en
|
||||||
ramfs
|
ramfs
|
||||||
argv0=$0
|
argv0=$0
|
||||||
|
@ -10,7 +11,7 @@ maxposts=30
|
||||||
mnt=/mnt/news
|
mnt=/mnt/news
|
||||||
if(~ $#newtname 0)
|
if(~ $#newtname 0)
|
||||||
newtname=newt@dont-email.me
|
newtname=newt@dont-email.me
|
||||||
fn enterpost{
|
fn e{
|
||||||
{
|
{
|
||||||
echo From: $"newtname
|
echo From: $"newtname
|
||||||
echo Newsgroups: `{echo $group | sed 's/\//\./g'}
|
echo Newsgroups: `{echo $group | sed 's/\//\./g'}
|
||||||
|
@ -18,9 +19,19 @@ fn enterpost{
|
||||||
echo
|
echo
|
||||||
} >/tmp/post
|
} >/tmp/post
|
||||||
eval $editor /tmp/post
|
eval $editor /tmp/post
|
||||||
cat /tmp/post >$mnt/$group/post
|
yn send
|
||||||
|
if(~ $yn y)
|
||||||
|
cat /tmp/post >$mnt/$group/post
|
||||||
}
|
}
|
||||||
fn f { du -a $* | sed 's/^.* //g' }
|
fn f { du -a $* | sed 's/^.* //g' }
|
||||||
|
fn flag{
|
||||||
|
if(~ $1 [\+][aDdfrSs] [-][aDdfrSs]){
|
||||||
|
if(test $2 -le $#rposts && test -f $rposts($2)^/flags)
|
||||||
|
echo $1 >$rposts($2)^/flags
|
||||||
|
if not
|
||||||
|
echo !address
|
||||||
|
}
|
||||||
|
}
|
||||||
fn fmtd{
|
fn fmtd{
|
||||||
date=`{cat}
|
date=`{cat}
|
||||||
if(! ~ $date(1) [0-9]*)
|
if(! ~ $date(1) [0-9]*)
|
||||||
|
@ -50,7 +61,7 @@ fn fmtd{
|
||||||
}
|
}
|
||||||
fn geth{
|
fn geth{
|
||||||
for(i in $*){
|
for(i in $*){
|
||||||
from=`{awk -F ' ' '{print $3;}' $i/xover}
|
from=`{awk -F ' ' '{print $3;}' $rposts($i)^/xover >[2]/dev/null}
|
||||||
if(! ~ $#from 0 && ! ~ $#from 1){
|
if(! ~ $#from 0 && ! ~ $#from 1){
|
||||||
nfrom=`{
|
nfrom=`{
|
||||||
for(i in $from){
|
for(i in $from){
|
||||||
|
@ -61,16 +72,31 @@ fn geth{
|
||||||
if(! ~ $#nfrom 0)
|
if(! ~ $#nfrom 0)
|
||||||
from=$nfrom
|
from=$nfrom
|
||||||
}
|
}
|
||||||
if(! ~ $#from 0){
|
if(~ $#from 0)
|
||||||
date=`{awk -F ' ' '{print $4;}' $i/xover >[2]/dev/null | fmtd}
|
from=nil
|
||||||
awk -v date'='$"date -v from'='$from(1) -F ' ' \
|
date=`{awk -F ' ' '{print $4;}' $rposts($i)^/xover >[2]/dev/null | fmtd}
|
||||||
'{print " " $1 " " date " " from " " substr($2,0,50);}' $i/xover >[2]/dev/null
|
if(~ $#date 0)
|
||||||
}
|
date=nil
|
||||||
if not
|
subject=`{awk -F ' ' '{print substr($2,0,50);}' $rposts($i)^/xover >[2]/dev/null}
|
||||||
echo ' '$"i' nil nil nil'
|
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 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{
|
fn k{
|
||||||
kmnt=`{echo $mnt | sed 's/\//\\\//g'}
|
kmnt=`{echo $mnt | sed 's/\//\\\//g'}
|
||||||
f $mnt/$* |
|
f $mnt/$* |
|
||||||
|
@ -80,17 +106,16 @@ fn k{
|
||||||
}
|
}
|
||||||
fn nshift{ shift; echo $* }
|
fn nshift{ shift; echo $* }
|
||||||
fn printhelp{
|
fn printhelp{
|
||||||
echo '[0-9]+ print specified message
|
echo 'Commands are of the form [<range>] <command> [args]
|
||||||
b back
|
<range> := <addr> | <addr>','<addr>
|
||||||
|
<command> :=
|
||||||
|
b print the next ten headers
|
||||||
e enter message
|
e enter message
|
||||||
f jump to first message
|
|
||||||
g ... go to specified group
|
g ... go to specified group
|
||||||
h print message headlines
|
h print message headline (,h for all)
|
||||||
help print this help message
|
help print this help message
|
||||||
k ... list sub-groups under specified group
|
k ... list sub-groups under specified group
|
||||||
kf ... grep $home/lib/newsgroups for regexp
|
kf ... grep $home/lib/newsgroups for regexp
|
||||||
l jump to last message
|
|
||||||
n next
|
|
||||||
p print message with minimal headers
|
p print message with minimal headers
|
||||||
P print message with full headers
|
P print message with full headers
|
||||||
q quit
|
q quit
|
||||||
|
@ -101,24 +126,62 @@ y synchronize message list with server
|
||||||
||cmd pipe raw message to a command
|
||cmd pipe raw message to a command
|
||||||
? print debug information'
|
? print debug information'
|
||||||
}
|
}
|
||||||
fn printp{
|
fn p{
|
||||||
if(test -d $mnt/$group/$1){
|
if(test $1 -le $#rposts && test -f $mnt/$group/$rposts($1)^/body){
|
||||||
{ # don't stutter
|
{ # don't stutter
|
||||||
grep -e '(^From|^Newsgroups|^Subject|^Date)' $1/header
|
grep -e '(^From|^Newsgroups|^Subject|^Date)' $rposts($1)^/header
|
||||||
echo
|
echo
|
||||||
cat $1/body
|
cat $rposts($1)^/body
|
||||||
} >/tmp/p
|
} >/tmp/p
|
||||||
cat /tmp/p
|
cat /tmp/p
|
||||||
}
|
}
|
||||||
echo
|
echo
|
||||||
|
r=$1
|
||||||
|
post=$1
|
||||||
prompt=$group/$1
|
prompt=$group/$1
|
||||||
}
|
}
|
||||||
fn printpp{
|
fn P{
|
||||||
if(test -d $mnt/$group/$1)
|
if(test $1 -le $#rposts && test -f $mnt/$group/$rposts($1)^/article)
|
||||||
cat $1/article
|
cat $rposts($1)^/article
|
||||||
echo
|
echo
|
||||||
|
r=$1
|
||||||
|
post=$1
|
||||||
prompt=$group/$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{
|
fn usage{
|
||||||
echo usage: $argv0 '[ -f newsgroup ] [ -m mountpoint ] [ -p maxposts ]' >[1=2]
|
echo usage: $argv0 '[ -f newsgroup ] [ -m mountpoint ] [ -p maxposts ]' >[1=2]
|
||||||
exit usage
|
exit usage
|
||||||
|
@ -147,42 +210,42 @@ if(! test -d $mnt/$group){
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
builtin cd $mnt/$group
|
builtin cd $mnt/$group
|
||||||
go=()
|
y
|
||||||
posts=`{getposts}
|
|
||||||
geth $posts >/tmp/h
|
|
||||||
post=$posts(1)
|
|
||||||
echo $#posts messages
|
|
||||||
while(){
|
while(){
|
||||||
echo -n $"prompt': '
|
echo -n $"prompt': '
|
||||||
cmd=`{read}
|
# 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){
|
switch($cmd){
|
||||||
case [0-9]*
|
|
||||||
if(grep -s -e '^[0-9]+$' <{echo $cmd(1)}){
|
|
||||||
post=$cmd(1)
|
|
||||||
printp $post
|
|
||||||
}
|
|
||||||
case b
|
case b
|
||||||
if(! ~ $post $posts(1)){
|
r=`{seq $r(1) `{echo $r(1)^+10|bc}}
|
||||||
post=`{echo $post^-1 | bc}
|
if(test $r($#r) -gt $posts($#posts))
|
||||||
printp $post
|
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
|
case e
|
||||||
enterpost
|
subject=() e
|
||||||
case f
|
|
||||||
post=$posts(1)
|
|
||||||
printp $post
|
|
||||||
case g' '*
|
case g' '*
|
||||||
ngroup=`{nshift $cmd | sed 's/\./\//g'}
|
ngroup=`{nshift $cmd | sed 's/\./\//g'}
|
||||||
if(test -d $mnt/$ngroup){
|
if(test -d $mnt/$ngroup){
|
||||||
if(grep -s -e '^[0-9]+$' <{ls -p $mnt/$ngroup}){
|
if(grep -s -e '^[0-9]+$' <{ls -p $mnt/$ngroup}){
|
||||||
group=$ngroup
|
group=$ngroup
|
||||||
builtin cd $mnt/$group
|
builtin cd $mnt/$group
|
||||||
go=()
|
y
|
||||||
posts=`{getposts}
|
|
||||||
geth $posts >/tmp/h
|
|
||||||
post=$posts(1)
|
|
||||||
prompt=$group
|
|
||||||
echo $#posts messages
|
|
||||||
}
|
}
|
||||||
if not
|
if not
|
||||||
echo !$ngroup contains no messages
|
echo !$ngroup contains no messages
|
||||||
|
@ -190,7 +253,10 @@ while(){
|
||||||
if not
|
if not
|
||||||
echo !$ngroup does not exist
|
echo !$ngroup does not exist
|
||||||
case h
|
case h
|
||||||
cat /tmp/h
|
for(i in $r)
|
||||||
|
h $i
|
||||||
|
post=$r($#r)
|
||||||
|
prompt=$post
|
||||||
case help
|
case help
|
||||||
printhelp
|
printhelp
|
||||||
case k
|
case k
|
||||||
|
@ -200,57 +266,53 @@ while(){
|
||||||
case kf' '*
|
case kf' '*
|
||||||
grep -e `{nshift $cmd} $home/lib/newsgroups |
|
grep -e `{nshift $cmd} $home/lib/newsgroups |
|
||||||
sed 's/^/ g /g'
|
sed 's/^/ g /g'
|
||||||
case l
|
|
||||||
post=$posts($#posts)
|
|
||||||
printp $post
|
|
||||||
case p
|
case p
|
||||||
printp $post
|
for(i in $r)
|
||||||
case p' '*
|
p $i
|
||||||
post=`{nshift $cmd}
|
|
||||||
printp $post
|
|
||||||
case P
|
case P
|
||||||
printpp $post
|
for(i in $r)
|
||||||
case P' '*
|
P $i
|
||||||
post=`{nshift $cmd}
|
|
||||||
printpp $post
|
|
||||||
case q
|
case q
|
||||||
|
q=1 y # BUP STOP
|
||||||
exit
|
exit
|
||||||
case r
|
case r
|
||||||
if(test -f $mnt/$group/$post/header){
|
for(i in $r)
|
||||||
subject='Re: '^`{grep -e '^Subject: ' $mnt/$group/$post/header | sed 's/^Subject: //g'}
|
r $i
|
||||||
enterpost
|
post=$r($#r)
|
||||||
}
|
prompt=$post
|
||||||
if not
|
|
||||||
echo !message missing
|
|
||||||
case y
|
case y
|
||||||
posts=`{getposts}
|
y
|
||||||
geth $posts >/tmp/h
|
|
||||||
echo $#posts messages
|
|
||||||
case '"'
|
case '"'
|
||||||
printp $post | sed 1d | sed 's/^/> /g' | sed 's/^> >/>>/g'
|
for(i in $r)
|
||||||
|
'"' $i
|
||||||
|
post=$r($#r)
|
||||||
|
prompt=$post
|
||||||
case '||'*
|
case '||'*
|
||||||
cmd=`{echo $"cmd | sed 's/^\|\|//g'}
|
cmd=`{echo $"cmd | sed 's/^\|\|//g'}
|
||||||
cat $mnt/$group/$post/article | eval $cmd
|
cat $mnt/$group/^$rposts($post)^/article | eval $cmd
|
||||||
case '|'*
|
case '|'*
|
||||||
cmd=`{echo $"cmd | sed 's/^\|//g'}
|
cmd=`{echo $"cmd | sed 's/^\|//g'}
|
||||||
cat $mnt/$group/$post/body | eval $cmd
|
cat $mnt/$group/^$rposts($post)^/body | eval $cmd
|
||||||
case '?'
|
case '?'
|
||||||
echo mnt: $mnt
|
echo mnt: $mnt
|
||||||
echo group: $group
|
echo group: $group
|
||||||
echo maxposts: $maxposts
|
echo maxposts: $maxposts
|
||||||
|
echo rposts: $rposts
|
||||||
|
echo 'rposts(r):' $rposts($r)
|
||||||
echo posts: $posts
|
echo posts: $posts
|
||||||
echo post: $post
|
echo post: $post
|
||||||
case n *
|
echo r: $r
|
||||||
|
case *
|
||||||
if(~ $post $posts(1) && ~ $#go 0){
|
if(~ $post $posts(1) && ~ $#go 0){
|
||||||
go=1
|
go=1
|
||||||
printp $post
|
p $post
|
||||||
}
|
}
|
||||||
if not if(! ~ $post $posts($#posts)){
|
if not if(! ~ $post $posts($#posts)){
|
||||||
go=1
|
go=1
|
||||||
post=`{echo $post^+1 | bc}
|
post=`{echo $post^+1 | bc}
|
||||||
if(test $post -gt $posts($#posts))
|
if(test $post -gt $posts($#posts))
|
||||||
post=$posts($#posts)
|
post=$posts($#posts)
|
||||||
printp $post
|
p $post
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,10 +39,35 @@ Default is 30.
|
||||||
starts by reading the list of messages in the
|
starts by reading the list of messages in the
|
||||||
.I newsgroup,
|
.I newsgroup,
|
||||||
printing out the number of messages, and then prompting for commands.
|
printing out the number of messages, and then prompting for commands.
|
||||||
The prompt itself presents the name of the group followed by
|
The prompt itself represents the name of the group followed by the
|
||||||
the message number in the form of a file system path, relative to the
|
message number in the form of a file system path, relative to the
|
||||||
.I mountpoint.
|
.I mountpoint.
|
||||||
.PP
|
.PP
|
||||||
|
Commands, as in
|
||||||
|
.IR ed (1),
|
||||||
|
are of the form
|
||||||
|
.RI `[ range ]
|
||||||
|
.I command
|
||||||
|
.RI [ arguments ]'.
|
||||||
|
The command is applied to each message in the (optional) range.
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
The address range can be:
|
||||||
|
.TP 1.4i
|
||||||
|
.I address
|
||||||
|
to indicate a single message header.
|
||||||
|
.PD
|
||||||
|
.TP
|
||||||
|
.IB address , address
|
||||||
|
to indicate a range of contiguous message headers.
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
|
The addresses can be:
|
||||||
|
.TP 1.4i
|
||||||
|
.I number
|
||||||
|
to indicate a particular message.
|
||||||
|
.PD
|
||||||
|
.PP
|
||||||
The commands are:
|
The commands are:
|
||||||
.PP
|
.PP
|
||||||
.TP
|
.TP
|
||||||
|
@ -51,7 +76,7 @@ Print message
|
||||||
.I number.
|
.I number.
|
||||||
.TP
|
.TP
|
||||||
.B b
|
.B b
|
||||||
Print the previous message.
|
Print the headers for the next ten messages.
|
||||||
.TP
|
.TP
|
||||||
.B e
|
.B e
|
||||||
Enter a new message, honoring the environment variable
|
Enter a new message, honoring the environment variable
|
||||||
|
@ -59,9 +84,6 @@ Enter a new message, honoring the environment variable
|
||||||
Default is
|
Default is
|
||||||
.IR hold (1) .
|
.IR hold (1) .
|
||||||
.TP
|
.TP
|
||||||
.B f
|
|
||||||
Jump to the first message in the group.
|
|
||||||
.TP
|
|
||||||
.BI g " newsgroup
|
.BI g " newsgroup
|
||||||
Change to the specified
|
Change to the specified
|
||||||
.I newsgroup.
|
.I newsgroup.
|
||||||
|
@ -70,9 +92,9 @@ The name of a group may be provided in dotted
|
||||||
.TP
|
.TP
|
||||||
.B h
|
.B h
|
||||||
Print the disposition, date, sender and subject line
|
Print the disposition, date, sender and subject line
|
||||||
of all messages in the group. These lines are suitable
|
of the message. These lines are suitable for selecting
|
||||||
for selecting and sending to the prompt, in order to
|
and sending to the prompt, in order to print messages
|
||||||
print messages either singly or in aggregate.
|
either singly or in aggregate.
|
||||||
.TP
|
.TP
|
||||||
.B help
|
.B help
|
||||||
Print a summary of the available commands.
|
Print a summary of the available commands.
|
||||||
|
@ -93,12 +115,6 @@ for
|
||||||
.I regexp
|
.I regexp
|
||||||
and prints commands suitable for changing to each match.
|
and prints commands suitable for changing to each match.
|
||||||
.TP
|
.TP
|
||||||
.B l
|
|
||||||
Jump to the last message in the group.
|
|
||||||
.TP
|
|
||||||
.B n, or enter key
|
|
||||||
Print the next message.
|
|
||||||
.TP
|
|
||||||
.B p
|
.B p
|
||||||
Print the current message with minimal headers.
|
Print the current message with minimal headers.
|
||||||
.TP
|
.TP
|
||||||
|
|
Loading…
Reference in a new issue