diff options
author | Tom Feist <shabble@cowu.be> | 2010-07-24 16:35:43 +0000 |
---|---|---|
committer | Tom Feist <shabble@cowu.be> | 2010-07-24 16:35:43 +0000 |
commit | 501309887a7499b91c2b9fa8f76180c2738d7990 (patch) | |
tree | 5bc5f26da277c8b4c7d66c5863ba365723dc6c53 /history-search/rl_history_search.pl | |
parent | misc stuffs (diff) | |
download | irssi-scripts-501309887a7499b91c2b9fa8f76180c2738d7990.tar.gz irssi-scripts-501309887a7499b91c2b9fa8f76180c2738d7990.zip |
something confusing going on here, have I got nested repos?
Diffstat (limited to 'history-search/rl_history_search.pl')
-rw-r--r-- | history-search/rl_history_search.pl | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/history-search/rl_history_search.pl b/history-search/rl_history_search.pl new file mode 100644 index 0000000..9b58fd7 --- /dev/null +++ b/history-search/rl_history_search.pl @@ -0,0 +1,228 @@ +# Search within your typed history as you type (like ctrl-R in bash) +# Usage: + +# * Setup: /bind ^R /history_search_start + +# * Then type ctrl-R and type what you're searching for + +# * You can cycle through multiple matches with ^R (older matches), and +# ^S (newer matches) + +# * Hitting enter selects a match and terminates search mode. + +# * You can use ^G to exit search mode without selecting. + + +# Original script Copyright 2007 Wouter Coekaerts <coekie@irssi.org> +# Heavy modifications by Shabble <shabble+irssi@metavore.org>, 2010. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +use strict; +use Irssi; +use Irssi::TextUI; +use Data::Dumper; + +use vars qw($VERSION %IRSSI); +$VERSION = '1.0'; +%IRSSI = + ( + authors => 'Wouter Coekaerts, Tom Feist', + contact => 'coekie@irssi.org', + name => 'rl_history_search', + description => 'Search within your typed history as you type' + . ' (like ctrl-R in readline applications)', + license => 'GPLv2 or later', + url => 'http://wouter.coekaerts.be/irssi/', + changed => '24/7/2010' + ); + +my $search_str = ''; +my $search_active = 0; + +my @history_cache = (); +my @search_matches = (); +my $match_index = 0; + + +sub DEBUG () { 0 } + +# check we have prompt_info loaded. + +sub script_is_loaded { + my $name = shift; + print "Checking if $name is loaded" if DEBUG; + no strict 'refs'; + my $retval = defined %{ "Irssi::Script::${name}::" }; + use strict 'refs'; + + return $retval; +} + +unless (script_is_loaded('prompt_info')) { + die "This script requires 'prompt_info' in order to work. " + . "Please load it and try again"; +} else { + history_init(); +} + +sub history_init { + Irssi::command_bind('history_search_start', \&history_search); + #Irssi::command_bind('history_search_exit', \&history_search_exit); + Irssi::signal_add_first('gui key pressed' => \&handle_keypress); +} + +sub history_search { + $search_active = 1; + $search_str = ''; + $match_index = -1; + + @history_cache = Irssi::active_win()->get_history_lines(); + @search_matches = (); + + update_history_prompt(); +} + +sub history_exit { + $search_active = 0; + Irssi::signal_emit('change prompt', ''); +} + +sub update_history_prompt { + Irssi::signal_emit('change prompt', " reverse-i-search: \`$search_str'"); +} + +sub update_history_matches { + my ($match_str) = @_; + $match_str //= $search_str; + + my %unique; + my @matches = grep { m/\Q$match_str/i } @history_cache; + + @search_matches = (); + + # uniquify the results, whilst maintaining order. + foreach my $m (@matches) { + unless (exists($unique{$m})) { + # add them in reverse order. + unshift @search_matches, $m; + } + $unique{$m}++; + } + + print "updated matches: ", scalar(@search_matches), " ", + join(", ", @search_matches) if DEBUG; +} + +sub get_history_match { + return $search_matches[$match_index]; +} + +sub prev_match { + + $match_index++; + if ($match_index > $#search_matches) { + $match_index = 0; + } + print "index now: $match_index" if DEBUG; +} + +sub next_match { + + $match_index--; + if ($match_index < 0) { + $match_index = $#search_matches; + } + print "index now: $match_index" if DEBUG; +} + +sub update_input { + my $match = get_history_match(); + Irssi::gui_input_set($match); + Irssi::gui_input_set_pos(length $match); +} + +sub handle_keypress { + my ($key) = @_; + + return unless $search_active; + + if ($key == 10) { # enter + print "selecting history and quitting" if DEBUG; + history_exit(); + return; + } + + if ($key == 18) { # Ctrl-R + print "skipping to prev match" if DEBUG; + prev_match(); + update_input(); + update_history_prompt(); + Irssi::signal_stop(); # prevent the bind from being re-triggered. + return; + } + + if ($key == 19) { # Ctrl-S + print "skipping to next match" if DEBUG; + next_match(); + update_input(); + update_history_prompt(); + + Irssi::signal_stop(); + return; + } + + if ($key == 7) { # Ctrl-G + print "aborting search" if DEBUG; + history_exit(); + + # cancel empties the inputline. + Irssi::gui_input_set(''); + Irssi::gui_input_set_pos(0); + + Irssi::signal_stop(); + return; + } + + if ($key == 127) { # DEL + + if (length $search_str) { + $search_str = substr($search_str, 0, -1); + print "Deleting char, now: $search_str" if DEBUG; + } + update_history_matches(); + update_history_prompt(); + + Irssi::signal_stop(); + return; + } + + # TODO: handle esc- sequences and arrow-keys? + + if ($key >= 32) { # printable + $search_str .= chr($key); + + update_history_matches(); + update_history_prompt(); + update_input(); + + Irssi::signal_stop(); + return; + } + + # any other key exits, for now. + history_exit(); + #Irssi::signal_stop(); +} |