Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
560 lines (465 sloc) 14.2 KB
##############################################################################
#
# mh_hold_mode.pl v1.08 (20170424)
#
# Copyright (c) 2007, 2015-2017 Michael Hansen
#
# Permission to use, copy, modify, and distribute this software
# for any purpose with or without fee is hereby granted, provided
# that the above copyright notice and this permission notice
# appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
# WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
# THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
##############################################################################
#
# Emulation of ircII per-window hold_mode
#
# upgrading from v0.xx to v1.xx:
#
# the statusbar item have changed name from mh_more to mh_sbmore, you
# can remove the old item with '/statusbar window remove mh_more' and
# follow the instructions below to add the new item
#
# should you not like the new item look, you can revert it back to the
# old style with the setting mh_hold_mode_more_oldstyle
#
# previously the default window hold_mode and scroll_always were hardcoded
# they are now setable in irssi (see settings below)
#
# instructions:
#
# add the mh_sbmore statusbar item with '/statusbar window add -after window_empty mh_sbmore'
# (For better control of the placement of mh_sbmore see '/HELP STATUSBAR'
#
# mh_sbmore *should* fully replace Irssi's standard more, so you could
# remove it with '/STATUSBAR WINDOW REMOVE more'
#
# when the script is loaded it will reset all windows and scroll them
# to the last line (without losing backlog) and from then on you will
# have to do '/HOLD_MODE ON' or '/HOLD_MODE OFF' in a given window to
# enable/disable hold_mode for it (off by default)
#
# should the buffer become too much for you to bother to read it, you
# can jump to the bottom with '/HOLD_MODE FLUSH' (although '/CLEAR'
# will do the same)
#
# when hold_mode is on, it will scroll until the last line you said or
# command you send, then hold untill you press enter (and depending on
# the 'scroll_always' value it will either scroll on any enter, or only on
# enter with empty commandline). enter will scroll by 1 page (minus 1 line)
# unless you have moved around in the scrollback buffer with pg-up/dn, in
# which case it will scroll to where you left (except when you pg-dn to
# end of buffer, this will reset the scroll stop point to that line)
#
# (also, you can reset the point to scroll to at any time by just
# pressing enter when in "live" view, the current line will then be set
# as the scroll stop point)
#
# it is not a true-to-ircII hold_mode emulation, as some things are slightly
# different, over time they might be made optional to be able to go back
# to as close to ircII as possible.
#
# (i hope i didn't forget anything :-)
#
# settings:
#
# mh_hold_mode_more_oldstyle (default OFF): switch between old and new
# style more statusbar item
#
# mh_hold_mode_default_hold_mode (default OFF): change the default hold_mode
# setting for new windows
#
# mh_hold_mode_default_scroll_always (default ON): change the default scroll_always
# setting for new windows
#
# history:
#
# v1.08 (20170424)
# added 'sbitems' to irssi header for better scriptassist.pl support (github issue #1)
#
# v1.07 (20160510)
# corrected typo in instructions
# added space to old-style more so it looks better
#
# v1.06 (20160503)
# fixed call to missing sub
#
# v1.05 (20160211)
# moved default settings from hardcoded to irssi settings _default_hold_mode and _default_scroll_always
#
# v1.04 (20160126)
# added mh_hold_mode_more_oldstyle and supporting code
# added namespace to MSGLEVEL
# code cleanup
#
# v1.03 (20151226)
# now using 'key send_line' instead of 'gui key pressed'
# added /help
# fixed '/hold_mode toggle', it didnt do anything before
# code cleanup
# added changed field to irssi header
# changed url
#
# v1.02 (20151210)
# now accepts both 10 and 13 as keycode for enter, required to work in upcoming irssi
#
# v1.01 (20151204)
# nicer (imho) mh_sbmore
#
# v1.00 (20151201)
# cleanup and re-release, this have been in active use since 2007 without any issues
#
# v0.12 (unknown 2007)
# added scroll_always option: /HOLD_MODE scroll_always [on|off|toggle]
# Defaults to always scroll on, even if the line is not empty when you
# press enter - the ircII way. If you like to only scroll on empty lines
# set '/HOLD_MODE scroll_always off'
# added '/HOLD_MODE toggle' for ircII emulation completenes
#
use v5.14.2;
use strict;
##############################################################################
#
# irssi head
#
##############################################################################
use Irssi 20100403;
use Irssi::TextUI;
our $VERSION = '1.08';
our %IRSSI =
(
'name' => 'mh_hold_mode',
'description' => 'Emulation of ircII per-window hold_mode',
'license' => 'BSD',
'authors' => 'Michael Hansen',
'contact' => 'mh on IRCnet #help',
'url' => 'http://scripts.irssi.org / https://github.com/mh-source/irssi-scripts',
'changed' => 'Mon Apr 24 10:32:25 CEST 2017',
'sbitems' => 'mh_sbmore',
);
##############################################################################
#
# global variables
#
##############################################################################
our %config;
our $lastcommand = '';
our $more = 0;
##############################################################################
#
# common support functions
#
##############################################################################
sub trim_space
{
my ($string) = @_;
if (defined($string))
{
$string =~ s/^\s+//g;
$string =~ s/\s+$//g;
} else
{
$string = '';
}
return($string);
}
##############################################################################
#
# script functions
#
##############################################################################
sub config_window_get
{
my ($windowrec) = @_;
if ($windowrec)
{
my $windowid = $windowrec->{'_irssi'};
if (!exists($config{'WINDOW'}{$windowid}))
{
if (Irssi::settings_get_bool('mh_hold_mode_default_hold_mode'))
{
$config{'WINDOW'}{$windowid}{'hold_mode'} = 1;
} else
{
$config{'WINDOW'}{$windowid}{'hold_mode'} = 0;
}
if (Irssi::settings_get_bool('mh_hold_mode_default_scroll_always'))
{
$config{'WINDOW'}{$windowid}{'scroll_always'} = 1;
} else
{
$config{'WINDOW'}{$windowid}{'scroll_always'} = 0;
}
}
return(\%{$config{'WINDOW'}{$windowid}});
}
return(undef);
}
sub config_window_del
{
my ($windowrec) = @_;
if ($windowrec)
{
my $windowid = $windowrec->{'_irssi'};
if (exists($config{'WINDOW'}{$windowid}))
{
delete($config{'WINDOW'}{$windowid});
return(1);
}
}
return(undef);
}
sub window_bookmark_compare
{
my ($bookmark1, $bookmark2) = @_;
if ($bookmark1 and $bookmark2)
{
if ($bookmark1->{'_irssi'} == $bookmark2->{'_irssi'})
{
return(1);
}
}
return(0);
}
sub window_refresh
{
my $windowrec = Irssi::active_win();
if (not $windowrec->view()->{'empty_linecount'})
{
my $bookmark = $windowrec->view()->get_bookmark('mh_hold_mode');
if (not $bookmark)
{
$windowrec->view()->set_bookmark('mh_hold_mode', $windowrec->view()->{'startline'});
$bookmark = $windowrec->view()->get_bookmark('mh_hold_mode');
if (not $bookmark)
{
return(0);
}
}
$windowrec->view()->scroll_line($bookmark);
statusbar_more_redraw();
}
}
sub window_scroll
{
my $windowrec = Irssi::active_win();
my $bookmark = $windowrec->view()->{'startline'};
window_refresh();
my $bookmark_new = $windowrec->view()->{'startline'};
if (window_bookmark_compare($bookmark_new, $bookmark))
{
$windowrec->view()->scroll(($windowrec->{'height'} - 1));
if ($windowrec->view()->{'bottom'})
{
$windowrec->view()->set_bookmark_bottom('mh_hold_mode');
} else
{
$windowrec->view()->set_bookmark('mh_hold_mode', $windowrec->view()->{'startline'});
}
}
statusbar_more_redraw();
}
sub statusbar_more_redraw
{
Irssi::statusbar_items_redraw('mh_sbmore');
}
##############################################################################
#
# irssi signal handlers
#
##############################################################################
sub signal_key_send_line_first
{
$lastcommand = Irssi::parse_special('$L');
my $windowrec = Irssi::active_win();
if (($lastcommand eq '' or config_window_get($windowrec)->{'scroll_always'}) and $more)
{
window_scroll();
}
}
sub signal_key_send_line_last
{
my $windowrec = Irssi::active_win();
if (config_window_get($windowrec)->{'hold_mode'})
{
if ($windowrec->view()->{'bottom'})
{
$windowrec->view()->set_bookmark_bottom('mh_hold_mode');
if ($more)
{
$windowrec->view()->scroll($more);
window_refresh();
}
} else
{
window_refresh();
}
}
}
sub signal_window_changed_last
{
my ($windowrec_new, $windowrec_old) = @_;
if (config_window_get($windowrec_new)->{'hold_mode'})
{
window_refresh();
}
}
sub signal_print_text_last
{
my ($textdest, $text, $stripped) = @_;
my $windowrec = Irssi::active_win();
my $window = config_window_get($windowrec);
if ($textdest->{'window'}->{'refnum'} == $windowrec->{'refnum'} and config_window_get($windowrec)->{'hold_mode'} and $more <= $windowrec->{'height'})
{
window_refresh();
}
}
##############################################################################
#
# irssi command functions
#
##############################################################################
sub command_hold_mode
{
my ($data, $server, $windowitem) = @_;
my $windowrec = Irssi::active_win();
my $window = config_window_get($windowrec);
my $showstatus = 1;
if (defined($data))
{
$data = trim_space($data);
if ($data ne '')
{
if ($data =~ m/^toggle$/i)
{
if (not $window->{'hold_mode'})
{
$window->{'hold_mode'} = 1;
} else
{
$window->{'hold_mode'} = 0;
}
} elsif ($data =~ m/^on$/i)
{
$window->{'hold_mode'} = 1;
$windowrec->view()->set_bookmark_bottom('mh_hold_mode');
window_refresh();
} elsif ($data =~ m/^off$/i)
{
$window->{'hold_mode'} = 0;
$windowrec->view()->set_bookmark_bottom('mh_hold_mode');
window_refresh();
} elsif ($data =~ m/^flush$/i)
{
$showstatus = 0;
$windowrec->view()->set_bookmark_bottom('mh_hold_mode');
window_refresh();
} elsif ($data =~ m/^scroll_always(.*)$/i)
{
$showstatus = 0;
if (defined($1))
{
$data = trim_space($1);
if ($data =~ m/^toggle$/i)
{
$data = (($window->{'scroll_always'}) ? 'off' : 'on' );
}
if ($data =~ m/^on$/i)
{
$window->{'scroll_always'} = 1;
} elsif ($data =~ m/^off$/i)
{
$window->{'scroll_always'} = 0;
}
}
$windowrec->print('hold_mode (' . (($window->{'hold_mode'}) ? 'on' : 'off' ) . '): scroll_always is ' . (($window->{'scroll_always'}) ? 'on' : 'off' ), Irssi::MSGLEVEL_CLIENTCRAP);
}
}
}
if ($showstatus)
{
$windowrec->print('hold_mode is ' . (($window->{'hold_mode'}) ? 'on' : 'off' ), Irssi::MSGLEVEL_CLIENTCRAP);
}
}
sub command_help
{
my ($data, $server, $windowitem) = @_;
$data = lc(trim_space($data));
if ($data =~ m/^hold_mode$/i)
{
Irssi::print('', Irssi::MSGLEVEL_CLIENTCRAP);
Irssi::print('HOLD_MODE %|[on|off|toggle|flush]', Irssi::MSGLEVEL_CLIENTCRAP);
Irssi::print('HOLD_MODE %|scroll_always [on|off|toggle]', Irssi::MSGLEVEL_CLIENTCRAP);
Irssi::print('', Irssi::MSGLEVEL_CLIENTCRAP);
Irssi::print('%|Show/enable/disable/toggle/flush status of window hold_mode or show/enable/disable/toggle the scroll_always setting.', Irssi::MSGLEVEL_CLIENTCRAP);
Irssi::print('', Irssi::MSGLEVEL_CLIENTCRAP);
Irssi::signal_stop();
}
}
##############################################################################
#
# statusbar item handlers
#
##############################################################################
sub statusbar_more
{
my ($statusbaritem, $get_size_only) = @_;
my $window = Irssi::active_win();
my $local_more = 0;
$local_more = ($window->view()->{'ypos'} - $window->view()->{'height'} + $window->view()->{'empty_linecount'} + 1);
$more = $local_more;
if ($more)
{
my $format = "{sb $more more}";
if (Irssi::settings_get_bool('mh_hold_mode_more_oldstyle'))
{
$format = " -- $more more --";
}
$statusbaritem->default_handler($get_size_only, $format, '', 0);
} else
{
$statusbaritem->default_handler($get_size_only, '', '', 0);
}
}
##############################################################################
#
# script on load
#
##############################################################################
Irssi::settings_add_bool('mh_hold_mode', 'mh_hold_mode_more_oldstyle', 0);
Irssi::settings_add_bool('mh_hold_mode', 'mh_hold_mode_default_hold_mode', 0);
Irssi::settings_add_bool('mh_hold_mode', 'mh_hold_mode_default_scroll_always', 1);
Irssi::signal_add_last('window created', 'config_window_get');
Irssi::signal_add_last('window destroyed', 'config_window_del');
Irssi::signal_add_first('key send_line', 'signal_key_send_line_first');
Irssi::signal_add_last('key send_line', 'signal_key_send_line_last');
Irssi::signal_add_last('window changed', 'signal_window_changed_last');
Irssi::signal_add_last('print text', 'signal_print_text_last');
Irssi::command_bind('hold_mode', 'command_hold_mode', 'mh_hold_mode');
Irssi::command_bind('help', 'command_help');
Irssi::statusbar_item_register('mh_sbmore', '', 'statusbar_more');
Irssi::statusbars_recreate_items();
Irssi::command('^SET SCROLL ON');
for my $window (Irssi::windows)
{
$window->view()->set_scroll(1);
$window->view()->set_bookmark_bottom('mh_hold_mode');
config_window_get($window);
}
statusbar_more_redraw();
Irssi::command('^REDRAW');
Irssi::timeout_add(1000, 'statusbar_more_redraw', undef);
1;
##############################################################################
#
# eof mh_hold_mode.pl
#
##############################################################################