<s> from __future__ import unicode_literals <EOL> from six . moves import zip_longest , range <EOL> from prompt_toolkit . filters import HasCompletions , IsDone , Condition , to_cli_filter <EOL> from prompt_toolkit . mouse_events import MouseEventTypes <EOL> from prompt_toolkit . token import Token <EOL> from prompt_toolkit . utils import get_cwidth <EOL> from . containers import Window , HSplit , ConditionalContainer , ScrollOffsets <EOL> from . controls import UIControl , UIContent <EOL> from . dimension import LayoutDimension <EOL> from . margins import ScrollbarMargin <EOL> from . screen import Point , Char <EOL> import math <EOL> __all__ = ( <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> ) <EOL> class CompletionsMenuControl ( UIControl ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . token = Token . Menu . Completions <EOL> def has_focus ( self , cli ) : <EOL> return False <EOL> def preferred_width ( self , cli , max_available_width ) : <EOL> complete_state = cli . current_buffer . complete_state <EOL> if complete_state : <EOL> menu_width = self . _get_menu_width ( <NUM_LIT> , complete_state ) <EOL> menu_meta_width = self . _get_menu_meta_width ( <NUM_LIT> , complete_state ) <EOL> return menu_width + menu_meta_width <EOL> else : <EOL> return <NUM_LIT:0> <EOL> def preferred_height ( self , cli , width , max_available_height , wrap_lines ) : <EOL> complete_state = cli . current_buffer . complete_state <EOL> if complete_state : <EOL> return len ( complete_state . current_completions ) <EOL> else : <EOL> return <NUM_LIT:0> <EOL> def create_content ( self , cli , width , height ) : <EOL> """<STR_LIT>""" <EOL> complete_state = cli . current_buffer . complete_state <EOL> if complete_state : <EOL> completions = complete_state . current_completions <EOL> index = complete_state . complete_index <EOL> menu_width = self . _get_menu_width ( width , complete_state ) <EOL> menu_meta_width = self . _get_menu_meta_width ( width - menu_width , complete_state ) <EOL> show_meta = self . _show_meta ( complete_state ) <EOL> def get_line ( i ) : <EOL> c = completions [ i ] <EOL> is_current_completion = ( i == index ) <EOL> result = self . _get_menu_item_tokens ( c , is_current_completion , menu_width ) <EOL> if show_meta : <EOL> result += self . _get_menu_item_meta_tokens ( c , is_current_completion , menu_meta_width ) <EOL> return result <EOL> return UIContent ( get_line = get_line , <EOL> cursor_position = Point ( x = <NUM_LIT:0> , y = index or <NUM_LIT:0> ) , <EOL> line_count = len ( completions ) , <EOL> default_char = Char ( '<STR_LIT:U+0020>' , self . token ) ) <EOL> return UIContent ( ) <EOL> def _show_meta ( self , complete_state ) : <EOL> """<STR_LIT>""" <EOL> return any ( c . display_meta for c in complete_state . current_completions ) <EOL> def _get_menu_width ( self , max_width , complete_state ) : <EOL> """<STR_LIT>""" <EOL> return min ( max_width , max ( get_cwidth ( c . display ) <EOL> for c in complete_state . current_completions ) + <NUM_LIT:2> ) <EOL> def _get_menu_meta_width ( self , max_width , complete_state ) : <EOL> """<STR_LIT>""" <EOL> if self . _show_meta ( complete_state ) : <EOL> return min ( max_width , max ( get_cwidth ( c . display_meta ) <EOL> for c in complete_state . current_completions ) + <NUM_LIT:2> ) <EOL> else : <EOL> return <NUM_LIT:0> <EOL> def _get_menu_item_tokens ( self , completion , is_current_completion , width ) : <EOL> if is_current_completion : <EOL> token = self . token . Completion . Current <EOL> else : <EOL> token = self . token . Completion <EOL> text , tw = _trim_text ( completion . display , width - <NUM_LIT:2> ) <EOL> padding = '<STR_LIT:U+0020>' * ( width - <NUM_LIT:2> - tw ) <EOL> return [ ( token , '<STR_LIT>' % ( text , padding ) ) ] <EOL> def _get_menu_item_meta_tokens ( self , completion , is_current_completion , width ) : <EOL> if is_current_completion : <EOL> token = self . token . Meta . Current <EOL> else : <EOL> token = self . token . Meta <EOL> text , tw = _trim_text ( completion . display_meta , width - <NUM_LIT:2> ) <EOL> padding = '<STR_LIT:U+0020>' * ( width - <NUM_LIT:2> - tw ) <EOL> return [ ( token , '<STR_LIT>' % ( text , padding ) ) ] <EOL> def mouse_handler ( self , cli , mouse_event ) : <EOL> """<STR_LIT>""" <EOL> b = cli . current_buffer <EOL> if mouse_event . event_type == MouseEventTypes . MOUSE_UP : <EOL> b . go_to_completion ( mouse_event . position . y ) <EOL> b . complete_state = None <EOL> elif mouse_event . event_type == MouseEventTypes . SCROLL_DOWN : <EOL> b . complete_next ( count = <NUM_LIT:3> , disable_wrap_around = True ) <EOL> elif mouse_event . event_type == MouseEventTypes . SCROLL_UP : <EOL> b . complete_previous ( count = <NUM_LIT:3> , disable_wrap_around = True ) <EOL> def _trim_text ( text , max_width ) : <EOL> """<STR_LIT>""" <EOL> width = get_cwidth ( text ) <EOL> if width > max_width : <EOL> if len ( text ) == width : <EOL> trimmed_text = ( text [ : max ( <NUM_LIT:1> , max_width - <NUM_LIT:3> ) ] + '<STR_LIT>' ) [ : max_width ] <EOL> return trimmed_text , len ( trimmed_text ) <EOL> else : <EOL> trimmed_text = '<STR_LIT>' <EOL> for c in text : <EOL> if get_cwidth ( trimmed_text + c ) <= max_width - <NUM_LIT:3> : <EOL> trimmed_text += c <EOL> trimmed_text += '<STR_LIT>' <EOL> return ( trimmed_text , get_cwidth ( trimmed_text ) ) <EOL> else : <EOL> return text , width <EOL> class CompletionsMenu ( ConditionalContainer ) : <EOL> def __init__ ( self , max_height = None , scroll_offset = <NUM_LIT:0> , extra_filter = True , display_arrows = False ) : <EOL> extra_filter = to_cli_filter ( extra_filter ) <EOL> display_arrows = to_cli_filter ( display_arrows ) <EOL> super ( CompletionsMenu , self ) . __init__ ( <EOL> content = Window ( <EOL> content = CompletionsMenuControl ( ) , <EOL> width = LayoutDimension ( min = <NUM_LIT:8> ) , <EOL> height = LayoutDimension ( min = <NUM_LIT:1> , max = max_height ) , <EOL> scroll_offsets = ScrollOffsets ( top = scroll_offset , bottom = scroll_offset ) , <EOL> right_margins = [ ScrollbarMargin ( display_arrows = display_arrows ) ] , <EOL> dont_extend_width = True , <EOL> ) , <EOL> filter = HasCompletions ( ) & ~ IsDone ( ) & extra_filter ) <EOL> class MultiColumnCompletionMenuControl ( UIControl ) : <EOL> """<STR_LIT>""" <EOL> _required_margin = <NUM_LIT:3> <EOL> def __init__ ( self , min_rows = <NUM_LIT:3> , suggested_max_column_width = <NUM_LIT:30> ) : <EOL> assert isinstance ( min_rows , int ) and min_rows >= <NUM_LIT:1> <EOL> self . min_rows = min_rows <EOL> self . suggested_max_column_width = suggested_max_column_width <EOL> self . token = Token . Menu . Completions <EOL> self . scroll = <NUM_LIT:0> <EOL> self . _rendered_rows = <NUM_LIT:0> <EOL> self . _rendered_columns = <NUM_LIT:0> <EOL> self . _total_columns = <NUM_LIT:0> <EOL> self . _render_pos_to_completion = { } <EOL> self . _render_left_arrow = False <EOL> self . _render_right_arrow = False <EOL> self . _render_width = <NUM_LIT:0> <EOL> def reset ( self ) : <EOL> self . scroll = <NUM_LIT:0> <EOL> def has_focus ( self , cli ) : <EOL> return False <EOL> def preferred_width ( self , cli , max_available_width ) : <EOL> """<STR_LIT>""" <EOL> complete_state = cli . current_buffer . complete_state <EOL> column_width = self . _get_column_width ( complete_state ) <EOL> result = int ( column_width * math . ceil ( len ( complete_state . current_completions ) / float ( self . min_rows ) ) ) <EOL> while result > column_width and result > max_available_width - self . _required_margin : <EOL> result -= column_width <EOL> return result + self . _required_margin <EOL> def preferred_height ( self , cli , width , max_available_height , wrap_lines ) : <EOL> """<STR_LIT>""" <EOL> complete_state = cli . current_buffer . complete_state <EOL> column_width = self . _get_column_width ( complete_state ) <EOL> column_count = max ( <NUM_LIT:1> , ( width - self . _required_margin ) // column_width ) <EOL> return int ( math . ceil ( len ( complete_state . current_completions ) / float ( column_count ) ) ) <EOL> def create_content ( self , cli , width , height ) : <EOL> """<STR_LIT>""" <EOL> complete_state = cli . current_buffer . complete_state <EOL> column_width = self . _get_column_width ( complete_state ) <EOL> self . _render_pos_to_completion = { } <EOL> def grouper ( n , iterable , fillvalue = None ) : <EOL> "<STR_LIT>" <EOL> args = [ iter ( iterable ) ] * n <EOL> return zip_longest ( fillvalue = fillvalue , * args ) <EOL> def is_current_completion ( completion ) : <EOL> "<STR_LIT>" <EOL> return complete_state . complete_index is not None and c == complete_state . current_completion <EOL> HORIZONTAL_MARGIN_REQUIRED = <NUM_LIT:3> <EOL> if complete_state : <EOL> column_width = min ( width - HORIZONTAL_MARGIN_REQUIRED , column_width ) <EOL> if column_width > self . suggested_max_column_width : <EOL> column_width //= ( column_width // self . suggested_max_column_width ) <EOL> visible_columns = max ( <NUM_LIT:1> , ( width - self . _required_margin ) // column_width ) <EOL> columns_ = list ( grouper ( height , complete_state . current_completions ) ) <EOL> rows_ = list ( zip ( * columns_ ) ) <EOL> selected_column = ( complete_state . complete_index or <NUM_LIT:0> ) // height <EOL> self . scroll = min ( selected_column , max ( self . scroll , selected_column - visible_columns + <NUM_LIT:1> ) ) <EOL> render_left_arrow = self . scroll > <NUM_LIT:0> <EOL> render_right_arrow = self . scroll < len ( rows_ [ <NUM_LIT:0> ] ) - visible_columns <EOL> tokens_for_line = [ ] <EOL> for row_index , row in enumerate ( rows_ ) : <EOL> tokens = [ ] <EOL> middle_row = row_index == len ( rows_ ) // <NUM_LIT:2> <EOL> if render_left_arrow : <EOL> tokens += [ ( Token . Scrollbar , '<STR_LIT:<>' if middle_row else '<STR_LIT:U+0020>' ) ] <EOL> for column_index , c in enumerate ( row [ self . scroll : ] [ : visible_columns ] ) : <EOL> if c is not None : <EOL> tokens += self . _get_menu_item_tokens ( c , is_current_completion ( c ) , column_width ) <EOL> for x in range ( column_width ) : <EOL> self . _render_pos_to_completion [ ( column_index * column_width + x , row_index ) ] = c <EOL> else : <EOL> tokens += [ ( self . token . Completion , '<STR_LIT:U+0020>' * column_width ) ] <EOL> tokens += [ ( self . token . Completion , '<STR_LIT:U+0020>' ) ] <EOL> if render_right_arrow : <EOL> tokens += [ ( Token . Scrollbar , '<STR_LIT:>>' if middle_row else '<STR_LIT:U+0020>' ) ] <EOL> tokens_for_line . append ( tokens ) <EOL> else : <EOL> tokens = [ ] <EOL> self . _rendered_rows = height <EOL> self . _rendered_columns = visible_columns <EOL> self . _total_columns = len ( columns_ ) <EOL> self . _render_left_arrow = render_left_arrow <EOL> self . _render_right_arrow = render_right_arrow <EOL> self . _render_width = column_width * visible_columns + render_left_arrow + render_right_arrow + <NUM_LIT:1> <EOL> def get_line ( i ) : <EOL> return tokens_for_line [ i ] <EOL> return UIContent ( get_line = get_line , line_count = len ( rows_ ) ) <EOL> def _get_column_width ( self , complete_state ) : <EOL> """<STR_LIT>""" <EOL> return max ( get_cwidth ( c . display ) for c in complete_state . current_completions ) + <NUM_LIT:1> <EOL> def _get_menu_item_tokens ( self , completion , is_current_completion , width ) : <EOL> if is_current_completion : <EOL> token = self . token . Completion . Current <EOL> else : <EOL> token = self . token . Completion <EOL> text , tw = _trim_text ( completion . display , width ) <EOL> padding = '<STR_LIT:U+0020>' * ( width - tw - <NUM_LIT:1> ) <EOL> return [ ( token , '<STR_LIT>' % ( text , padding ) ) ] <EOL> def mouse_handler ( self , cli , mouse_event ) : <EOL> """<STR_LIT>""" <EOL> b = cli . current_buffer <EOL> def scroll_left ( ) : <EOL> b . complete_previous ( count = self . _rendered_rows , disable_wrap_around = True ) <EOL> self . scroll = max ( <NUM_LIT:0> , self . scroll - <NUM_LIT:1> ) <EOL> def scroll_right ( ) : <EOL> b . complete_next ( count = self . _rendered_rows , disable_wrap_around = True ) <EOL> self . scroll = min ( self . _total_columns - self . _rendered_columns , self . scroll + <NUM_LIT:1> ) <EOL> if mouse_event . event_type == MouseEventTypes . SCROLL_DOWN : <EOL> scroll_right ( ) <EOL> elif mouse_event . event_type == MouseEventTypes . SCROLL_UP : <EOL> scroll_left ( ) <EOL> elif mouse_event . event_type == MouseEventTypes . MOUSE_UP : <EOL> x = mouse_event . position . x <EOL> y = mouse_event . position . y <EOL> if x == <NUM_LIT:0> : <EOL> if self . _render_left_arrow : <EOL> scroll_left ( ) <EOL> elif x == self . _render_width - <NUM_LIT:1> : <EOL> if self . _render_right_arrow : <EOL> scroll_right ( ) <EOL> else : <EOL> completion = self . _render_pos_to_completion . get ( ( x , y ) ) <EOL> if completion : <EOL> b . apply_completion ( completion ) <EOL> class MultiColumnCompletionsMenu ( HSplit ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , min_rows = <NUM_LIT:3> , suggested_max_column_width = <NUM_LIT:30> , show_meta = True , extra_filter = True ) : <EOL> show_meta = to_cli_filter ( show_meta ) <EOL> extra_filter = to_cli_filter ( extra_filter ) <EOL> full_filter = HasCompletions ( ) & ~ IsDone ( ) & extra_filter <EOL> any_completion_has_meta = Condition ( lambda cli : <EOL> any ( c . display_meta for c in cli . current_buffer . complete_state . current_completions ) ) <EOL> completions_window = ConditionalContainer ( <EOL> content = Window ( <EOL> content = MultiColumnCompletionMenuControl ( <EOL> min_rows = min_rows , suggested_max_column_width = suggested_max_column_width ) , <EOL> width = LayoutDimension ( min = <NUM_LIT:8> ) , <EOL> height = LayoutDimension ( min = <NUM_LIT:1> ) ) , <EOL> filter = full_filter ) <EOL> meta_window = ConditionalContainer ( <EOL> content = Window ( content = _SelectedCompletionMetaControl ( ) ) , <EOL> filter = show_meta & full_filter & any_completion_has_meta ) <EOL> super ( MultiColumnCompletionsMenu , self ) . __init__ ( [ <EOL> completions_window , <EOL> meta_window <EOL> ] ) <EOL> class _SelectedCompletionMetaControl ( UIControl ) : <EOL> """<STR_LIT>""" <EOL> def preferred_width ( self , cli , max_available_width ) : <EOL> """<STR_LIT>""" <EOL> if cli . current_buffer . complete_state : <EOL> state = cli . current_buffer . complete_state <EOL> return <NUM_LIT:2> + max ( get_cwidth ( c . display_meta ) for c in state . current_completions ) <EOL> else : <EOL> return <NUM_LIT:0> <EOL> def preferred_height ( self , cli , width , max_available_height , wrap_lines ) : <EOL> return <NUM_LIT:1> <EOL> def create_content ( self , cli , width , height ) : <EOL> tokens = self . _get_tokens ( cli ) <EOL> def get_line ( i ) : <EOL> return tokens <EOL> return UIContent ( get_line = get_line , line_count = <NUM_LIT:1> if tokens else <NUM_LIT:0> ) <EOL> def _get_tokens ( self , cli ) : <EOL> token = Token . Menu . Completions . MultiColumnMeta <EOL> state = cli . current_buffer . complete_state <EOL> if state and state . current_completion and state . current_completion . display_meta : <EOL> return [ ( token , '<STR_LIT>' % state . current_completion . display_meta ) ] <EOL> return [ ] </s>
