diff options
| author | Tom Feist <shabble@metavore.org> | 2010-12-30 01:08:18 +0000 | 
|---|---|---|
| committer | Tom Feist <shabble@metavore.org> | 2010-12-30 01:08:18 +0000 | 
| commit | d01a9573ada4b6a20ed506d10f0286754e738b08 (patch) | |
| tree | 54da3d9c47bb78259d24900678af772207ac8112 /ido-mode | |
| parent | ido_switch: create hilight for numbers, and fix bugs with regex match impleme... (diff) | |
| download | irssi-scripts-d01a9573ada4b6a20ed506d10f0286754e738b08.tar.gz irssi-scripts-d01a9573ada4b6a20ed506d10f0286754e738b08.zip | |
ido_switch: general refactor of code for more DRY. Beginning of full listing
available with <tab>.
Diffstat (limited to 'ido-mode')
| -rw-r--r-- | ido-mode/ido_switcher.pl | 755 | 
1 files changed, 471 insertions, 284 deletions
| diff --git a/ido-mode/ido_switcher.pl b/ido-mode/ido_switcher.pl index 3a6a99c..eca29ff 100644 --- a/ido-mode/ido_switcher.pl +++ b/ido-mode/ido_switcher.pl @@ -44,7 +44,7 @@ $VERSION = '2.0';     authors     => 'Tom Feist, Wouter Coekaerts',     contact     => 'shabble+irssi@metavore.org, shabble@#irssi/freenode',     name        => 'ido_switcher', -   description => 'Select window(-items) using ido-mode like search interface', +   description => 'Select window[-items] using an ido-mode like search interface',     license     => 'GPLv2 or later',     url         => 'http://github.com/shabble/irssi-scripts/tree/master/history-search/',     changed     => '24/7/2010' @@ -63,11 +63,13 @@ $VERSION = '2.0';  # TODO tab - display all possibilities in window (clean up afterwards)  #       how exactly will this work?  # DONE sort by recent activity/recently used windows (separate commands?) +# TODO should space auto-move forward to next window for easy stepping through +#      sequential/active windows?  my $input_copy     = '';  my $input_pos_copy = 0; -my $ido_switch_active = 0; # for intercepting keystrokes +my $ido_switch_active = 0;      # for intercepting keystrokes  my @window_cache   = ();  my @search_matches = (); @@ -76,6 +78,9 @@ my $match_index = 0;  my $search_str  = '';  my $active_only = 0; +my $mode_type = 'ALL'; +my @mode_cache; +  my $need_clear = 0;  my $sort_ordering = "start-asc"; @@ -87,12 +92,15 @@ my $ido_use_flex;  my $DEBUG_ENABLED = 0;  sub DEBUG () { $DEBUG_ENABLED } -#sub MODE_A () { 0 } # all -#sub MODE_Q () { 1 } # queries + +sub MODE_WIN () { 0 } # windows +sub MODE_NET () { 1 } # chatnets  #sub MODE_C () { 2 } # channels  #sub MODE_S () { 3 } # select server  #sub MODE_W () { 4 } # select window +my $MODE = MODE_WIN; +  # check we have uberprompt loaded.  sub _print { @@ -117,23 +125,59 @@ sub _print_clear {  sub print_all_matches {      my $msg = join(", ", map { $_->{name} } @search_matches); -    _print($msg); -} +    my $message_header = "Windows:"; +    my $win = Irssi::active_win(); +    my $win_width = $win->{width} || 80; + +    # TODO: needs to prefix ambig things with chatnet, or maybe order in groups +    # by chatnet with newlines. + +    # Also, colourise the channel list. + +    my $col_width; + +    for (@search_matches) { +        my $len = length($_->{name}); +        $col_width = $len if $len > $col_width; +    } + +    my $cols = int($win_width / $col_width); + +    my @lines; +    my $i = 0; +    my @line; -sub script_is_loaded { -    my $name = shift; -    _debug_print "Checking if $name is loaded"; -    no strict 'refs'; -    my $retval = defined %{ "Irssi::Script::${name}::" }; -    use strict 'refs'; +    for my $item (@search_matches) { +        my $name = $item->{name}; +        push @line, sprintf('%.*s', $col_width, $name); +        if ($i == $cols) { +            push @lines, join ' ', @line; +            @line = (); +            $i = 0; +        } +    } +    # flush rest out. +    push @lines, join ' ', @line; -    return $retval; +    _print($message_header); +    _print($_) for (@lines); +    #_print("Longtest name: $longest_name");  } +  sub script_is_loaded { +      my $name = shift; +      _debug_print "Checking if $name is loaded"; +      no strict 'refs'; +      my $retval = defined %{ "Irssi::Script::${name}::" }; +      use strict 'refs'; + +      return $retval; +  } +  unless (script_is_loaded('uberprompt')) {      _print "This script requires 'uberprompt.pl' in order to work. " -     . "Attempting to load it now..."; +      . "Attempting to load it now...";      Irssi::signal_add('script error', 'load_uberprompt_failed');      Irssi::command("script load uberprompt.pl"); @@ -147,7 +191,7 @@ unless (script_is_loaded('uberprompt')) {  sub load_uberprompt_failed {      Irssi::signal_remove('script error', 'load_uberprompt_failed');      _print "Script could not be loaded. Script cannot continue. " -      . "Check you have uberprompt.pl installed in your path and " +        . "Check you have uberprompt.pl installed in your path and "          .  "try again.";      die "Script Load Failed: " . join(" ", @_);  } @@ -183,6 +227,7 @@ sub ido_switch_start {      $ido_switch_active = 1;      $search_str        = '';      $match_index       = 0; +    $mode_type         = 'ALL';      # refresh in case we toggled it last time.      $ido_use_flex   = Irssi::settings_get_bool('ido_use_flex'); @@ -193,13 +238,44 @@ sub ido_switch_start {      _update_cache();      update_matches(); -    update_prompt(); +    update_window_select_prompt();  }  sub _update_cache {      @window_cache = get_all_windows();  } +sub _build_win_obj { +    my ($win, $win_item) = @_; + +    my @base = ( +                b_pos         => -1, +                e_pos         => -1, +                hilight_field => 'name', +                active        => $win->{data_level} > 0, +                num           => $win->{refnum}, +                server        => $win->{active_server}, + +               ); + +    if (defined($win_item)) { +        return ( +                @base, +                name     => $win_item->{visible_name}, +                type     => $win_item->{type}, +                itemname => $win_item->{name}, +                active   => $win_item->{data_level} > 0, + +               ) +    } else { +        return ( +                @base, +                name => $win->{name}, +                type => 'WIN', +               ); +    } +} +  sub get_all_windows {      my @ret; @@ -208,394 +284,505 @@ sub get_all_windows {          if ($win->{name} ne '') {              _debug_print "Adding window: " . $win->{name}; -            push @ret, { -                        name   => $win->{name}, -                        type   => 'WINDOW', -                        num    => $win->{refnum}, -                        server => $win->{active_server}, -                        active => $win->{data_level} > 0, -                        b_pos  => -1, -                        e_pos  => -1, -                        hilight_field => 'name', -                       }; +            push @ret, { _build_win_obj($win, undef) };          } -          if (scalar @items) {              foreach my $item (@items) {                  _debug_print "Adding windowitem: " . $item->{visible_name}; - -                push @ret, { -                            name     => $item->{visible_name}, -                            type     => $item->{type}, -                            server   => $item->{server}, -                            num      => $win->{refnum}, -                            itemname => $item->{name}, -                            active   => $win->{data_level} > 0, -                            b_pos    => -1, -                            e_pos    => -1, -                            hilight_field => 'name', -                           }; +                push @ret, { _build_win_obj($win, $item) };              }          } else { -            #_debug_print "Error occurred reading info from window: $win"; +            _debug_print "Error occurred reading info from window: $win";              #_debug_print Dumper($win);          }      } -      @ret = _sort_windows(\@ret);      return @ret; +  } -sub _sort_windows { -    my $list_ref = shift; -    my @ret = @$list_ref; +    sub _sort_windows { +        my $list_ref = shift; +        my @ret = @$list_ref; -    @ret = sort { $a->{num} <=> $b->{num} } @ret; +        @ret = sort { $a->{num} <=> $b->{num} } @ret; -    return @ret; -} +        return @ret; +    } -sub ido_switch_select { -    my ($selected, $is_refnum) = @_; +    sub ido_switch_select { +        my ($selected, $is_refnum) = @_; -    _debug_print "Selecting window: " . $selected->{name}; +        _debug_print "Selecting window: " . $selected->{name}; -    Irssi::command("WINDOW GOTO " . $selected->{name}); +        Irssi::command("WINDOW GOTO " . $selected->{name}); + +        if ($selected->{type} ne 'WINDOW') { +            _debug_print "Selecting window item: " . $selected->{itemname}; +            Irssi::command("WINDOW ITEM GOTO " . $selected->{itemname}); +        } -    if ($selected->{type} ne 'WINDOW') { -        _debug_print "Selecting window item: " . $selected->{itemname}; -        Irssi::command("WINDOW ITEM GOTO " . $selected->{itemname});      } -} +    sub ido_switch_exit { +        $ido_switch_active = 0; -sub ido_switch_exit { -    $ido_switch_active = 0; +        _print_clear(); -    _print_clear(); +        Irssi::gui_input_set($input_copy); +        Irssi::gui_input_set_pos($input_pos_copy); +        Irssi::signal_emit('change prompt', '', 'UP_INNER'); +    } -    Irssi::gui_input_set($input_copy); -    Irssi::gui_input_set_pos($input_pos_copy); -    Irssi::signal_emit('change prompt', '', 'UP_INNER'); -} +    sub _order_matches { +        return @_[$match_index .. $#_, +                  0            .. $match_index - 1] +    } -sub _order_matches { -    return @_[$match_index .. $#_, -              0            .. $match_index - 1] -} +    sub update_window_select_prompt { + +        # take the top $ido_show_count entries and display them. +        my $match_count  = scalar @search_matches; +        my $show_count   = $ido_show_count; +        my $match_string = '[No match'; + +        $show_count = $match_count if $match_count < $show_count; + +        if ($show_count > 0) { # otherwise, default message above. +            _debug_print "Showing: $show_count matches"; + +            my @ordered_matches = _order_matches(@search_matches); + +            my %uniq; +            # determine which items are non-unique, if any. +            foreach my $res (@ordered_matches) { +                my $name = $res->{name}; + +                if (exists $uniq{$name}) { +                    push @{$uniq{$name}}, $res; +                } else { +                    $uniq{$name} = []; +                    push @{$uniq{$name}}, $res; +                } +            } + +            # and set a flag to ensure they have their network tag applied +            # to them when drawn. +            foreach my $name (keys %uniq) { +                my @values = @{$uniq{$name}}; +                if (@values > 1) { +                    $_->{display_net} = 1 for @values; +                } +            } -sub update_prompt { +            # +            my @display = @ordered_matches[0..$show_count - 1]; -    #TODO: refactor this beast. +            # show the first entry in green -    # take the top $ido_show_count entries and display them. -    my $match_count  = scalar @search_matches; -    my $show_count   = $ido_show_count; -    my $match_string = '(no matches) '; +            my $first = shift @display; +            my $formatted_first = _format_display_entry($first, '%g'); +            unshift @display, $formatted_first; -    $show_count = $match_count if $match_count < $show_count; +            # and array-slice-map the rest to be red. +            # or yellow, if they have unviewed activity -    if ($show_count > 0) { -        _debug_print "Showing: $show_count matches"; +            @display[1..$#display] +              = map +              { +                  _format_display_entry($_, $_->{active}?'%y':'%r') -        my @ordered_matches = _order_matches(@search_matches); -        my @display = @ordered_matches[0..$show_count - 1]; +              } @display[1..$#display]; + +            # join em all up +            $match_string = join ', ', @display; +        } -        # show the first entry in green +        my @indicators; -        unshift(@display, _format_display_entry(shift(@display), '%g')); +        # indicator if flex mode is being used (C-f to toggle) +        push @indicators, $ido_use_flex ? 'Flex' : 'Exact'; +        push @indicators, 'Active' if $active_only; +        push @indicators, ucfirst(lc($mode_type)); -        # and array-slice-map the rest to be red. -        @display[1..$#display] -          = map { _format_display_entry($_, '%r') } @display[1..$#display]; +        my $flex = sprintf(' %%k[%%n%s%%k]%%n ', join ',', @indicators); -        # join em all up -        $match_string = join ', ', @display; +        my $search = ''; +        $search = (sprintf '`%s\': ', $search_str) if length $search_str; + +        Irssi::signal_emit('change prompt', $flex . $search . $match_string, +                           'UP_INNER');      } -    # indicator if flex mode is being used (C-f to toggle) -    my @indicators = ($ido_use_flex ? 'Flex' : 'Exact'); -    push @indicators, 'Active' if $active_only; -    my $flex = sprintf(' %%k[%%n%s%%k]%%n ', join ',', @indicators); -    my $search = ''; -    $search = (sprintf '`%s\': ', $search_str) if length $search_str; +    sub _format_display_entry { +        my ($obj, $colour) = @_; -    Irssi::signal_emit('change prompt', $flex . $search . $match_string, -                       'UP_INNER'); -} +        my $field     = $obj->{hilight_field}; +        my $hilighted = { name => $obj->{name}, num => $obj->{num} }; +        my $show_tag  = $obj->{display_net} || 0; -sub _format_display_entry { -    my ($obj, $colour) = @_; +        if ($obj->{b_pos} >= 0 && $obj->{e_pos} > $obj->{b_pos}) { +            substr($hilighted->{$field}, $obj->{e_pos}, 0) = '%_'; +            substr($hilighted->{$field}, $obj->{b_pos}, 0) = '%_'; +            _debug_print "Showing $field as: " . $hilighted->{$field} +        } -    my $field = $obj->{hilight_field}; -    my $hilighted = { name => $obj->{name}, num => $obj->{num} }; +        return sprintf('%s%s:%s%s%%n', +                       $colour, +                       $hilighted->{num}, +                       $show_tag ? _format_display_tag($obj) : '', +                       $hilighted->{name}); +    } -    if ($obj->{b_pos} >= 0 && $obj->{e_pos} > $obj->{b_pos}) { -        substr($hilighted->{$field}, $obj->{e_pos}, 0) = '%_'; -        substr($hilighted->{$field}, $obj->{b_pos}, 0) = '%_'; -        _debug_print "Showing $field as: " . $hilighted->{$field} +    sub _format_display_tag { +        my $obj = shift; +        if (defined $obj->{server}) { +            my $server = $obj->{server}; +            my $tag = $server->{tag}; +            return $tag . '/' if length $tag; +        } +        return '';      } -    return sprintf('%s%s:%s%%n', $colour, $hilighted->{num}, $hilighted->{name}); -} +    sub _check_active { +        my ($obj) = @_; +        return 1 unless $active_only; +        return $obj->{active}; +    } -sub _check_active { -    my ($obj) = @_; -    return 1 unless $active_only; -    return $obj->{active}; -} +    sub update_matches { -sub update_matches { +        _update_cache() unless $search_str; -    _update_cache() unless $search_str; +        if ($mode_type ne 'ALL') { +            @mode_cache = @window_cache; +            @window_cache = grep { print "Type: " . $_->{type}; $_->{type} eq $mode_type } @window_cache; +        } else { +            @window_cache = @mode_cache if @mode_cache; +        } -    if ($search_str =~ m/^\d+$/) { +        if ($search_str =~ m/^\d+$/) { -        @search_matches = -          grep { -              _check_active($_) and regex_match($_, 'num') -          } @window_cache; +            @search_matches = +              grep { +                  _check_active($_) and regex_match($_, 'num') +              } @window_cache; -    } elsif ($ido_use_flex) { +        } elsif ($ido_use_flex) { -        @search_matches = -          grep { -              _check_active($_) and flex_match($_) >= 0 -          } @window_cache; +            @search_matches = +              grep { +                  _check_active($_) and flex_match($_) >= 0 +              } @window_cache; -    } else { +        } else { -        @search_matches = -          grep { -              _check_active($_) and regex_match($_, 'name') -          } @window_cache; -    } +            @search_matches = +              grep { +                  _check_active($_) and regex_match($_, 'name') +              } @window_cache; +        } -} +    } -sub regex_match { -    my ($obj, $field) = @_; -    if ($obj->{$field} =~ m/^(.*?)\Q$search_str\E(.*?)$/i) { -        $obj->{hilight_field} = $field; -        $obj->{b_pos} = length $1; -        $obj->{e_pos} = $obj->{b_pos} + length($search_str); -        return 1; +    sub regex_match { +        my ($obj, $field) = @_; +        if ($obj->{$field} =~ m/^(.*?)\Q$search_str\E(.*?)$/i) { +            $obj->{hilight_field} = $field; +            $obj->{b_pos} = length $1; +            $obj->{e_pos} = $obj->{b_pos} + length($search_str); +            return 1; +        } +        return 0;      } -    return 0; -} -sub flex_match { -    my ($obj) = @_; +    sub flex_match { +        my ($obj) = @_; -    my $pattern = $search_str; -    my $source  = $obj->{name}; +        my $pattern = $search_str; +        my $source  = $obj->{name}; -    _debug_print "Flex match: $pattern / $source"; +        _debug_print "Flex match: $pattern / $source"; -    # default to matching everything if we don't have a pattern to compare -    # against. +        # default to matching everything if we don't have a pattern to compare +        # against. -    return 0 unless $pattern; +        return 0 unless $pattern; -    my @chars = split '', lc($pattern); -    my $ret = -1; -    my $first = 0; +        my @chars = split '', lc($pattern); +        my $ret = -1; +        my $first = 0; -    my $lc_source = lc($source); +        my $lc_source = lc($source); -    $obj->{hilight_field} = 'name'; +        $obj->{hilight_field} = 'name'; -    foreach my $char (@chars) { -        my $pos = index($lc_source, $char, $ret); -        if ($pos > -1) { +        foreach my $char (@chars) { +            my $pos = index($lc_source, $char, $ret); +            if ($pos > -1) { -            # store the beginning of the match -            $obj->{b_pos} = $pos unless $first; -            $first = 1; +                # store the beginning of the match +                $obj->{b_pos} = $pos unless $first; +                $first = 1; -            _debug_print("matched: $char at $pos in $source"); -            $ret = $pos + 1; +                _debug_print("matched: $char at $pos in $source"); +                $ret = $pos + 1; -        } else { +            } else { -            $obj->{b_pos} = $obj->{e_pos} = -1; -            _debug_print "Flex returning: -1"; +                $obj->{b_pos} = $obj->{e_pos} = -1; +                _debug_print "Flex returning: -1"; -            return -1; +                return -1; +            }          } -    } -    _debug_print "Flex returning: $ret"; +        _debug_print "Flex returning: $ret"; -    #store the end of the match. -    $obj->{e_pos} = $ret; +        #store the end of the match. +        $obj->{e_pos} = $ret; -    return $ret; -} +        return $ret; +    } -sub prev_match { +    sub prev_match { -    $match_index++; -    if ($match_index > $#search_matches) { -        $match_index = 0; +        $match_index++; +        if ($match_index > $#search_matches) { +            $match_index = 0; +        } + +        _debug_print "index now: $match_index";      } -    _debug_print "index now: $match_index"; -} +    sub next_match { -sub next_match { +        $match_index--; +        if ($match_index < 0) { +            $match_index = $#search_matches; +        } +        _debug_print "index now: $match_index"; +    } -    $match_index--; -    if ($match_index < 0) { -        $match_index = $#search_matches; +    sub get_window_match { +        return $search_matches[$match_index];      } -    _debug_print "index now: $match_index"; -} -sub get_window_match { -    return $search_matches[$match_index]; -} +    sub handle_keypress { +        my ($key) = @_; -sub handle_keypress { -	my ($key) = @_; +        return unless $ido_switch_active; -    return unless $ido_switch_active; +        if ($key == 0) {        # C-SPC? +            _debug_print "\%_Ctrl-space\%_"; -    if ($key == 0) { # C-SPC? -        _debug_print "\%_Ctrl-space\%_"; +            $search_str = ''; +            @window_cache = @search_matches; +            update_window_select_prompt(); -        $search_str = ''; -        @window_cache = @search_matches; -        update_prompt(); +            Irssi::signal_stop(); +            return; +        } -        Irssi::signal_stop(); -        return; -    } +        if ($key == 3) {        # C-c +            _print_clear(); +            Irssi::signal_stop(); +            return; +        } +        if ($key == 4) {        # C-d +            update_network_select_prompt(); +            Irssi::signal_stop(); +            return; +        } -    if ($key == 3) { # C-C -        _print_clear(); -        Irssi::signal_stop(); -        return; -    } +        if ($key == 5) {        # C-e +            $active_only = not $active_only; +            Irssi::signal_stop(); +            update_matches(); +            update_window_select_prompt(); +            return; +        } -    if ($key == 5) { # C-e -        $active_only = not $active_only; -        Irssi::signal_stop(); -        update_matches(); -        update_prompt(); -        return; -    } +        if ($key == 6) {        # C-f -    if ($key == 6) { # C-f +            $ido_use_flex = not $ido_use_flex; +            _update_cache(); -        $ido_use_flex = not $ido_use_flex; -        _update_cache(); +            update_matches(); +            update_window_select_prompt(); -        update_matches(); -        update_prompt(); +            Irssi::signal_stop(); +            return; +        } +        if ($key == 9) {        # TAB +            _debug_print "Tab complete"; +            print_all_matches(); +            Irssi::signal_stop(); +        } -        Irssi::signal_stop(); -        return; -    } -    if ($key == 9) { # TAB -        _debug_print "Tab complete"; -        print_all_matches(); -        Irssi::signal_stop(); -    } +        if ($key == 10) {       # enter +            _debug_print "selecting history and quitting"; +            my $selected_win = get_window_match(); +            ido_switch_select($selected_win); -	if ($key == 10) { # enter -        _debug_print "selecting history and quitting"; -        my $selected_win = get_window_match(); -        ido_switch_select($selected_win); +            ido_switch_exit(); +            Irssi::signal_stop(); +            return; +        } -        ido_switch_exit(); -        Irssi::signal_stop(); -        return; -	} +        if ($key == 18) {       # Ctrl-R +            _debug_print "skipping to prev match"; +            #update_matches(); +            next_match(); -    if ($key == 18) { # Ctrl-R -        _debug_print "skipping to prev match"; -        #update_matches(); -        next_match(); +            update_window_select_prompt(); +            Irssi::signal_stop(); # prevent the bind from being re-triggered. +            return; +        } -        update_prompt(); -        Irssi::signal_stop(); # prevent the bind from being re-triggered. -        return; -    } +        if ($key == 17) {       # Ctrl-q +            if ($mode_type eq 'CHANNEL') { +                $mode_type = 'QUERY'; +            } elsif ($mode_type eq 'QUERY') { +                $mode_type = 'ALL'; +            } else { # ALL +                $mode_type = 'CHANNEL'; +            } +            update_matches(); +            update_window_select_prompt(); +            Irssi::signal_stop(); +        } -    if ($key == 19) {  # Ctrl-S -        _debug_print "skipping to next match"; -        prev_match(); +        if ($key == 19) {       # Ctrl-s +            _debug_print "skipping to next match"; +            prev_match(); -        #update_matches(); -        update_prompt(); +            #update_matches(); +            update_window_select_prompt(); -        Irssi::signal_stop(); -        return; -    } +            Irssi::signal_stop(); +            return; +        } -    if ($key == 7) { # Ctrl-G -        _debug_print "aborting search"; -        ido_switch_exit(); -        Irssi::signal_stop(); -        return; -    } +        if ($key == 7) {        # Ctrl-g +            _debug_print "aborting search"; +            ido_switch_exit(); +            Irssi::signal_stop(); +            return; +        } -    if ($key == 21) { # Ctrl-U -        $search_str = ''; -        update_matches(); -        update_prompt(); +        if ($key == 21) {       # Ctrl-u +            $search_str = ''; +            update_matches(); +            update_window_select_prompt(); -        Irssi::signal_stop(); -        return; +            Irssi::signal_stop(); +            return; -    } +        } + +        if ($key == 127) {      # DEL + +            if (length $search_str) { +                $search_str = substr($search_str, 0, -1); +                _debug_print "Deleting char, now: $search_str"; +            } -    if ($key == 127) { # DEL +            update_matches(); +            update_window_select_prompt(); -        if (length $search_str) { -            $search_str = substr($search_str, 0, -1); -            _debug_print "Deleting char, now: $search_str"; +            Irssi::signal_stop(); +            return;          } -        update_matches(); -        update_prompt(); +        # TODO: handle esc- sequences and arrow-keys? + +        if ($key == 27) {       # Esc +            ido_switch_exit(); +            return; +        } + +        if ($key == 32) {       # space +            my $selected_win = get_window_match(); +            ido_switch_select($selected_win); +            Irssi::signal_stop(); + +            return; +        } + +        if ($key > 32) {        # printable +            $search_str .= chr($key); + +            update_matches(); +            update_window_select_prompt(); + +            Irssi::signal_stop(); +            return; +        } +        # ignore all other keys.          Irssi::signal_stop(); -        return;      } -    # TODO: handle esc- sequences and arrow-keys? +    ido_switch_init(); -    if ($key == 27) { # Esc -        ido_switch_exit(); -        return; -    } +    sub update_network_select_prompt { -    if ($key == 32) { # space -        my $selected_win = get_window_match(); -        ido_switch_select($selected_win); -        Irssi::signal_stop(); +        my @servers = map +          { +              { +                  name => $_->{tag}, +                  type => 'SERVER', +                  active => 0, +                  e_pos => -1, +                  b_pos => -1, +                  hilight_field => 'name', +              } +          } Irssi::servers(); -        return; -    } +        my $match_count  = scalar @servers; +        my $show_count   = $ido_show_count; +        my $match_string = '(no matches) '; -    if ($key > 32) { # printable -        $search_str .= chr($key); +        $show_count = $match_count if $match_count < $show_count; -        update_matches(); -        update_prompt(); +        if ($show_count > 0) { +            _debug_print "Showing: $show_count matches"; -        Irssi::signal_stop(); -        return; -    } +            my @ordered_matches = _order_matches(@servers); +            my @display = @ordered_matches[0..$show_count - 1]; -    # ignore all other keys. -    Irssi::signal_stop(); -} +            # show the first entry in green + +            unshift(@display, _format_display_entry(shift(@display), '%g')); + +            # and array-slice-map the rest to be red (or yellow for active) +            @display[1..$#display] +              = map +              { +                  _format_display_entry($_, $_->{active}?'%y':'%r') -ido_switch_init(); +              } @display[1..$#display]; +            # join em all up +            $match_string = join ', ', @display; +        } + +        my @indicators; + +        # indicator if flex mode is being used (C-f to toggle) +        push @indicators, $ido_use_flex ? 'Flex' : 'Exact'; +        push @indicators, 'Active' if $active_only; + +        my $flex = sprintf(' %%k[%%n%s%%k]%%n ', join ',', @indicators); + +        my $search = ''; +        $search = (sprintf '`%s\': ', $search_str) if length $search_str; + +        Irssi::signal_emit('change prompt', $flex . $search . $match_string, +                           'UP_INNER'); + +    } | 
