<s> import os <EOL> import re <EOL> from . import keys <EOL> from . import ui <EOL> from . import readchar <EOL> from . import dirhandler <EOL> def get_selected_command_or_input ( search ) : <EOL> state = State ( search ) <EOL> ui . refresh ( state ) <EOL> prompt ( state ) <EOL> ui . erase ( ) <EOL> return state . input <EOL> def prompt ( state ) : <EOL> while True : <EOL> c = readchar . get_symbol ( ) <EOL> if c == keys . ENTER : <EOL> if state . get_matches ( ) : <EOL> state . append_match_to_input ( ) <EOL> break <EOL> elif c == keys . CTRL_F : <EOL> break <EOL> elif c == keys . TAB : <EOL> if state . get_matches ( ) : <EOL> state . append_match_to_input ( ) <EOL> elif c == keys . CTRL_C or c == keys . ESC : <EOL> state . reset_input ( ) <EOL> break <EOL> elif c == keys . CTRL_U : <EOL> state . clear_input ( ) <EOL> elif c == keys . BACKSPACE : <EOL> state . set_input ( state . input [ <NUM_LIT:0> : - <NUM_LIT:1> ] ) <EOL> elif c == keys . UP or c == keys . CTRL_K : <EOL> state . select_previous ( ) <EOL> elif c == keys . DOWN or c == keys . CTRL_J : <EOL> state . select_next ( ) <EOL> elif c == keys . LEFT or c == keys . CTRL_H : <EOL> state . go_back ( ) <EOL> elif c == keys . RIGHT or c == keys . CTRL_L : <EOL> if state . get_matches ( ) : <EOL> state . append_match_to_input ( ) <EOL> elif c < <NUM_LIT> and c >= <NUM_LIT:32> : <EOL> state . set_input ( state . input + chr ( c ) ) <EOL> ui . refresh ( state ) <EOL> class State ( object ) : <EOL> '''<STR_LIT>''' <EOL> def __init__ ( self , default_input ) : <EOL> self . _selected_command_index = <NUM_LIT:0> <EOL> self . matches = [ ] <EOL> self . default_input = default_input <EOL> self . set_input ( default_input ) <EOL> def get_matches ( self ) : <EOL> return self . matches <EOL> def reset_input ( self ) : <EOL> self . input = self . default_input <EOL> def set_input ( self , input ) : <EOL> self . input = input if input else "<STR_LIT>" <EOL> self . _update ( ) <EOL> def append_match_to_input ( self ) : <EOL> self . set_input ( os . path . join ( os . path . dirname ( self . input ) , self . get_selected_match ( ) ) ) <EOL> def go_back ( self ) : <EOL> isdir = is_dir ( self . input ) <EOL> input_stripped = self . input . rstrip ( os . sep ) <EOL> if not input_stripped : <EOL> return <EOL> input_splitted = input_stripped . split ( os . sep ) <EOL> entry_name = input_splitted [ - <NUM_LIT:1> ] <EOL> if isdir : <EOL> entry_name += os . sep <EOL> new_input = os . sep . join ( input_splitted [ <NUM_LIT:0> : - <NUM_LIT:1> ] ) <EOL> if new_input : <EOL> new_input += os . sep <EOL> self . set_input ( new_input ) <EOL> self . set_selected_entry ( entry_name ) <EOL> def clear_input ( self ) : <EOL> self . set_input ( "<STR_LIT>" ) <EOL> def clear_selection ( self ) : <EOL> self . _selected_command_index = <NUM_LIT:0> <EOL> def select_next ( self ) : <EOL> self . _selected_command_index = ( self . _selected_command_index + <NUM_LIT:1> ) % len ( self . matches ) if len ( self . matches ) else <NUM_LIT:0> <EOL> def select_previous ( self ) : <EOL> self . _selected_command_index = ( self . _selected_command_index - <NUM_LIT:1> ) % len ( self . matches ) if len ( self . matches ) else <NUM_LIT:0> <EOL> def _update ( self ) : <EOL> self . matches = get_matches ( os . getcwd ( ) , self . input ) <EOL> self . _selected_command_index = <NUM_LIT:0> <EOL> def get_output ( self ) : <EOL> return self . input <EOL> def get_selected_match ( self ) : <EOL> if len ( self . matches ) : <EOL> return self . matches [ self . _selected_command_index ] <EOL> else : <EOL> raise Exception ( '<STR_LIT>' ) <EOL> def set_selected_entry ( self , entry ) : <EOL> if not ( entry in self . matches ) : <EOL> return <EOL> self . _selected_command_index = self . matches . index ( entry ) <EOL> def get_matches ( root_dir , user_input ) : <EOL> start_dir = join_paths ( root_dir , os . path . dirname ( user_input ) ) <EOL> search_str = os . path . basename ( user_input ) <EOL> if not os . path . isdir ( start_dir ) : <EOL> return [ ] <EOL> source_files = dirhandler . get_source_files ( start_dir ) <EOL> filtered_files = filter_files ( source_files , search_str ) <EOL> sorted_files = sort_matches ( filtered_files , search_str ) <EOL> return sorted_files <EOL> def filter_files ( files , search_str ) : <EOL> """<STR_LIT>""" <EOL> matched = set ( ) <EOL> if not search_str : <EOL> for f in files : <EOL> f = f [ : _index_or_len ( f , os . sep ) + <NUM_LIT:1> ] <EOL> matched . add ( f ) <EOL> else : <EOL> search_str = search_str . lower ( ) <EOL> for f in files : <EOL> if search_str in f . lower ( ) : <EOL> index = f . lower ( ) . index ( search_str ) <EOL> trail = f [ index : ] <EOL> f = f [ : index + _index_or_len ( trail , os . sep ) + <NUM_LIT:1> ] <EOL> matched . add ( f ) <EOL> return matched <EOL> def sort_matches ( matches , string ) : <EOL> """<STR_LIT>""" <EOL> files = sorted ( matches , key = lambda s : s . lower ( ) ) <EOL> return sorted ( files , key = lambda p : get_weight ( p , string ) ) <EOL> def get_weight ( path , string ) : <EOL> """<STR_LIT>""" <EOL> weight = <NUM_LIT:0> <EOL> if not is_dir ( path ) : <EOL> weight += <NUM_LIT:1> <EOL> string = string . lower ( ) <EOL> p = path . rstrip ( os . sep ) . lower ( ) <EOL> path_elems = p . split ( os . sep ) <EOL> weight += min ( len ( path_elems ) * <NUM_LIT:1000> , <NUM_LIT> ) <EOL> if not string : <EOL> return weight <EOL> elm = next ( e for e in path_elems if string in e ) <EOL> elm_words = [ _f for _f in re . split ( '<STR_LIT>' , elm ) if _f ] <EOL> if string in elm_words : <EOL> if len ( elm_words ) > <NUM_LIT:1> : <EOL> weight += <NUM_LIT:10> * ( min ( elm_words . index ( string ) , <NUM_LIT:8> ) + <NUM_LIT:1> ) <EOL> else : <EOL> if elm . startswith ( string ) : <EOL> weight += <NUM_LIT:10> * <NUM_LIT:2> <EOL> else : <EOL> weight += <NUM_LIT:10> * ( <NUM_LIT:10> + min ( elm . index ( string ) , <NUM_LIT> ) ) <EOL> return weight <EOL> def join_paths ( p1 , p2 ) : <EOL> p1 = ( os . path . expandvars ( os . path . expanduser ( p1 ) ) ) <EOL> p2 = ( os . path . expandvars ( os . path . expanduser ( p2 ) ) ) <EOL> return os . path . normpath ( os . path . join ( p1 , p2 ) ) <EOL> def _index_or_len ( s , c ) : <EOL> if c in s : <EOL> return s . index ( c ) <EOL> else : <EOL> return len ( s ) <EOL> def is_dir ( p ) : <EOL> if p . endswith ( os . sep ) : <EOL> return True <EOL> return False </s>
