[slrn] Cleanthreads v.2
- From: ernobe <ernobe@xxxxxxxxx>
- Date: Wed, 25 Aug 2010 13:57:35 +0000 (UTC)
I've improved my program for tagging retrieved articles ( using slrnpull ) so
that it now identifies both new article bodies and new headers. It does so by
reading slrns' newsrc file after calling slrn. The call to slrn now not only
makes sure the tagged articles are safe from deletion, but because it writes
the newsrc file, after the call it can be read to identify which articles are
left on the list. So now the overall deletion of incomplete threads occurs
only whenever slrnpull is called, not each time a newsgroup is entered. The
call to slrn requires a copy of the initialization file ( .slrnrc ) with the
following interpret lines:
interpret groups.sl
interpret cleaner.sl
and the cleaner macro only has the delete routine:
() = register_hook ("article_mode_startup_hook", "my_groups" );
define make_clean_threads ()
{
call ("header_bob");
do
{
if (not ("" == extract_article_header ("References")))
{
if (1 == get_body_status ())
{
call ("delete");
header_up (1);
}
}
}
while (header_down (1));
call ("expunge");
}
() = register_hook ("article_mode_startup_hook", "make_clean_threads" );
The groups macro is written by the Icon program, which also writes the
mythreads macro based on information it receives after the call to slrn. So
the ordinary use .slrnrc file should have both of these interpret lines:
interpret mythreads.sl
interpret cleanthreads.sl
The cleanthreads macro registers the routines defined in mythreads and
contains other routines not strictly related to this program.
procedure main( x )
v := []
d := []
e := []
k := []
v1 := 0
b6 := table()
n7 := []
s := open( "/home/roy/spool/slrnpull.conf" ) | stop( "no slrnpull conf file" )
while s1 := read( s ) do {
if s1[ 1 ] == "#" then next
s1 ? {
s2 := tab( upto( ' ' ) | 0 )
if s2 == ( "default" | "" ) then next
else put( d, s2 )
} }
x[ 1 ] | system( "slrnpull -d /home/roy/spool --fetch-score 1" ) | exit()
every put( v, m1( !d ) )
if *v > 0 then {
m := open( "groups.sl", "crw" )
write( m, "define my_groups ()\n{ variable mm = current_newsgroup (),dma,hhh,list;" )
every b := !v do {
v1 +:= 1
b1 := b[ 1 ]
b2 := b[ 2 ]
b3 := b[ 3 ]
write( m, "variable " || b[ 6 ] || "_threads = {" )
every u := open( b3 || "/" || ( b4 := !b1 ), "r" ) do
{
b2 -:= 1
while c := read( u ) do {
( c[ 1:9 ] == "Message-" ) & break
}
writes( m, "\"", ( b5 := c[ 13:0 ] ), "\"" )
if b2 > 0 then write( m, "," )
b6[ b4 ] := b5
close( u )
}
write( m, " };" )
b[ 1 ] := b6
v[ v1 ] := b
put( e, b[ 5:0 ] )
b6 := table()
}
write( m, "switch (mm)" )
every e1 := !e do {
write( m, "{ case \"", e1[ 1 ], "\" : list = ", e1[ 2 ] || "_threads; }" )
}
write( m, "{ list = {}; }\nhhh = length (list);\nwhile (hhh)\n{ hhh--;\n",
"dma = list[hhh];\nif (1 == locate_header_by_msgid (dma,0))\n",
"if (0 == get_body_status ())\nset_header_flags (4); }\n",
"collapse_threads (); }\n",
"define group_mode_startup_hook ()\n{variable dma, hhh, news = {" )
while e2 := get( e ) do {
writes( m, "\"", !e2, "\"" )
if *e > 0 then write( m, "," ) }
write( m, " };\nhhh = length (news);\nwhile (hhh)\n{ hhh--;\ndma = news[hhh];\n",
"set_group_order (dma);\ngroup_up_n (1);\nif (dma == current_newsgroup ())\n",
"{select_group ();\ncall(\"quit\");}}\ncall(\"quit\");}" )
system( "slrn -n -w0 -i groupmoderc --debug slrnfile" )
}
else exit()
n := ( open( ".jnewsrc" ) )
while n1 := read( n ) do {
n1 ? {
n2 := tab( upto( ':' ) )
move( 2 )
repeat {
n3 := tab( upto( ',' ) | 0 )
if numeric( n3 ) then {
put( k, integer( n3 ) )
move( 1 ) | break
next
}
n3 ? {
k1 := integer( tab( upto( '-' ) ) )
move( 1 )
k2 := integer( tab( 0 ) )
put( k, k1 )
while k1 +:= 1 do {
put( k, k1 )
if k1 = k2 then break
}
}
move( 1 ) | break }
}
v1 := 0
every b := !v do {
v1 +:= 1
if b[ 5 ] == n2 then {
n4 := b[ 4 ] -- set( k )
break
}
}
every put( n7, key( b[ 1 ] ) )
n5 := set( n7 ) ** n4
n6 := *n5
if n6 > 0 then {
b[ 3 ] := n5
b[ 2 ] := n6
v[ v1 ] := b }
else v := v[ 1 : v1 ] ||| v[ (v1 + 1):0 ]
k := []
n7 := []
}
o := open( "mythreads.sl", "crw" )
write( o, "define my_groups ()\n{ variable mm = current_newsgroup (),dma,hhh,list;" )
every b := !v do {
b1 := b[ 1 ]
b2 := b[ 2 ]
b3 := b[ 3 ]
write( o, "variable " || b[ 6 ] || "_threads = {" )
every u := b1[ !b3 ] do
{
b2 -:= 1
writes( o, "\"", u, "\"" )
if b2 > 0 then write( o, "," )
}
write( o, " };" )
put( e, b[ 5:0 ] )
}
write( o, "switch (mm)" )
every e1 := !e do {
write( o, "{ case \"", e1[ 1 ], "\" : list = ", e1[ 2 ] || "_threads; }" )
}
write( o, "{ list = {}; }\nhhh = length (list);\nwhile (hhh)\n{ hhh--;\n",
"dma = list[hhh];\nif (1 == locate_header_by_msgid (dma,0))\n",
"set_header_score (1); }\ncall(\"header_bob\"); }\n",
"define group_mode_startup_hook ()\n{variable dma, hhh, news = {" )
while e2 := get( e ) do {
writes( o, "\"", !e2, "\"" )
if *e > 0 then write( o, "," ) }
write( o, " };\nhhh = length (news);\nwhile (hhh)\n{ hhh--;\ndma = news[hhh];\n",
"set_group_order (dma);\ngroup_up_n (1);\nset_group_flags (2); } }" )
end
procedure m1( s )
s2 := ""
f := "/home/roy/spool/news/"
g := ""
g1 := "/home/roy/clean/"
k := []
g6 := []
g7 := []
g8 := []
s ? { while s1 := tab( upto( '.' ) ) do {
f ||:= s1 || "/"
s2 ||:= s1[ 1:2 ]
move( 1 ) }
s3 := tab( 0 )
f ||:= s3
s2 ||:= s3[ 1:4 ]
every g ||:= ( !s2 ** &letters )
}
g2 := g1 || g || "-spool"
g3 := open( g2, "rw" | "crw" )
g4 := g1 || g || "-allbodies"
g5 := open( g4, "rw" | "crw" )
while put( g6, integer( read( g3 ) ) )
while put( g7, integer( read( g5 ) ) )
close( g3 )
system( "ls " || f || " > " || g2 ) | stop( "unable to open directory" )
g3 := open( g2, "rw" )
while put( g8, integer( read( g3 ) ) )
g9 := set( g8 )
# find new headers
g01 := g9 -- set( g6 )
n := ( open( f || "/.headers" ) | "" )
n1 := !n
\n1 ? {
repeat {
n2 := tab( upto( ',' ) | 0 )
if numeric( n2 ) then {
put( k, integer( n2 ) )
move( 1 ) | break
next
}
n2 ? {
k1 := integer( tab( upto( '-' ) ) )
move( 1 )
k2 := integer( tab( 0 ) )
put( k, k1 )
while k1 +:= 1 do {
put( k, k1 )
if k1 = k2 then break
}
}
move( 1 ) | break }
}
g02 := g9 -- set( k )
# find new bodies
g03 := g02 -- set( g7 )
g04 := g01 ++ g03
h := *g04
g05 := g1 || g || "-bodies"
g06 := open( g05, "crw" )
every write( g06, !g02 )
close( g06 )
close( g5 )
system( "mv " || g05 || " " || g4 )
if ( h > 0 ) & ( *g7 > 0 ) & ( *g6 > 0 ) then return [ g04, h, f, g9, s, g ]
end
To use this, edit the four lines containing addresses on your system, that is:
1. the location of the slrnpull conf. file
2. the location of the slrnpull news directory
3. the slrnpull command line
4. the location of where this program will keep its files
Then compile it with Icon ( http://cs.arizona.edu/icon ). The first time it
is used, it will only gather information about the article bodies present in
the spool, so you can obviate the call to slrnpull by calling this program
with an argument (anything), unless of course the group is totally new and you
don't have a directory already created for it in the slrnpull news directory.
Here is what my current mythreads.sl macro looks like:
define my_groups ()
{ variable mm = current_newsgroup (),dma,hhh,list;
variable aisuf_threads = {
"<3ba6225a-3939-43b1-a698-cd1e8c30d5de@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<44dcfb12-58c4-482e-8861-eccb6841a04c@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>" };
variable asuf_threads = {
"<488bfd86-2288-4238-91fc-abe3b2db710e@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<bbd5f963-a11d-469b-8bad-4a88017de2ff@xxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<e05cfd9f-3f53-4c06-bb58-6f1e7feb2032@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>" };
variable aath_threads = {
"<i4ta2o$8dg$1@xxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<Virgil-5FF374.17373022082010@xxxxxxxxxxxxxxxxxxxxxxxxx>",
"<39b4eede-9716-484f-8fc9-b4423153ac49@xxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<TUnco.68141$lS1.58138@xxxxxxxxxxxx>",
"<172fb4c8-4f00-412c-b395-dbacb0c78033@xxxxxxxxxxxxxxxxxxxxxxxxxxx>" };
variable apsy_threads = {
"<40ef6d88-d80a-4155-a9c9-edc8d03e7d42@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<c3b6aedb-39b7-4a6b-b978-336e5cc4873c@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>" };
variable arccat_threads = {
"<285a268f-f929-4896-b8cd-13deff5961c4@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<8dettmF4d3U1@xxxxxxxxxxxxxxxxxx>" };
variable trnew_threads = {
"<NMudnZnZAMQX4-_RnZ2dnUVZ_sOdnZ2d@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<lNOdnZACK_U-4O_RnZ2dnUVZ_uudnZ2d@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>" };
variable trcou_threads = {
"<26fbbd39-52d0-44fa-9cc0-c92766e2b53a@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>",
"<ZABco.58710$F%7.3802@xxxxxxxxxxxx>",
"<S2zco.28345$6o7.12482@xxxxxxxxxxxx>" };
variable ecmat_threads = {
"<8df3t2F82eU1@xxxxxxxxxxxxxxxxxx>",
"<8dfbp1FnfpU1@xxxxxxxxxxxxxxxxxx>" };
variable ehlit_threads = {
"<8dfsq9F3g3U1@xxxxxxxxxxxxxxxxxx>",
"<8dfs8lFvcjU1@xxxxxxxxxxxxxxxxxx>",
"<i4ubig$kfc$1@xxxxxxxxxxxxxxxxx>" };
switch (mm)
{ case "alt.islam.sufism" : list = aisuf_threads; }
{ case "alt.sufi" : list = asuf_threads; }
{ case "alt.atheism" : list = aath_threads; }
{ case "alt.psychology" : list = apsy_threads; }
{ case "alt.religion.christian.catholic" : list = arccat_threads; }
{ case "talk.religion.newage" : list = trnew_threads; }
{ case "talk.religion.course-miracle" : list = trcou_threads; }
{ case "es.ciencia.matematicas" : list = ecmat_threads; }
{ case "es.humanidades.literatura" : list = ehlit_threads; }
{ list = {}; }
hhh = length (list);
while (hhh)
{ hhh--;
dma = list[hhh];
if (1 == locate_header_by_msgid (dma,0))
set_header_score (1); }
call("header_bob"); }
define group_mode_startup_hook ()
{variable dma, hhh, news = {
"alt.islam.sufism",
"alt.sufi",
"alt.atheism",
"alt.psychology",
"alt.religion.christian.catholic",
"talk.religion.newage",
"talk.religion.course-miracle",
"es.ciencia.matematicas",
"es.humanidades.literatura" };
hhh = length (news);
while (hhh)
{ hhh--;
dma = news[hhh];
set_group_order (dma);
group_up_n (1);
set_group_flags (2); } }
And here are the relevant parts from cleanthreads.sl:
() = register_hook ("article_mode_hook", "my_groups" );
define make_clean_threads ()
{
variable amd, dma, hhh, list, mdo, ppp;
list = {};
call ("header_bob");
do
{
if (not ("" == extract_article_header ("References")))
{
amd = extract_article_header ("Message-ID");
list_insert (list, amd);
}
}
while (header_down (1));
hhh = length (list);
mdo = hhh;
while (mdo)
{
mdo--;
dma = list[mdo];
() = locate_header_by_msgid (dma,0);
set_prefix_argument (2);
call ("get_parent_header");
}
collapse_threads ();
if (hhh == 0)
call("header_bob");
}
% I've found these routines useful for keeping threads collapsed when
% reading the original post, reading read articles, etc.
define going_down ()
{
header_down (1);
if (1 == has_parent ())
article_line_down (1);
else
{
article_line_down (1);
collapse_thread ();
}
}
define going_up ()
{
header_up (1);
if (1 == has_parent ())
article_line_down (1);
else
{
article_line_down (1);
collapse_thread ();
}
}
define prevheader ()
{
if (1 == prev_tagged_header ())
{
if (0 == get_body_status ())
article_line_down (1);
if (0 == has_parent ())
collapse_threads ();
}
}
define new_slash ()
{
if (1 == has_parent ())
call("hide_article");
else
{
call("hide_article");
collapse_thread ();
}
}
define nextheader ()
{
if (1 == next_tagged_header ())
{
if (0 == get_body_status ())
article_line_down (1);
if (0 == has_parent ())
collapse_threads ();
}
}
define my_down ()
{
variable amd;
if (not (3 == _is_article_visible ()))
article_line_down ();
else
{
amd = article_cline_number ();
amd++;
article_goto_line (amd);
}
if (0 == has_parent ())
collapse_thread ();
}
define my_up ()
{
variable amd;
if (not (3 == _is_article_visible ()))
article_line_up ();
else
{
amd = article_cline_number ();
amd--;
article_goto_line (amd);
}
if (0 == has_parent ())
collapse_thread ();
}
define recon_old ()
{
() = register_hook ("article_mode_startup_hook", "make_clean_threads");
select_group ();
() = unregister_hook ("article_mode_startup_hook", "make_clean_threads");
}
definekey ("going_down", "<Right>", "article");
definekey ("going_up", "<Left>", "article");
definekey ("new_slash", "/", "article" );
definekey ("nextheader", "7", "article" );
definekey ("prevheader", "6", "article" );
definekey ("my_down", "<Down>", "article" );
definekey ("my_up", "<Up>", "article" );
definekey ("recon_old", " ", "group" );
--
"The world of existence is an emanation of the merciful attribute of God."
Abdu'l-Baha
http://www.costarricense.cr/pagina/ernobe
.
- Follow-Ups:
- Re: [slrn] Cleanthreads v.2
- From: ernobe
- Re: [slrn] Cleanthreads v.2
- Prev by Date: Re: [slrn] Generating Message-ID not working on windows
- Next by Date: Re: Getting NG list in 40tude
- Previous by thread: Re: Miss You Brittany [03of52] - "Brittany-Murphy001.jpg" yEnc (1/1) 92740 bytes -
- Next by thread: Re: [slrn] Cleanthreads v.2
- Index(es):
Relevant Pages
|