PFR submission: type-ahead 
Author Message
 PFR submission: type-ahead

# comments, improvements, etc invited...
##
# I've never used this for "live" type-ahead (like what you see in
# web browsers' location fields, or what you seen MicroSoft's appps),
# but I do use it to allow me to type less than a full string in
# contexts where I might want to be lazy, and the list of possible
# strings I might have been trying to type are known beforehand by
# the script.
##
# Of course it works the way that makes sense to me, so modify
# as needed to have it make sense to you :)
##
# I've prettied it up a bit from the code I actually use, so
# please forgive me if I've introduced typos...
##


        # Copyright relinquished 1999

        # This code is in the public domain.
        ##
        # Given a first argument of a string typed by user and then
        # additional arguments of possible options for available
        # commands (or whatever), try to "type ahead" to complete
        # their input into one of the available menu options.
        ##
        # This will be done case-insensitively. When the user has
        # typed something that matches multiple menu options, we will
        # first prefer shorter menu options (*least* undertyped), so
        # 'pe' will match 'perl' before matching 'pearls'. When there
        # are multiple equally-short possible matches, we will prefer
        # the option which occured first in our menu of options.
        # The return value will be undef for no match, or the menu
        # item which "best" matched if we have one or more matches.
        # That returned item will be returned in the same case as it
        # occured in our menu, even though matching was done without
        # case sensitivity.

                # [lc typed input, length thereof]
        my %seen;
                # %{ $seen{length} }
                        # used to track unique lengths of possible matches

                        # used to store possible matches of each $length
        # read the following from bottom to the top of course...

                # mapped to array ref of matches at each length
                        map  { $seen{matches}{$_} }
                # sorting least undertyped (shorter) lengths first
                        sort { $b <=> $a }
                # keep only one instance of each length
                        grep { !$seen{length}{$_}++ }
                # mapped to the matching option's length
                        map  {
                                # this push business does not affect our map,
                                # but allows us to store the possible match
                                # by length, so we can eventually prefer the
                                # *least* undertyped of all possible matches
                                        push(

                                                $_->[0]
                                        );
                                # our acutal map value: the option's length
                                        $_->[1];
                        }
                # keeping only those which are type-ahead matches:
                        grep { $t->[0] eq lc( substr($_->[0], 0, $t->[1]) ) }
                # mapped to [the option, the length thereof]
                        map  { [$_, length($_)] }
                # the menu of each available option:

        );

        ##
        # Each ref'ed array contains possible matches of a specific
        # length, and earlier array refs are for shorter matches.
        ##
        # Within each ref'ed array, the equally-long matches are
        # sorted to the order in which they occured in the original
        # menu of possible options.
        ##
        # I only care about the first item in the first array, but


Quote:
}

--== Sent via Deja.com http://www.*-*-*.com/
---Share what you know. Learn what you don't.---


Sun, 04 Nov 2001 03:00:00 GMT  
 PFR submission: type-ahead

er... "zero or more" rather

-matt

--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---



Wed, 07 Nov 2001 03:00:00 GMT  
 PFR submission: type-ahead

Quote:

># comments, improvements, etc invited...


How about:

Change:

Quote:
>            # mapped to array ref of matches at each length
>                    map  { $seen{matches}{$_} }

To:
               # mapped to list of matches in order first by length,
               # then by original order

and change:

Quote:

>    ##
>    # Each ref'ed array contains possible matches of a specific
>    # length, and earlier array refs are for shorter matches.
>    ##
>    # Within each ref'ed array, the equally-long matches are
>    # sorted to the order in which they occured in the original
>    # menu of possible options.
>    ##
>    # I only care about the first item in the first array, but



to:
       # return the preferred match (or undef if there were none)
       return $matches[0];

Alternatively, you could hold the original order as a third element in
the Schwartzian array ref created in your first-performed map and skip
%seen and a map and a grep and make your sort more complicated.

This would depend of course on how many potential matches there were and
how many of each length.



Thu, 08 Nov 2001 03:00:00 GMT  
 PFR submission: type-ahead

In most cases, I only want one return value. ...but sometimes
I like to have all the equally-least-undertyped values, and
I can imagine that one day I might want all possible matches.

The initial code would let folks make modifications such as
what you'd suggested to get back whichever matches they
wanted in the format they want.

If you know for certain that you'll only want one type-ahead
match back, and you want it to be the match which is least-
undertyped, and earliest in the menu list when there is a tie
for least-undertyped (in other words you want it to behave
like the initial version, w/o all the extra futzing to allow
for easier customization) then you could do something like:




                grep { $t->[0] eq lc( substr($_->[0], 0, $t->[1]) ) }
                map      { [$_, length($_)] }

        );


                $match = $item if $item->[1] < $match->[1];
        }
        return $match;

Quote:
}

-matt

--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---



Fri, 09 Nov 2001 03:00:00 GMT  
 
 [ 4 post ] 

 Relevant Pages 

1. Nonmember submission: Re: Nonmember submission: perl/Tk on RedHat 9

2. Nonmember submission: Re: Nonmember submission: re linux/tk/button memory leak

3. Nonmember submission: Re: Nonmember submission: Display an image

4. Nonmember submission: Re: Tk-core TIP Submissions

5. Easy way to peek ahead in <>

6. range operator and look ahead

7. PFR: Compute offset of local timezone from UTC

8. PFR: Comput offset of local time from UTC

9. PFR: Convert engineering notation to arbitrary fixed-point format

10. PFR gone?

11. PFR: read_file, write_file

12. Makebak: script for PFR

 

 
Powered by phpBB® Forum Software