]>
jfr.im git - irssi-scripts.git/blob - dim_nicks.pl
4 our $VERSION = '0.4.8' ; # baf75f08d3d32c9
7 contact
=> 'Nei @ anti @conference .jabber.teamidiot.de' ,
8 url
=> "http://anti.teamidiot.de/" ,
10 description
=> 'Dims nicks that are not in channel anymore.' ,
11 license
=> 'GNU GPLv2 or later' ,
16 # Once loaded, this script will record the nicks of each new
17 # message. If the user leaves the room, the messages will be rewritten
18 # with the nick in another colour/style.
20 # Depending on your theme, tweaking the forms settings may be
21 # necessary. With the default irssi theme, this script should just
26 # /set dim_nicks_color <colour>
27 # * the colour code to use for dimming the nick, or a string of format
28 # codes with the special token $* in place of the nick (e.g. %I$*%I
31 # /set dim_nicks_history_lines <num>
32 # * only this many lines of messages are remembered/rewritten (per
35 # /set dim_nicks_ignore_hilights <ON|OFF>
36 # * ignore lines with hilight when dimming
38 # /set dim_nicks_forms_skip <num>
39 # /set dim_nicks_forms_search_max <num>
40 # * these two settings limit the range where to search for the
42 # It sets how many forms (blocks of irssi format codes or
43 # non-letters) to skip at the beginning of line before starting to
44 # search for the nick, and from then on how many forms to search
46 # You should set this to the appropriate values to avoid (a) dimming
47 # your timestamp (b) dimming message content instead of the nick.
48 # To check your settings, you can use the command
49 # /script exec Irssi::Script::dim_nicks::debug_forms
52 no warnings
'redefine' ;
53 use constant IN_IRSSI
=> __PACKAGE__
ne 'main' || $ENV { IRSSI_MOCK
};
67 my $history_lines = 100 ;
69 my $search_forms_max = 5 ;
70 my $ignore_hilights = 1 ;
71 my $color_letter = 'K' ;
73 # nick object cache, chan object cache, line id cache, line id -> window map, -> channel, -> nick, -> nickname, channel -> line ids, channel->nickname->departure time, channel->nickname->{parts of line}
74 my ( %nick_reg , %chan_reg , %history_w , %history_c , %history_n , %history_nn , %history_st , %lost_nicks , %lost_nicks_fs , %lost_nicks_fc , %lost_nicks_bc , %lost_nicks_bs );
76 our ( $dest , $chanref , $nickref );
80 my ( $srv , $msg , $nick , $addr , $targ ) = @_ ;
81 local $chanref = $srv -> channel_find ( $targ );
82 local $nickref = ref $chanref ? $chanref -> nick_find ( $nick ) : undef ;
83 & Irssi
:: signal_continue
;
89 my $win = Irssi
:: active_win
;
90 my $view = $win -> view ;
91 my $cl = $color_letter ;
92 if (- 1 == index $cl , ' $* ' ) {
95 $win -> print_after ( undef , MSGLEVEL_NEVER
, " $cl " );
96 my $lp = $win -> last_line_insert ;
97 my $color_code = $lp -> get_text ( 1 );
98 $color_code =~ s/ $// ;
99 $view -> remove_line ( $lp );
100 @color_code = split /\$\*/ , $color_code , 2 ;
104 $history_lines = Irssi
:: settings_get_int
( set
'history_lines' );
105 $skip_forms = Irssi
:: settings_get_int
( set
'forms_skip' );
106 $search_forms_max = Irssi
:: settings_get_int
( set
'forms_search_max' );
107 $ignore_hilights = Irssi
:: settings_get_bool
( set
'ignore_hilights' );
108 my $new_color = Irssi
:: settings_get_str
( set
'color' );
109 if ( $new_color ne $color_letter ) {
110 $color_letter = $new_color ;
122 & Irssi
:: signal_continue
;
126 for my $ch ( keys %history_st ) {
127 if (@{ $history_st { $ch }} > 2 * $history_lines ) {
128 my @del = splice @{ $history_st { $ch }}, 0 , $history_lines ;
129 delete @history_w { @del };
130 delete @history_c { @del };
131 delete @history_n { @del };
132 delete @history_nn { @del };
138 return unless $nickref ;
139 return unless $dest && defined $dest ->{ target
};
140 return unless $dest ->{ level
} & MSGLEVEL_PUBLIC
;
141 return if $ignore_hilights && $dest ->{ level
} & MSGLEVEL_HILIGHT
;
144 my $view = $win -> view ;
145 my $line_id = $view ->{ buffer
}{ _irssi
} . ',' . $view ->{ buffer
}{ cur_line
}{ _irssi
};
146 $chan_reg { $chanref ->{ _irssi
} } = $chanref ;
147 $nick_reg { $nickref ->{ _irssi
} } = $nickref ;
148 if ( exists $history_w { $line_id }) {
150 $history_w { $line_id } = $win ->{ _irssi
};
151 $history_c { $line_id } = $chanref ->{ _irssi
};
152 $history_n { $line_id } = $nickref ->{ _irssi
};
153 $history_nn { $line_id } = $nickref ->{ nick
};
154 push @{ $history_st { $chanref ->{ _irssi
} }}, $line_id ;
156 my @lost_forever = grep { $view ->{ buffer
}{ first_line
}{ info
}{ time } > $lost_nicks { $chanref ->{ _irssi
} }{ $_ } }
157 keys %{ $lost_nicks { $chanref ->{ _irssi
} }};
158 delete @{ $lost_nicks { $chanref ->{ _irssi
} }}{ @lost_forever };
159 delete @{ $lost_nicks_fs { $chanref ->{ _irssi
} }}{ @lost_forever };
160 delete @{ $lost_nicks_fc { $chanref ->{ _irssi
} }}{ @lost_forever };
161 delete @{ $lost_nicks_bc { $chanref ->{ _irssi
} }}{ @lost_forever };
162 delete @{ $lost_nicks_bs { $chanref ->{ _irssi
} }}{ @lost_forever };
168 for my $ch ( keys %history_st ) {
169 @{ $history_st { $ch }} = grep { exists $history_w { $_ } &&
170 $history_w { $_ } != $win ->{ _irssi
} } @{ $history_st { $ch }};
172 my @del = grep { $history_w { $_ } == $win ->{ _irssi
} } keys %history_w ;
173 delete @history_w { @del };
174 delete @history_c { @del };
175 delete @history_n { @del };
176 delete @history_nn { @del };
181 my ( $chan , $check_lr , $ad ) = @_ ;
182 my $win = $chan -> window ;
183 return unless ref $win ;
184 my $view = $win -> view ;
185 my $count = $history_lines ;
186 my $buffer_id = $view ->{ buffer
}{ _irssi
} . ',' ;
187 my $lp = $view ->{ buffer
}{ cur_line
};
188 my %check_lr = map { $_ => undef } @$check_lr ;
190 my $bottom = $view ->{ bottom
};
191 while ( $lp && $count ) {
192 my $line_id = $buffer_id . $lp ->{ _irssi
};
193 if ( exists $check_lr { $line_id }) {
194 $lp = _alter_line
( $buffer_id , $line_id , $win , $view , $lp , $chan ->{ _irssi
}, $ad );
205 $win -> command ( '^scrollback end' ) if $bottom && ! $win -> view ->{ bottom
};
210 my $irssi_mumbo = qr/\cD[`-i]|\cD[&-@\xff]./ ;
211 my $irssi_mumbo_no_partial = qr/(?<!\cD)(?<!\cD[&-@\xff])/ ;
212 my $irssi_skip_form_re = qr/((?:$irssi_mumbo|[.,*@%+&!#$()=~'";:?\/ ><]+(?= $irssi_mumbo | \s
))+| \s
+)/;
215 my $win = Irssi
:: active_win
;
216 my $view = $win -> view ;
217 my $lp = $view ->{ buffer
}{ cur_line
};
218 my $count = $history_lines ;
219 my $buffer_id = $view ->{ buffer
}{ _irssi
} . ',' ;
220 while ( $lp && $count ) {
221 my $line_id = $buffer_id . $lp ->{ _irssi
};
222 if ( exists $history_w { $line_id }) {
223 my $line_nick = $history_nn { $line_id };
224 my $text = $lp -> get_text ( 1 );
227 for ( my $i = 0 ; $i < $skip_forms ; ++ $i ) {
229 scalar $text =~ /$irssi_skip_form_re/g ;
233 for ( my $i = 0 ; $i < $search_forms_max ; ++ $i ) {
235 scalar $text =~ /$irssi_skip_form_re/g ;
238 my $pre = substr $text , 0 , $from ;
239 my $search = substr $text , $from , $to - $from ;
240 my $post = substr $text , $to ;
241 unless ( $to > $from ) {
244 unshift @nick_reg , quotemeta substr $line_nick , 0 , $_ for 1 .. length $line_nick ;
245 no warnings
'uninitialized' ;
246 for my $nick_reg ( @nick_reg ) {
248 =~ s/(\Q$color_code[0]\E\s*)?((?:$irssi_mumbo)+)?$irssi_mumbo_no_partial($nick_reg)((?:$irssi_mumbo)+)?(\s*\Q$color_code[0]\E)?/<match>$1$2<nick>$3<\/ nick
> $4$5 < \
/match>/ ;
250 =~ s/(?:\Q$color_code[0]\E)?(?:(?:$irssi_mumbo)+?)?$irssi_mumbo_no_partial($nick_reg)(?:(?:$irssi_mumbo)+?)?(?:\Q$color_code[1]\E)?/<nick>$1<\/ nick
>/;
253 my $msg = " $pre <search> $search </search> $post " ;
254 #$msg =~ s/([^[:print:]])/sprintf '\\x%02x', ord $1/ge;
255 $msg =~ s/\cDe/%|/g ; $msg =~ s/%/%%/g ;
256 $win -> print ( setc
. " form debug: [ $msg ]" , MSGLEVEL_CLIENTCRAP
);
263 $win -> print ( setc
. " form debug: no usable line found" , MSGLEVEL_CLIENTCRAP
);
267 my ( $buffer_id , $lrp , $win , $view , $lp , $cid , $ad ) = @_ ;
268 my $line_nick = $history_nn { $lrp };
269 my $text = $lp -> get_text ( 1 );
272 for ( my $i = 0 ; $i < $skip_forms ; ++ $i ) {
274 scalar $text =~ /$irssi_skip_form_re/g ;
278 for ( my $i = 0 ; $i < $search_forms_max ; ++ $i ) {
280 scalar $text =~ /$irssi_skip_form_re/g ;
283 return $lp unless $to > $from ;
285 unshift @nick_reg , quotemeta substr $line_nick , 0 , $_ for 1 .. length $line_nick ;
286 { no warnings
'uninitialized' ;
288 if ( exists $lost_nicks_fs { $cid }{ $line_nick }) {
289 my ( $fs , $fc , $bc , $bs ) = ( $lost_nicks_fs { $cid }{ $line_nick }, $lost_nicks_fc { $cid }{ $line_nick }, $lost_nicks_bc { $cid }{ $line_nick }, $lost_nicks_bs { $cid }{ $line_nick });
290 my $sen = length $bs ? $color_code [ 0 ] : '' ;
291 for my $nick_reg ( @nick_reg ) {
293 ( substr $text , $from , $to - $from )
294 =~ s/(?:\Q$color_code[0]\E)?(?:(?:$irssi_mumbo)+?)?$irssi_mumbo_no_partial($nick_reg)(?:(?:$irssi_mumbo)+?)?(?:\Q$color_code[1]\E)?/$fc$1$bc$sen/ ;
299 for my $nick_reg ( @nick_reg ) {
301 ( substr $text , $from , $to - $from )
302 =~ s/(\Q$color_code[0]\E\s*)?((?:$irssi_mumbo)+)?$irssi_mumbo_no_partial($nick_reg)((?:$irssi_mumbo)+)?(\s*\Q$color_code[0]\E)?/$1$2$color_code[0]$3$color_code[1]$4$5/ ) {
303 $lost_nicks_fs { $cid }{ $line_nick } = $1 ;
304 $lost_nicks_fc { $cid }{ $line_nick } = $2 ;
305 $lost_nicks_bc { $cid }{ $line_nick } = $4 ;
306 $lost_nicks_bs { $cid }{ $line_nick } = $5 ;
311 $win -> gui_printtext_after ( $lp -> prev , $lp ->{ info
}{ level
} | MSGLEVEL_NEVER
, " $text \n " , $lp ->{ info
}{ time });
312 my $ll = $win -> last_line_insert ;
313 my $line_id = $buffer_id . $ll ->{ _irssi
};
314 if ( exists $history_w { $line_id }) {
316 grep { $_ eq $lrp and $_ = $line_id } @{ $history_st { $cid }};
317 $history_w { $line_id } = delete $history_w { $lrp };
318 $history_c { $line_id } = delete $history_c { $lrp };
319 $history_n { $line_id } = delete $history_n { $lrp };
320 $history_nn { $line_id } = delete $history_nn { $lrp };
321 $view -> remove_line ( $lp );
326 my ( $chan , $nick ) = @_ ;
327 if ( delete $lost_nicks { $chan ->{ _irssi
} }{ $nick ->{ nick
} }) {
328 my @check_lr = grep { $history_c { $_ } == $chan ->{ _irssi
} &&
329 $history_n { $_ } eq $nick ->{ nick
} } keys %history_w ;
331 $nick_reg { $nick ->{ _irssi
} } = $nick ;
332 for my $li ( @check_lr ) {
333 $history_n { $li } = $nick ->{ _irssi
};
335 _alter_lines
( $chan , \
@check_lr , 1 );
338 delete $lost_nicks_fs { $chan ->{ _irssi
} }{ $nick ->{ nick
} };
339 delete $lost_nicks_fc { $chan ->{ _irssi
} }{ $nick ->{ nick
} };
340 delete $lost_nicks_bc { $chan ->{ _irssi
} }{ $nick ->{ nick
} };
341 delete $lost_nicks_bs { $chan ->{ _irssi
} }{ $nick ->{ nick
} };
346 my ( $chan , $nick ) = @_ ;
347 my @check_lr = grep { $history_n { $_ } eq $nick ->{ _irssi
} } keys %history_w ;
348 for my $li ( @check_lr ) {
349 $history_n { $li } = $nick ->{ nick
};
352 $lost_nicks { $chan ->{ _irssi
} }{ $nick ->{ nick
} } = time ;
353 _alter_lines
( $chan , \
@check_lr , 0 );
355 delete $nick_reg { $nick ->{ _irssi
} };
360 my ( $chan , $nick , $oldnick ) = @_ ;
361 nick_add
( $chan , $nick );
366 if ( my $del = delete $history_st { $chan ->{ _irssi
} }) {
367 delete @history_w { @$del };
368 delete @history_c { @$del };
369 delete @history_n { @$del };
370 delete @history_nn { @$del };
372 delete $chan_reg { $chan ->{ _irssi
} };
373 delete $lost_nicks { $chan ->{ _irssi
}};
374 delete $lost_nicks_fs { $chan ->{ _irssi
}};
375 delete $lost_nicks_fc { $chan ->{ _irssi
}};
376 delete $lost_nicks_bc { $chan ->{ _irssi
}};
377 delete $lost_nicks_bs { $chan ->{ _irssi
}};
381 Irssi
:: settings_add_int
( setc
, set
'history_lines' , $history_lines );
382 Irssi
:: settings_add_bool
( setc
, set
'ignore_hilights' , $ignore_hilights );
383 Irssi
:: signal_add_last
({
384 'setup changed' => 'setup_changed' ,
387 'print text' => 'prt_text_issue' ,
388 'gui print text finished' => 'prt_text_ref' ,
389 'nicklist new' => 'nick_add' ,
390 'nicklist changed' => 'nick_change' ,
391 'nicklist remove' => 'nick_del' ,
392 'window destroyed' => 'win_del' ,
393 'message public' => 'msg_line_tag' ,
394 'channel destroyed' => 'chan_del' ,
398 my $win = Irssi
:: active_win
;
399 my $view = $win -> view ;
400 my $buffer_id = $view ->{ buffer
}{ _irssi
} . ',' ;
401 for ( my $lp = $view ->{ buffer
}{ first_line
}; $lp ; $lp = $lp -> next ) {
402 my $line_id = $buffer_id . $lp ->{ _irssi
};
403 if ( exists $history_w { $line_id }) {
404 my $k = $history_c { $line_id };
405 my $kn = $history_n { $line_id };
406 if ( exists $chan_reg { $k }) {
408 if ( exists $nick_reg { $kn }) {
410 if ( exists $lost_nicks { $k } && exists $lost_nicks { $k }{ $kn }) {
415 Irssi
:: settings_add_str
( setc
, set
'color' , $color_letter );
416 Irssi
:: settings_add_int
( setc
, set
'forms_skip' , $skip_forms );
417 Irssi
:: settings_add_int
( setc
, set
'forms_search_max' , $search_forms_max );
421 { package Irssi
:: Nick
}
426 # - optionally ignore hilighted lines
428 # - fix useless re-reading of settings colour
430 # - fix crash on some lines reported by pierrot