From 6839be2ccdb9cd97cfc2131cdcadda3123a5ad13 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Sun, 12 Feb 2017 10:19:02 +0100 Subject: Initial checkin of ctrlact script Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 510 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 scripts/ctrlact.pl (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl new file mode 100644 index 0000000..5bc807e --- /dev/null +++ b/scripts/ctrlact.pl @@ -0,0 +1,510 @@ +# ctrlact.pl — Irssi script for fine-grained control of activity indication +# +# © 2017 martin f. krafft +# Released under the MIT licence. +# +### Usage: +# +# /script load ctrlact +# +# If you like a busy activity statusbar, this script is not for you. +# +# If, on the other hand, you don't care about most activity, but you do want +# the ability to define per-item and per-window, what level of activity should +# trigger a change in the statusbar, then ctrlact might be for you. +# +# For instance, you might never want to be disturbed by activity in any +# channel, unless someone highlights you. However, you do want all activity +# in queries, as well as an indication about any chatter in your company +# channels. The following ctrlact map would do this for you: +# +# channel /^#myco-/ messages +# channel * hilights +# query * all +# +# These three lines would be interpreted/read as: +# "only messages or higher in a channel matching /^#myco-/ should trigger act" +# "in all other channels, only hilights (or higher) should trigger act" +# "messages of all levels should trigger act in queries" +# +# The activity level in the third column is thus to be interpreted as +# "the minimum level of activity that will trigger an indication" +# +# Loading this script per-se should not change anything, except it will create +# ~/.irssi/ctrlact with some informational content, including the defaults and +# some examples. +# +# The four activity levels are, and you can use either the words, or the +# integers in the map. +# +# all (data_level: 1) +# messages (data_level: 2) +# hilights (data_level: 3) +# none (data_level: 4) +# +# Note that the name is either matched in full and verbatim, or treated like +# a regular expression, if it starts and ends with the same punctuation +# character. The asterisk ('*') is special and simply gets translated to /.*/ +# internally. No other wildcards are supported. +# +# Once you defined your mappings, please don't forget to /ctrlact reload them. +# You can then use the following commands from Irssi to check out the result: +# +# # list all mappings +# /ctrlact list +# +# # query the applicable activity levels, possibly limited to +# # windows/channels/queries +# /ctrlact query name [name, …] [-window|-channel|-query] +# +# # display the applicable level for each window/channel/query +# /ctrlact show [-window|-channel|-query] +# +# There's an interplay between window items and windows here, and you can +# specify mininum activity levels for each. Here are the rules: +# +# 1. if the minimum activity level of a window item (channel or query) is not +# reached, then the window is prevented from indicating activity. +# 2. if traffic in a window item does reach minimum activity level, then the +# minimum activity level of the window is considered, and activity is only +# indicated if the window's minimum activity level is lower. +# +# In general, this means you'd have windows defaulting to 'all', but it might +# come in handy to move window items to windows with min.levels of 'hilights' +# or even 'none' in certain cases, to further limit activity indication for +# them. +# +# You can use the Irssi settings activity_msg_level and activity_hilight_level +# to specify which IRC levels will be considered messages and hilights. Note +# that if an activity indication is inhibited, then there also won't be +# a beep (cf. beep_msg_level). +# +### Settings: +# +# /set ctrlact_map_file [~/.irssi/ctrlact] +# Controls where the activity control map will be read from (and saved to) +# +# /set ctrlact_fallback_(channel|query|window)_threshold [1] +# Controls the lowest data level that will trigger activity for channels, +# queries, and windows respectively, if no applicable mapping could be +# found. +# +# /set ctrlact_debug [off] +# Turns on debug output. Not that this may itself be buggy, so please don't +# use it unless you really need it. +# +### To-do: +# +# - figure out interplay with activity_hide_level +# - /ctrlact add/delete/move and /ctrlact save, maybe +# - ability to add a server tag to an item name to make matches more specific +# - make beep inhibition configurable +# - completion for commands +# +use strict; +use warnings; +use Irssi; +use Text::ParseWords; + +our $VERSION = '1.0'; + +our %IRSSI = ( + authors => 'martin f. krafft', + contact => 'madduck@madduck.net', + name => 'ctrlact', + description => 'allows per-channel control over activity indication', + license => 'MIT', + changed => '2017-02-12' +); + +### DEFAULTS AND SETTINGS ###################################################### + +my $debug = 0; +my $map_file = Irssi::get_irssi_dir()."/ctrlact"; +my $fallback_channel_threshold = 1; +my $fallback_query_threshold = 1; +my $fallback_window_threshold = 1; + +Irssi::settings_add_str('ctrlact', 'ctrlact_map_file', $map_file); +Irssi::settings_add_bool('ctrlact', 'ctrlact_debug', $debug); +Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_channel_threshold', $fallback_channel_threshold); +Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_query_threshold', $fallback_query_threshold); +Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_window_threshold', $fallback_window_threshold); + +sub sig_setup_changed { + $debug = Irssi::settings_get_bool('ctrlact_debug'); + $map_file = Irssi::settings_get_str('ctrlact_map_file'); + $fallback_channel_threshold = Irssi::settings_get_int('ctrlact_fallback_channel_threshold'); + $fallback_query_threshold = Irssi::settings_get_int('ctrlact_fallback_query_threshold'); + $fallback_window_threshold = Irssi::settings_get_int('ctrlact_fallback_window_threshold'); +} +Irssi::signal_add('setup changed', \&sig_setup_changed); +sig_setup_changed(); + +my $changed_since_last_save = 0; + +my @DATALEVEL_KEYWORDS = ('all', 'messages', 'hilights', 'none'); + +### HELPERS #################################################################### + +my $_inhibit_debug_activity = 0; +sub debugprint { + return unless $debug; + my ($msg, @rest) = @_; + $_inhibit_debug_activity = 1; + Irssi::print("ctrlact debug: ".$msg); + $_inhibit_debug_activity = 0; +} + +sub error { + my ($msg) = @_; + Irssi::print("ctrlact: ERROR: $msg", MSGLEVEL_CLIENTERROR); +} + +my @window_thresholds; +my @channel_thresholds; +my @query_thresholds; + +sub match { + my ($pat, $text) = @_; + my $npat = ($pat eq '*') ? '/.*/' : $pat; + if ($npat =~ m/^(\W)(.+)\1$/) { + my $re = qr/$2/; + $pat = $2 unless $pat eq '*'; + return $pat if $text =~ /$re/i; + } + else { + return $pat if lc($text) eq lc($npat); + } + return 0; +} + +sub to_data_level { + my ($kw) = @_; + return $1 if $kw =~ m/^(\d+)$/; + foreach my $i (2..4) { + my $matcher = qr/^$DATALEVEL_KEYWORDS[5-$i]$/; + return 6-$i if $kw =~ m/$matcher/i; + } + return 1; +} + +sub from_data_level { + my ($dl) = @_; + die "Invalid numeric data level: $dl" unless $dl =~ m/^([1-4])$/; + return $DATALEVEL_KEYWORDS[$dl-1]; +} + +sub walk_match_array { + my ($name, $type, @arr) = @_; + foreach my $pair (@arr) { + my $match = match($pair->[0], $name); + next unless $match; + my $result = to_data_level($pair->[1]); + my $tresult = from_data_level($result); + $name = '(unnamed)' unless length $name; + debugprint("$name ($type) matches '$match' → '$tresult' ($result)"); + return $result + } + return -1; +} + +sub get_mappings_table { + my (@arr) = @_; + my @ret = (); + for (my $i = 0; $i < @arr; $i++) { + push @ret, sprintf("%4d: %-40s %-10s", $i, $arr[$i]->[0], $arr[$i]->[1]); + } + return join("\n", @ret); +} + +sub get_specific_threshold { + my ($type, $name) = @_; + $type = lc($type); + if ($type eq 'window') { + return walk_match_array($name, $type, @window_thresholds); + } + elsif ($type eq 'channel') { + return walk_match_array($name, $type, @channel_thresholds); + } + elsif ($type eq 'query') { + return walk_match_array($name, $type, @query_thresholds); + } + else { + die "ctrlact: can't look up threshold for type: $type"; + } +} + +sub get_item_threshold { + my ($chattype, $type, $name) = @_; + my $ret = get_specific_threshold($type, $name); + return $ret if $ret > 0; + return ($type eq 'CHANNEL') ? $fallback_channel_threshold : $fallback_query_threshold; +} + +sub get_win_threshold { + my ($name) = @_; + my $ret = get_specific_threshold('window', $name); + return ($ret > 0) ? $ret : $fallback_window_threshold; +} + +sub print_levels_for_all { + my ($type, @arr) = @_; + Irssi::print("ctrlact: $type mappings:"); + for (my $i = 0; $i < @arr; $i++) { + my $name = $arr[$i]->{'name'}; + my $t = get_specific_threshold($type, $name); + my $c = ($type eq 'window') ? $arr[$i]->{'refnum'} : $i; + printf CLIENTCRAP "%4d: %-40s → %d (%s)", $c, $name, $t, from_data_level($t); + } +} + +### HILIGHT SIGNAL HANDLERS #################################################### + +my $_inhibit_bell = 0; +my $_inhibit_window = 0; + +sub maybe_inhibit_witem_hilight { + my ($witem, $oldlevel) = @_; + return unless $witem; + $oldlevel = 0 unless $oldlevel; + my $newlevel = $witem->{'data_level'}; + return if ($newlevel <= $oldlevel); + + $_inhibit_window = 0; + $_inhibit_bell = 0; + my $wichattype = $witem->{'chat_type'}; + my $witype = $witem->{'type'}; + my $winame = $witem->{'name'}; + my $threshold = get_item_threshold($wichattype, $witype, $winame); + my $inhibit = $newlevel > 0 && $newlevel < $threshold; + debugprint("$winame: witem $wichattype:$witype:\"$winame\" $oldlevel → $newlevel (".($inhibit ? "< $threshold, inhibit" : ">= $threshold, pass").')'); + if ($inhibit) { + Irssi::signal_stop(); + $_inhibit_bell = 1; + $_inhibit_window = $witem->window(); + } +} +Irssi::signal_add_first('window item hilight', \&maybe_inhibit_witem_hilight); + +sub inhibit_win_hilight { + my ($win) = @_; + Irssi::signal_stop(); + Irssi::signal_emit('window dehilight', $win); +} + +sub maybe_inhibit_win_hilight { + my ($win, $oldlevel) = @_; + return unless $win; + if ($_inhibit_debug_activity) { + inhibit_win_hilight($win); + } + elsif ($_inhibit_window && $win->{'refnum'} == $_inhibit_window->{'refnum'}) { + inhibit_win_hilight($win); + } + else { + $oldlevel = 0 unless $oldlevel; + my $newlevel = $win->{'data_level'}; + return if ($newlevel <= $oldlevel); + + my $wname = $win->{'name'}; + my $threshold = get_win_threshold($wname); + my $inhibit = $newlevel > 0 && $newlevel < $threshold; + debugprint(($wname?$wname:'(unnamed)').": window \"$wname\" $oldlevel → $newlevel (".($inhibit ? "< $threshold, inhibit" : ">= $threshold, pass").')'); + inhibit_win_hilight($win) if $inhibit; + } +} +Irssi::signal_add_first('window hilight', \&maybe_inhibit_win_hilight); + +sub maybe_inhibit_beep { + Irssi::signal_stop() if $_inhibit_bell; +} +Irssi::signal_add_first('beep', \&maybe_inhibit_beep); + +### SAVING AND LOADING ######################################################### + +sub get_mappings_fh { + my ($filename) = @_; + my $fh; + if (-e $filename) { + open($fh, $filename) || die "Cannot open mappings file: $!"; + } + else { + open($fh, "+>$filename") || die "Cannot create mappings file: $!"; + + my $ftw = from_data_level($fallback_window_threshold); + my $ftc = from_data_level($fallback_channel_threshold); + my $ftq = from_data_level($fallback_query_threshold); + print $fh <<"EOF"; +# ctrlact mappings file (version:$VERSION) +# +# type: window, channel, query +# name: full name to match, /regexp/, or * (for all) +# min.level: none, messages, hilights, all, or 1,2,3,4 +# +# type name min.level + + +# EXAMPLES +# +### only indicate activity in the status window if messages were displayed: +# window (status) messages +# +### never ever indicate activity for any item bound to this window: +# window oubliette none +# +### indicate activity on all messages in debian-related channels: +# channel /^#debian/ messages +# +### display any text (incl. joins etc.) for the '#madduck' channel: +# channel #madduck all +# +### otherwise ignore everything in channels, unless a hilight is triggered: +# channel * hilights +# +### make somebot only get your attention if they hilight you: +# query somebot hilights +# +### otherwise we want to see everything in queries: +# query * all + +# DEFAULTS: +# window * $ftw +# channel * $ftc +# query * $ftq + +# vim:noet:tw=0:ts=16 +EOF + Irssi::print("ctrlact: created new/empty mappings file: $filename"); + } + return $fh; +} + +sub load_mappings { + my ($filename) = @_; + @window_thresholds = @channel_thresholds = @query_thresholds = (); + my $fh = get_mappings_fh($filename); + while (<$fh>) { + next if m/^\s*(?:#|$)/; + m/^\s*(\S+)\s+(\S+)\s+(\S+)\s*$/; + push @window_thresholds, [$2, $3] if match($1, 'window'); + push @channel_thresholds, [$2, $3] if match($1, 'channel'); + push @query_thresholds, [$2, $3] if match($1, 'query'); + } + close($fh) || die "Cannot close mappings file: $!"; +} + +sub cmd_load { + Irssi::print("ctrlact: loading mappings from $map_file"); + load_mappings($map_file); + $changed_since_last_save = 0; +} + +sub cmd_save { + error("saving not yet implemented"); + return 1; +} + +sub cmd_list { + Irssi::print("ctrlact: window mappings"); + print CLIENTCRAP get_mappings_table(@window_thresholds); + Irssi::print("ctrlact: channel mappings"); + print CLIENTCRAP get_mappings_table(@channel_thresholds); + Irssi::print("ctrlact: query mappings"); + print CLIENTCRAP get_mappings_table(@query_thresholds); +} + +sub parse_args { + my (@args) = @_; + my @words = (); + my $typewasset = 0; + my $max = 0; + my $type = undef; + foreach my $arg (@args) { + if ($arg =~ m/^-(windows?|channels?|quer(?:ys?|ies))/) { + if ($typewasset) { + error("can't specify -$1 after -$type"); + return 1; + } + $type = 'window' if $1 =~ m/^w/; + $type = 'channel' if $1 =~ m/^c/; + $type = 'query' if $1 =~ m/^q/; + $typewasset = 1 + } + elsif ($arg =~ m/^-/) { + error("Unknown argument: $arg"); + } + else { + push @words, $arg; + $max = length $arg if length $arg > $max; + } + } + return ($type, $max, @words); +} + +sub cmd_query { + my ($data, $server, $item) = @_; + my @args = shellwords($data); + my ($type, $max, @words) = parse_args(@args); + $type = $type // 'channel'; + foreach my $word (@words) { + my $t = get_specific_threshold($type, $word); + printf CLIENTCRAP "ctrlact $type map: %*s → %d (%s)", $max, $word, $t, from_data_level($t); + } +} + +sub cmd_show { + my ($data, $server, $item) = @_; + my @args = shellwords($data); + my ($type, $max, @words) = parse_args(@args); + $type = $type // 'all'; + + if ($type eq 'channel' or $type eq 'all') { + print_levels_for_all('channel', Irssi::channels()); + } + if ($type eq 'query' or $type eq 'all') { + print_levels_for_all('query', Irssi::queries()); + } + if ($type eq 'window' or $type eq 'all') { + print_levels_for_all('window', Irssi::windows()); + } +} + +sub autosave { + cmd_save() if ($changed_since_last_save); +} + +sub UNLOAD { + autosave(); +} + +Irssi::signal_add('setup saved', \&autosave); + +Irssi::command_bind('ctrlact help',\&cmd_help); +Irssi::command_bind('ctrlact reload',\&cmd_load); +Irssi::command_bind('ctrlact load',\&cmd_load); +Irssi::command_bind('ctrlact save',\&cmd_save); +Irssi::command_bind('ctrlact list',\&cmd_list); +Irssi::command_bind('ctrlact query',\&cmd_query); +Irssi::command_bind('ctrlact show',\&cmd_show); + +Irssi::command_bind('ctrlact' => sub { + my ( $data, $server, $item ) = @_; + $data =~ s/\s+$//g; + if ($data) { + Irssi::command_runsub('ctrlact', $data, $server, $item); + } + else { + cmd_help(); + } + } +); +Irssi::command_bind('help', sub { + $_[0] =~ s/\s+$//g; + return unless $_[0] eq 'ctrlact'; + cmd_help(); + Irssi::signal_stop(); + } +); + +cmd_load(); -- cgit v1.2.3 From f874b2743ec6455d9ccb6d17f219d8041e1c5d10 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Mon, 13 Feb 2017 08:14:12 +0100 Subject: Make inhibiting the beep configurable Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 5bc807e..0e471d0 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -77,7 +77,7 @@ # You can use the Irssi settings activity_msg_level and activity_hilight_level # to specify which IRC levels will be considered messages and hilights. Note # that if an activity indication is inhibited, then there also won't be -# a beep (cf. beep_msg_level). +# a beep (cf. beep_msg_level), unless you toggle ctrlmap_inhibit_beep. # ### Settings: # @@ -89,6 +89,10 @@ # queries, and windows respectively, if no applicable mapping could be # found. # +# /set ctrlact_inhibit_beep [on] +# If an activity wouldn't be indicated, also inhibit the beep/bell. Turn +# this off if you want the bell anyway. +# # /set ctrlact_debug [off] # Turns on debug output. Not that this may itself be buggy, so please don't # use it unless you really need it. @@ -98,7 +102,6 @@ # - figure out interplay with activity_hide_level # - /ctrlact add/delete/move and /ctrlact save, maybe # - ability to add a server tag to an item name to make matches more specific -# - make beep inhibition configurable # - completion for commands # use strict; @@ -124,12 +127,14 @@ my $map_file = Irssi::get_irssi_dir()."/ctrlact"; my $fallback_channel_threshold = 1; my $fallback_query_threshold = 1; my $fallback_window_threshold = 1; +my $inhibit_beep = 1; Irssi::settings_add_str('ctrlact', 'ctrlact_map_file', $map_file); Irssi::settings_add_bool('ctrlact', 'ctrlact_debug', $debug); Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_channel_threshold', $fallback_channel_threshold); Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_query_threshold', $fallback_query_threshold); Irssi::settings_add_int('ctrlact', 'ctrlact_fallback_window_threshold', $fallback_window_threshold); +Irssi::settings_add_bool('ctrlact', 'ctrlact_inhibit_beep', $inhibit_beep); sub sig_setup_changed { $debug = Irssi::settings_get_bool('ctrlact_debug'); @@ -137,6 +142,7 @@ sub sig_setup_changed { $fallback_channel_threshold = Irssi::settings_get_int('ctrlact_fallback_channel_threshold'); $fallback_query_threshold = Irssi::settings_get_int('ctrlact_fallback_query_threshold'); $fallback_window_threshold = Irssi::settings_get_int('ctrlact_fallback_window_threshold'); + $inhibit_beep = Irssi::settings_get_bool('ctrlact_inhibit_beep'); } Irssi::signal_add('setup changed', \&sig_setup_changed); sig_setup_changed(); @@ -261,7 +267,7 @@ sub print_levels_for_all { ### HILIGHT SIGNAL HANDLERS #################################################### -my $_inhibit_bell = 0; +my $_inhibit_beep = 0; my $_inhibit_window = 0; sub maybe_inhibit_witem_hilight { @@ -272,7 +278,7 @@ sub maybe_inhibit_witem_hilight { return if ($newlevel <= $oldlevel); $_inhibit_window = 0; - $_inhibit_bell = 0; + $_inhibit_beep = 0; my $wichattype = $witem->{'chat_type'}; my $witype = $witem->{'type'}; my $winame = $witem->{'name'}; @@ -281,7 +287,9 @@ sub maybe_inhibit_witem_hilight { debugprint("$winame: witem $wichattype:$witype:\"$winame\" $oldlevel → $newlevel (".($inhibit ? "< $threshold, inhibit" : ">= $threshold, pass").')'); if ($inhibit) { Irssi::signal_stop(); - $_inhibit_bell = 1; + # the rhval comes from config, so if the user doesn't want the + # bell inhibited, this is effectively a noop. + $_inhibit_beep = $inhibit_beep; $_inhibit_window = $witem->window(); } } @@ -317,7 +325,7 @@ sub maybe_inhibit_win_hilight { Irssi::signal_add_first('window hilight', \&maybe_inhibit_win_hilight); sub maybe_inhibit_beep { - Irssi::signal_stop() if $_inhibit_bell; + Irssi::signal_stop() if $_inhibit_beep; } Irssi::signal_add_first('beep', \&maybe_inhibit_beep); -- cgit v1.2.3 From 98c69f9c50bda34342f3ea6ff0b5aae1f7dad2ac Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Mon, 13 Feb 2017 08:57:36 +0100 Subject: React to setup reread signal Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 0e471d0..2756244 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -145,6 +145,7 @@ sub sig_setup_changed { $inhibit_beep = Irssi::settings_get_bool('ctrlact_inhibit_beep'); } Irssi::signal_add('setup changed', \&sig_setup_changed); +Irssi::signal_add('setup reread', \&sig_setup_changed); sig_setup_changed(); my $changed_since_last_save = 0; @@ -487,6 +488,7 @@ sub UNLOAD { } Irssi::signal_add('setup saved', \&autosave); +Irssi::signal_add('setup reread', \&cmd_load); Irssi::command_bind('ctrlact help',\&cmd_help); Irssi::command_bind('ctrlact reload',\&cmd_load); -- cgit v1.2.3 From 1dacfd9fac96f478f31d6f54f252dae968064871 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Mon, 13 Feb 2017 11:11:14 +0100 Subject: Single-line debug output Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 2756244..b7e694c 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -155,6 +155,7 @@ my @DATALEVEL_KEYWORDS = ('all', 'messages', 'hilights', 'none'); ### HELPERS #################################################################### my $_inhibit_debug_activity = 0; +use constant DEBUGEVENTFORMAT => "%7s %-22.22s %d %s %d → %-7s (%-8s ← %s)"; sub debugprint { return unless $debug; my ($msg, @rest) = @_; @@ -210,8 +211,7 @@ sub walk_match_array { my $result = to_data_level($pair->[1]); my $tresult = from_data_level($result); $name = '(unnamed)' unless length $name; - debugprint("$name ($type) matches '$match' → '$tresult' ($result)"); - return $result + return ($result, $tresult, $match) } return -1; } @@ -244,15 +244,25 @@ sub get_specific_threshold { sub get_item_threshold { my ($chattype, $type, $name) = @_; - my $ret = get_specific_threshold($type, $name); - return $ret if $ret > 0; - return ($type eq 'CHANNEL') ? $fallback_channel_threshold : $fallback_query_threshold; + my ($ret, $tret, $match) = get_specific_threshold($type, $name); + return ($ret, $tret, $match) if $ret > 0; + if ($type eq 'CHANNEL') { + return ($fallback_channel_threshold, from_data_level($fallback_channel_threshold), '[default]'); + } + else { + return ($fallback_query_threshold, from_data_level($fallback_query_threshold), '[default]'); + } } sub get_win_threshold { my ($name) = @_; - my $ret = get_specific_threshold('window', $name); - return ($ret > 0) ? $ret : $fallback_window_threshold; + my ($ret, $tret, $match) = get_specific_threshold('window', $name); + if ($ret > 0) { + return ($ret, $tret, $match); + } + else { + return ($fallback_window_threshold, from_data_level($fallback_window_threshold), '[default]'); + } } sub print_levels_for_all { @@ -260,9 +270,9 @@ sub print_levels_for_all { Irssi::print("ctrlact: $type mappings:"); for (my $i = 0; $i < @arr; $i++) { my $name = $arr[$i]->{'name'}; - my $t = get_specific_threshold($type, $name); + my ($t, $tt, $match) = get_specific_threshold($type, $name); my $c = ($type eq 'window') ? $arr[$i]->{'refnum'} : $i; - printf CLIENTCRAP "%4d: %-40s → %d (%s)", $c, $name, $t, from_data_level($t); + printf CLIENTCRAP "%4d: %-40s → %d (%s; match:%s)", $c, $name, $t, $tt, $match; } } @@ -283,9 +293,11 @@ sub maybe_inhibit_witem_hilight { my $wichattype = $witem->{'chat_type'}; my $witype = $witem->{'type'}; my $winame = $witem->{'name'}; - my $threshold = get_item_threshold($wichattype, $witype, $winame); - my $inhibit = $newlevel > 0 && $newlevel < $threshold; - debugprint("$winame: witem $wichattype:$witype:\"$winame\" $oldlevel → $newlevel (".($inhibit ? "< $threshold, inhibit" : ">= $threshold, pass").')'); + my ($th, $tth, $match) = get_item_threshold($wichattype, $witype, $winame); + my $inhibit = $newlevel > 0 && $newlevel < $th; + debugprint(sprintf(DEBUGEVENTFORMAT, lc($witype), $winame, $newlevel, + $inhibit ? ('<',$th,'inhibit'):('≥',$th,'pass'), + $tth, $match)); if ($inhibit) { Irssi::signal_stop(); # the rhval comes from config, so if the user doesn't want the @@ -317,9 +329,12 @@ sub maybe_inhibit_win_hilight { return if ($newlevel <= $oldlevel); my $wname = $win->{'name'}; - my $threshold = get_win_threshold($wname); - my $inhibit = $newlevel > 0 && $newlevel < $threshold; - debugprint(($wname?$wname:'(unnamed)').": window \"$wname\" $oldlevel → $newlevel (".($inhibit ? "< $threshold, inhibit" : ">= $threshold, pass").')'); + my ($th, $tth, $match) = get_win_threshold($wname); + my $inhibit = $newlevel > 0 && $newlevel < $th; + debugprint(sprintf(DEBUGEVENTFORMAT, 'window', + $wname?$wname:'(unnamed)', $newlevel, + $inhibit ? ('<',$th,'inhibit'):('≥',$th,'pass'), + $tth, $match)); inhibit_win_hilight($win) if $inhibit; } } @@ -457,8 +472,8 @@ sub cmd_query { my ($type, $max, @words) = parse_args(@args); $type = $type // 'channel'; foreach my $word (@words) { - my $t = get_specific_threshold($type, $word); - printf CLIENTCRAP "ctrlact $type map: %*s → %d (%s)", $max, $word, $t, from_data_level($t); + my ($t, $tt, $match) = get_specific_threshold($type, $word); + printf CLIENTCRAP "ctrlact $type map: %*s → %d (%s, match:%s)", $max, $word, $t, $tt, $match; } } -- cgit v1.2.3 From 4f9d8b3e4e90bb7606cebfb7786c3601df298ccd Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 03:08:47 +0100 Subject: Add ability to match on server tag Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 142 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 89 insertions(+), 53 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index b7e694c..6911192 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -15,17 +15,19 @@ # # For instance, you might never want to be disturbed by activity in any # channel, unless someone highlights you. However, you do want all activity -# in queries, as well as an indication about any chatter in your company -# channels. The following ctrlact map would do this for you: +# in queries (except on efnet, as well as an indication about any chatter in +# your company channels. The following ctrlact map would do this for you: # -# channel /^#myco-/ messages -# channel * hilights -# query * all +# channel /^#myco-/ messages +# channel * hilights +# query efnet * messages +# query * all # # These three lines would be interpreted/read as: # "only messages or higher in a channel matching /^#myco-/ should trigger act" # "in all other channels, only hilights (or higher) should trigger act" -# "messages of all levels should trigger act in queries" +# "queries on efnet should only trigger act for messages and higher" +# "messages of all levels should trigger act in queries elsewhere" # # The activity level in the third column is thus to be interpreted as # "the minimum level of activity that will trigger an indication" @@ -101,7 +103,6 @@ # # - figure out interplay with activity_hide_level # - /ctrlact add/delete/move and /ctrlact save, maybe -# - ability to add a server tag to an item name to make matches more specific # - completion for commands # use strict; @@ -109,7 +110,7 @@ use warnings; use Irssi; use Text::ParseWords; -our $VERSION = '1.0'; +our $VERSION = '1.1'; our %IRSSI = ( authors => 'martin f. krafft', @@ -117,7 +118,7 @@ our %IRSSI = ( name => 'ctrlact', description => 'allows per-channel control over activity indication', license => 'MIT', - changed => '2017-02-12' + changed => '2017-02-15' ); ### DEFAULTS AND SETTINGS ###################################################### @@ -155,7 +156,7 @@ my @DATALEVEL_KEYWORDS = ('all', 'messages', 'hilights', 'none'); ### HELPERS #################################################################### my $_inhibit_debug_activity = 0; -use constant DEBUGEVENTFORMAT => "%7s %-22.22s %d %s %d → %-7s (%-8s ← %s)"; +use constant DEBUGEVENTFORMAT => "%7s %7.7s %-22.22s %d %s %d → %-7s (%-8s ← %s)"; sub debugprint { return unless $debug; my ($msg, @rest) = @_; @@ -204,13 +205,17 @@ sub from_data_level { } sub walk_match_array { - my ($name, $type, @arr) = @_; - foreach my $pair (@arr) { - my $match = match($pair->[0], $name); - next unless $match; - my $result = to_data_level($pair->[1]); + my ($name, $net, $type, @arr) = @_; + foreach my $quadruplet (@arr) { + my $netmatch = match($quadruplet->[0], $net); + my $match = match($quadruplet->[1], $name); + next unless $netmatch and $match; + + my $result = to_data_level($quadruplet->[2]); my $tresult = from_data_level($result); $name = '(unnamed)' unless length $name; + $match = sprintf('line %-3d = net:%-10.10s name:%s', + $quadruplet->[3], $netmatch, $match); return ($result, $tresult, $match) } return -1; @@ -220,22 +225,23 @@ sub get_mappings_table { my (@arr) = @_; my @ret = (); for (my $i = 0; $i < @arr; $i++) { - push @ret, sprintf("%4d: %-40s %-10s", $i, $arr[$i]->[0], $arr[$i]->[1]); + push @ret, sprintf("%4d: %-10s %-40s %-10s", + $i, $arr[$i]->[0], $arr[$i]->[1], $arr[$i]->[2]); } return join("\n", @ret); } sub get_specific_threshold { - my ($type, $name) = @_; + my ($type, $name, $net) = @_; $type = lc($type); if ($type eq 'window') { - return walk_match_array($name, $type, @window_thresholds); + return walk_match_array($name, $net, $type, @window_thresholds); } elsif ($type eq 'channel') { - return walk_match_array($name, $type, @channel_thresholds); + return walk_match_array($name, $net, $type, @channel_thresholds); } elsif ($type eq 'query') { - return walk_match_array($name, $type, @query_thresholds); + return walk_match_array($name, $net, $type, @query_thresholds); } else { die "ctrlact: can't look up threshold for type: $type"; @@ -243,8 +249,8 @@ sub get_specific_threshold { } sub get_item_threshold { - my ($chattype, $type, $name) = @_; - my ($ret, $tret, $match) = get_specific_threshold($type, $name); + my ($chattype, $type, $name, $net) = @_; + my ($ret, $tret, $match) = get_specific_threshold($type, $name, $net); return ($ret, $tret, $match) if $ret > 0; if ($type eq 'CHANNEL') { return ($fallback_channel_threshold, from_data_level($fallback_channel_threshold), '[default]'); @@ -255,8 +261,8 @@ sub get_item_threshold { } sub get_win_threshold { - my ($name) = @_; - my ($ret, $tret, $match) = get_specific_threshold('window', $name); + my ($name, $net) = @_; + my ($ret, $tret, $match) = get_specific_threshold('window', $name, $net); if ($ret > 0) { return ($ret, $tret, $match); } @@ -270,9 +276,10 @@ sub print_levels_for_all { Irssi::print("ctrlact: $type mappings:"); for (my $i = 0; $i < @arr; $i++) { my $name = $arr[$i]->{'name'}; - my ($t, $tt, $match) = get_specific_threshold($type, $name); - my $c = ($type eq 'window') ? $arr[$i]->{'refnum'} : $i; - printf CLIENTCRAP "%4d: %-40s → %d (%s; match:%s)", $c, $name, $t, $tt, $match; + my $net = $arr[$i]->{'server'}->{'tag'} // ''; + my ($t, $tt, $match) = get_specific_threshold($type, $name, $net); + my $c = ($type eq 'window') ? $arr[$i]->{'refnum'} : $arr[$i]->window()->{'refnum'}; + printf CLIENTCRAP "%4d: %-40.40s → %d (%-8s) match %s", $c, $name, $t, $tt, $match; } } @@ -293,9 +300,10 @@ sub maybe_inhibit_witem_hilight { my $wichattype = $witem->{'chat_type'}; my $witype = $witem->{'type'}; my $winame = $witem->{'name'}; - my ($th, $tth, $match) = get_item_threshold($wichattype, $witype, $winame); + my $witag = $witem->{'server'}->{'tag'} // ''; + my ($th, $tth, $match) = get_item_threshold($wichattype, $witype, $winame, $witag); my $inhibit = $newlevel > 0 && $newlevel < $th; - debugprint(sprintf(DEBUGEVENTFORMAT, lc($witype), $winame, $newlevel, + debugprint(sprintf(DEBUGEVENTFORMAT, lc($witype), $witag, $winame, $newlevel, $inhibit ? ('<',$th,'inhibit'):('≥',$th,'pass'), $tth, $match)); if ($inhibit) { @@ -329,9 +337,10 @@ sub maybe_inhibit_win_hilight { return if ($newlevel <= $oldlevel); my $wname = $win->{'name'}; - my ($th, $tth, $match) = get_win_threshold($wname); + my $wtag = $win->{'server'}->{'tag'} // ''; + my ($th, $tth, $match) = get_win_threshold($wname, $wtag); my $inhibit = $newlevel > 0 && $newlevel < $th; - debugprint(sprintf(DEBUGEVENTFORMAT, 'window', + debugprint(sprintf(DEBUGEVENTFORMAT, 'window', $wtag, $wname?$wname:'(unnamed)', $newlevel, $inhibit ? ('<',$th,'inhibit'):('≥',$th,'pass'), $tth, $match)); @@ -363,39 +372,40 @@ sub get_mappings_fh { # ctrlact mappings file (version:$VERSION) # # type: window, channel, query +# server: the server tag (chatnet) # name: full name to match, /regexp/, or * (for all) # min.level: none, messages, hilights, all, or 1,2,3,4 # -# type name min.level +# type server name min.level # EXAMPLES # ### only indicate activity in the status window if messages were displayed: -# window (status) messages +# window * (status) messages # ### never ever indicate activity for any item bound to this window: -# window oubliette none +# window * oubliette none # -### indicate activity on all messages in debian-related channels: -# channel /^#debian/ messages +### indicate activity on all messages in debian-related channels on OFTC: +# channel oftc /^#debian/ messages # ### display any text (incl. joins etc.) for the '#madduck' channel: -# channel #madduck all +# channel * #madduck all # ### otherwise ignore everything in channels, unless a hilight is triggered: -# channel * hilights +# channel * * hilights # ### make somebot only get your attention if they hilight you: -# query somebot hilights +# query efnet somebot hilights # ### otherwise we want to see everything in queries: -# query * all +# query * * all # DEFAULTS: -# window * $ftw -# channel * $ftc -# query * $ftq +# window * * $ftw +# channel * * $ftc +# query * * $ftq # vim:noet:tw=0:ts=16 EOF @@ -408,12 +418,36 @@ sub load_mappings { my ($filename) = @_; @window_thresholds = @channel_thresholds = @query_thresholds = (); my $fh = get_mappings_fh($filename); + my $firstline = <$fh>; + my $version; + if ($firstline =~ m/^#+\s+ctrlact mappings file \(version:([\d.]+)\)/) { + $version = $1; + } + else { + die "First line of $filename is not a ctrlact header."; + } + + my $nrcols = 4; + if ($version eq $VERSION) { + # current version + } + elsif ($version eq "1.0") { + $nrcols = 3; + } + else { + die "Unsupported version found in $filename: $version" + } + my $linesplitter = '^\s*'.join('\s+', ('(\S+)') x $nrcols).'\s*$'; + my $l = 1; while (<$fh>) { + $l++; next if m/^\s*(?:#|$)/; - m/^\s*(\S+)\s+(\S+)\s+(\S+)\s*$/; - push @window_thresholds, [$2, $3] if match($1, 'window'); - push @channel_thresholds, [$2, $3] if match($1, 'channel'); - push @query_thresholds, [$2, $3] if match($1, 'query'); + my ($type, @matchers) = m/$linesplitter/; + @matchers = ['*', @matchers] if ($version eq "1.0"); + push @matchers, $l; + push @window_thresholds, [@matchers] if match($type, 'window'); + push @channel_thresholds, [@matchers] if match($type, 'channel'); + push @query_thresholds, [@matchers] if match($type, 'query'); } close($fh) || die "Cannot close mappings file: $!"; } @@ -442,6 +476,7 @@ sub parse_args { my (@args) = @_; my @words = (); my $typewasset = 0; + my $tag; my $max = 0; my $type = undef; foreach my $arg (@args) { @@ -455,25 +490,26 @@ sub parse_args { $type = 'query' if $1 =~ m/^q/; $typewasset = 1 } - elsif ($arg =~ m/^-/) { - error("Unknown argument: $arg"); + elsif ($arg =~ m/-(\S+)/) { + $tag = $1; } else { push @words, $arg; $max = length $arg if length $arg > $max; } } - return ($type, $max, @words); + return ($type, $tag, $max, @words); } sub cmd_query { my ($data, $server, $item) = @_; my @args = shellwords($data); - my ($type, $max, @words) = parse_args(@args); + my ($type, $tag, $max, @words) = parse_args(@args); $type = $type // 'channel'; + $tag = $tag // '*'; foreach my $word (@words) { - my ($t, $tt, $match) = get_specific_threshold($type, $word); - printf CLIENTCRAP "ctrlact $type map: %*s → %d (%s, match:%s)", $max, $word, $t, $tt, $match; + my ($t, $tt, $match) = get_specific_threshold($type, $word, $tag); + printf CLIENTCRAP "ctrlact $type map: %s %*s → %d (%s, match:%s)", $tag, $max, $word, $t, $tt, $match; } } -- cgit v1.2.3 From 970d433eaab3402cdb4edb8b67ae5026ad5c15b4 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 04:34:06 +0100 Subject: Lower message level of debug output Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 6911192..35e2cd7 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -161,7 +161,7 @@ sub debugprint { return unless $debug; my ($msg, @rest) = @_; $_inhibit_debug_activity = 1; - Irssi::print("ctrlact debug: ".$msg); + Irssi::print("ctrlact debug: ".$msg, MSGLEVEL_CRAP); $_inhibit_debug_activity = 0; } -- cgit v1.2.3 From 709c4bc9ef277e3391b115b1b0ed29f55f0d9314 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 04:43:40 +0100 Subject: Print linenumbers in /ctrlact list output Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 35e2cd7..6a48773 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -225,8 +225,8 @@ sub get_mappings_table { my (@arr) = @_; my @ret = (); for (my $i = 0; $i < @arr; $i++) { - push @ret, sprintf("%4d: %-10s %-40s %-10s", - $i, $arr[$i]->[0], $arr[$i]->[1], $arr[$i]->[2]); + push @ret, sprintf("%4d: %-10s %-40s %-10s (line: %3d)", + $i, $arr[$i]->[0], $arr[$i]->[1], $arr[$i]->[2], $arr[$i]->[3]); } return join("\n", @ret); } -- cgit v1.2.3 From d060a3072cdefa3a14f4a03a3c6c21ed2ec5a109 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 04:43:56 +0100 Subject: Unify print output Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 6a48773..931b89c 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -279,7 +279,7 @@ sub print_levels_for_all { my $net = $arr[$i]->{'server'}->{'tag'} // ''; my ($t, $tt, $match) = get_specific_threshold($type, $name, $net); my $c = ($type eq 'window') ? $arr[$i]->{'refnum'} : $arr[$i]->window()->{'refnum'}; - printf CLIENTCRAP "%4d: %-40.40s → %d (%-8s) match %s", $c, $name, $t, $tt, $match; + Irssi::print(sprintf("%4d: %-40.40s → %d (%-8s) match %s", $c, $name, $t, $tt, $match), MSGLEVEL_CRAP); } } @@ -465,11 +465,11 @@ sub cmd_save { sub cmd_list { Irssi::print("ctrlact: window mappings"); - print CLIENTCRAP get_mappings_table(@window_thresholds); + Irssi::print(get_mappings_table(@window_thresholds), MSGLEVEL_CRAP); Irssi::print("ctrlact: channel mappings"); - print CLIENTCRAP get_mappings_table(@channel_thresholds); + Irssi::print(get_mappings_table(@channel_thresholds), MSGLEVEL_CRAP); Irssi::print("ctrlact: query mappings"); - print CLIENTCRAP get_mappings_table(@query_thresholds); + Irssi::print(get_mappings_table(@query_thresholds), MSGLEVEL_CRAP); } sub parse_args { -- cgit v1.2.3 From 287853515d45770147a7083998fdbea8c5d65135 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 04:56:08 +0100 Subject: Simplify debug output Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 931b89c..25dbb0d 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -214,7 +214,7 @@ sub walk_match_array { my $result = to_data_level($quadruplet->[2]); my $tresult = from_data_level($result); $name = '(unnamed)' unless length $name; - $match = sprintf('line %-3d = net:%-10.10s name:%s', + $match = sprintf('line %3d = net:%s name:%s', $quadruplet->[3], $netmatch, $match); return ($result, $tresult, $match) } -- cgit v1.2.3 From 70893f08280e062732e84bed4314419ecfdfcd7a Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 21:46:04 +0100 Subject: Use croak instead of die Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 25dbb0d..28263ef 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -107,6 +107,7 @@ # use strict; use warnings; +use Carp qw( croak ); use Irssi; use Text::ParseWords; @@ -200,7 +201,7 @@ sub to_data_level { sub from_data_level { my ($dl) = @_; - die "Invalid numeric data level: $dl" unless $dl =~ m/^([1-4])$/; + croak "Invalid numeric data level: $dl" unless $dl =~ m/^([1-4])$/; return $DATALEVEL_KEYWORDS[$dl-1]; } @@ -244,7 +245,7 @@ sub get_specific_threshold { return walk_match_array($name, $net, $type, @query_thresholds); } else { - die "ctrlact: can't look up threshold for type: $type"; + croak "ctrlact: can't look up threshold for type: $type"; } } @@ -360,10 +361,10 @@ sub get_mappings_fh { my ($filename) = @_; my $fh; if (-e $filename) { - open($fh, $filename) || die "Cannot open mappings file: $!"; + open($fh, $filename) || croak "Cannot open mappings file: $!"; } else { - open($fh, "+>$filename") || die "Cannot create mappings file: $!"; + open($fh, "+>$filename") || croak "Cannot create mappings file: $!"; my $ftw = from_data_level($fallback_window_threshold); my $ftc = from_data_level($fallback_channel_threshold); @@ -424,7 +425,7 @@ sub load_mappings { $version = $1; } else { - die "First line of $filename is not a ctrlact header."; + croak "First line of $filename is not a ctrlact header."; } my $nrcols = 4; @@ -435,7 +436,7 @@ sub load_mappings { $nrcols = 3; } else { - die "Unsupported version found in $filename: $version" + croak "Unsupported version found in $filename: $version" } my $linesplitter = '^\s*'.join('\s+', ('(\S+)') x $nrcols).'\s*$'; my $l = 1; @@ -449,7 +450,7 @@ sub load_mappings { push @channel_thresholds, [@matchers] if match($type, 'channel'); push @query_thresholds, [@matchers] if match($type, 'query'); } - close($fh) || die "Cannot close mappings file: $!"; + close($fh) || croak "Cannot close mappings file: $!"; } sub cmd_load { -- cgit v1.2.3 From 9a06b4ae868eb006c1db46c61502ff8d49ebec4f Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 22:14:05 +0100 Subject: Properly handle mappings file creation Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 28263ef..c35a2c4 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -370,7 +370,7 @@ sub get_mappings_fh { my $ftc = from_data_level($fallback_channel_threshold); my $ftq = from_data_level($fallback_query_threshold); print $fh <<"EOF"; -# ctrlact mappings file (version:$VERSION) +# ctrlact mappings file (version: $VERSION) # # type: window, channel, query # server: the server tag (chatnet) @@ -411,6 +411,7 @@ sub get_mappings_fh { # vim:noet:tw=0:ts=16 EOF Irssi::print("ctrlact: created new/empty mappings file: $filename"); + seek($fh, 0, 0) || croak "Cannot rewind $filename."; } return $fh; } @@ -419,9 +420,9 @@ sub load_mappings { my ($filename) = @_; @window_thresholds = @channel_thresholds = @query_thresholds = (); my $fh = get_mappings_fh($filename); - my $firstline = <$fh>; + my $firstline = <$fh> || croak "Cannot read from $filename.";; my $version; - if ($firstline =~ m/^#+\s+ctrlact mappings file \(version:([\d.]+)\)/) { + if ($firstline =~ m/^#+\s+ctrlact mappings file \(version: *([\d.]+)\)/) { $version = $1; } else { -- cgit v1.2.3 From d707da591a371427bf67e9eb1a7a2993c5730c55 Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Wed, 15 Feb 2017 22:20:06 +0100 Subject: Switch to 3-arg open calls Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index c35a2c4..534b00a 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -361,10 +361,10 @@ sub get_mappings_fh { my ($filename) = @_; my $fh; if (-e $filename) { - open($fh, $filename) || croak "Cannot open mappings file: $!"; + open($fh, '<', $filename) || croak "Cannot open mappings file: $!"; } else { - open($fh, "+>$filename") || croak "Cannot create mappings file: $!"; + open($fh, '+>', $filename) || croak "Cannot create mappings file: $!"; my $ftw = from_data_level($fallback_window_threshold); my $ftc = from_data_level($fallback_channel_threshold); -- cgit v1.2.3 From 74c036b5a725d8d268ea62ace595bce9d4eaf36f Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Fri, 24 Feb 2017 07:33:08 +1300 Subject: Fix network matching for query subcommand In the absence of a network tag passed to the `query` subcommand, no rules but the default would match and so the returned match(es) would potentially not actually be the ones used in context of ctrlact's normal operation. This commit fixes #354 by special-casing the threshold match when the data to be looked up doesn't actually specify a network tag. In this case, the output for net will be '(ignored)'. Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index 534b00a..aa9dcfb 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -111,7 +111,7 @@ use Carp qw( croak ); use Irssi; use Text::ParseWords; -our $VERSION = '1.1'; +our $VERSION = '1.2'; our %IRSSI = ( authors => 'martin f. krafft', @@ -119,7 +119,7 @@ our %IRSSI = ( name => 'ctrlact', description => 'allows per-channel control over activity indication', license => 'MIT', - changed => '2017-02-15' + changed => '2017-02-24' ); ### DEFAULTS AND SETTINGS ###################################################### @@ -208,7 +208,8 @@ sub from_data_level { sub walk_match_array { my ($name, $net, $type, @arr) = @_; foreach my $quadruplet (@arr) { - my $netmatch = match($quadruplet->[0], $net); + my $netmatch = $net eq '*' ? '(ignored)' + : match($quadruplet->[0], $net); my $match = match($quadruplet->[1], $name); next unless $netmatch and $match; -- cgit v1.2.3 From 85e74f61af85356830030596e9ff77faf2f7c05f Mon Sep 17 00:00:00 2001 From: martin f. krafft Date: Fri, 24 Feb 2017 07:41:29 +1300 Subject: Loosen version check on data file read The versioning of the data file allows for making changes to the format, but if the script version increases without the data file-format being changed, things are expected to work as before, and thus there ought not be an error spouted. Let's only use the versioning to patch up handling for formats of the past. Signed-off-by: martin f. krafft --- scripts/ctrlact.pl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts/ctrlact.pl') diff --git a/scripts/ctrlact.pl b/scripts/ctrlact.pl index aa9dcfb..da39804 100644 --- a/scripts/ctrlact.pl +++ b/scripts/ctrlact.pl @@ -432,14 +432,14 @@ sub load_mappings { my $nrcols = 4; if ($version eq $VERSION) { - # current version + # current version, i.e. no special handling is required. If + # previous versions require special handling, then massage the + # data or do whatever is required in the following + # elsif-clauses: } elsif ($version eq "1.0") { $nrcols = 3; } - else { - croak "Unsupported version found in $filename: $version" - } my $linesplitter = '^\s*'.join('\s+', ('(\S+)') x $nrcols).'\s*$'; my $l = 1; while (<$fh>) { -- cgit v1.2.3