<s> """<STR_LIT>""" <EOL> import warnings <EOL> from x84 . bbs . ansiwin import AnsiWindow , GLYPHSETS <EOL> from x84 . bbs . session import getterminal , getch <EOL> from x84 . bbs . output import echo <EOL> PC_KEYSET = { '<STR_LIT>' : [ unichr ( <NUM_LIT:12> ) , ] , <EOL> '<STR_LIT>' : [ unichr ( <NUM_LIT:8> ) , unichr ( <NUM_LIT> ) , ] , <EOL> '<STR_LIT>' : [ unichr ( <NUM_LIT> ) , ] , <EOL> '<STR_LIT>' : [ u'<STR_LIT:\r>' , ] , <EOL> '<STR_LIT>' : [ unichr ( <NUM_LIT> ) , ] , } <EOL> class LineEditor ( object ) : <EOL> """<STR_LIT>""" <EOL> _hidden = False <EOL> _width = <NUM_LIT:0> <EOL> def __init__ ( self , width = None , content = u'<STR_LIT>' , hidden = False , <EOL> colors = None , glyphs = None , keyset = None ) : <EOL> """<STR_LIT>""" <EOL> self . _term = getterminal ( ) <EOL> self . content = content or u'<STR_LIT>' <EOL> self . hidden = hidden <EOL> self . _width = width <EOL> self . _input_length = self . _term . length ( content ) <EOL> self . _quit = False <EOL> self . _carriage_returned = False <EOL> self . init_keystrokes ( keyset = keyset or PC_KEYSET . copy ( ) ) <EOL> self . init_theme ( colors = colors , glyphs = glyphs ) <EOL> def init_theme ( self , colors = None , glyphs = None , hidden = False ) : <EOL> """<STR_LIT>""" <EOL> self . colors = { '<STR_LIT>' : self . _term . reverse } <EOL> self . glyphs = GLYPHSETS [ '<STR_LIT>' ] . copy ( ) <EOL> if colors is not None : <EOL> self . colors . update ( colors ) <EOL> if glyphs is not None : <EOL> self . glyphs . update ( glyphs ) <EOL> if hidden : <EOL> self . hidden = hidden <EOL> def init_keystrokes ( self , keyset ) : <EOL> """<STR_LIT>""" <EOL> self . keyset = keyset <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_REFRESH ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_BACKSPACE ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_DELETE ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_ENTER ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_ESCAPE ) <EOL> @ property <EOL> def quit ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _quit <EOL> @ property <EOL> def carriage_returned ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _carriage_returned <EOL> @ property <EOL> def hidden ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _hidden <EOL> @ hidden . setter <EOL> def hidden ( self , value ) : <EOL> assert value is False or <NUM_LIT:1> == len ( value ) <EOL> self . _hidden = value <EOL> @ property <EOL> def width ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _width <EOL> @ width . setter <EOL> def width ( self , value ) : <EOL> self . _width = value <EOL> def refresh ( self ) : <EOL> """<STR_LIT>""" <EOL> disp_lightbar = u'<STR_LIT>' . join ( ( <EOL> self . _term . normal , <EOL> self . colors . get ( '<STR_LIT>' , u'<STR_LIT>' ) , <EOL> '<STR_LIT:U+0020>' * self . width , <EOL> '<STR_LIT>' * self . width ) ) <EOL> content = self . content <EOL> if self . hidden : <EOL> content = self . hidden * self . _term . length ( self . content ) <EOL> return u'<STR_LIT>' . join ( ( disp_lightbar , content , self . _term . cursor_visible ) ) <EOL> def process_keystroke ( self , keystroke ) : <EOL> """<STR_LIT>""" <EOL> self . _quit = False <EOL> keystroke = hasattr ( keystroke , '<STR_LIT:code>' ) and keystroke . code or keystroke <EOL> if keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> return u'<STR_LIT>' * self . _term . length ( self . content ) + self . refresh ( ) <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> if len ( self . content ) != <NUM_LIT:0> : <EOL> len_toss = self . _term . length ( self . content [ - <NUM_LIT:1> ] ) <EOL> self . content = self . content [ : - <NUM_LIT:1> ] <EOL> return u'<STR_LIT>' . join ( ( <EOL> u'<STR_LIT>' * len_toss , <EOL> u'<STR_LIT:U+0020>' * len_toss , <EOL> u'<STR_LIT>' , ) ) <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> if len ( self . content ) != <NUM_LIT:0> : <EOL> ridx = self . content . rstrip ( ) . rfind ( '<STR_LIT:U+0020>' ) + <NUM_LIT:1> <EOL> toss = self . _term . length ( self . content [ ridx : ] ) <EOL> move = len ( self . content [ ridx : ] ) <EOL> self . content = self . content [ : ridx ] <EOL> return u'<STR_LIT>' . join ( ( <EOL> u'<STR_LIT>' * toss , <EOL> u'<STR_LIT:U+0020>' * move , <EOL> u'<STR_LIT>' * move , ) ) <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> self . _carriage_returned = True <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> self . _quit = True <EOL> elif isinstance ( keystroke , int ) : <EOL> return u'<STR_LIT>' <EOL> elif ( ord ( keystroke ) >= ord ( '<STR_LIT:U+0020>' ) and <EOL> ( self . _term . length ( self . content ) < self . width <EOL> or self . width is None ) ) : <EOL> self . content += keystroke <EOL> return keystroke if not self . hidden else self . hidden <EOL> return u'<STR_LIT>' <EOL> def read ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _carriage_returned = False <EOL> self . _quit = False <EOL> echo ( self . refresh ( ) ) <EOL> while not ( self . quit or self . carriage_returned ) : <EOL> inp = getch ( ) <EOL> echo ( self . process_keystroke ( inp ) ) <EOL> echo ( self . _term . normal ) <EOL> if not self . quit : <EOL> return self . content <EOL> return None <EOL> class ScrollingEditor ( AnsiWindow ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> self . _term = getterminal ( ) <EOL> self . _horiz_shift = <NUM_LIT:0> <EOL> self . _horiz_pos = <NUM_LIT:0> <EOL> self . _horiz_lastshift = <NUM_LIT:0> <EOL> self . _scroll_pct = kwargs . pop ( '<STR_LIT>' , <NUM_LIT> ) <EOL> self . _margin_pct = kwargs . pop ( '<STR_LIT>' , <NUM_LIT> ) <EOL> self . _carriage_returned = False <EOL> self . _max_length = kwargs . pop ( '<STR_LIT:max_length>' , <NUM_LIT:0> ) <EOL> self . _quit = False <EOL> self . _bell = False <EOL> self . content = kwargs . pop ( '<STR_LIT:content>' , u'<STR_LIT>' ) <EOL> self . _input_length = self . _term . length ( self . content ) <EOL> kwargs [ '<STR_LIT>' ] = <NUM_LIT:3> <EOL> self . init_keystrokes ( keyset = kwargs . pop ( '<STR_LIT>' , PC_KEYSET . copy ( ) ) ) <EOL> AnsiWindow . __init__ ( self , * args , ** kwargs ) <EOL> def init_theme ( self , colors = None , glyphs = None ) : <EOL> """<STR_LIT>""" <EOL> AnsiWindow . init_theme ( self , colors , glyphs ) <EOL> if '<STR_LIT>' not in self . colors : <EOL> self . colors [ '<STR_LIT>' ] = self . _term . yellow_reverse <EOL> if '<STR_LIT>' not in self . glyphs : <EOL> self . glyphs [ '<STR_LIT>' ] = u'<STR_LIT>' <EOL> def init_keystrokes ( self , keyset ) : <EOL> """<STR_LIT>""" <EOL> self . keyset = keyset <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_REFRESH ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_BACKSPACE ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_DELETE ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_ENTER ) <EOL> self . keyset [ '<STR_LIT>' ] . append ( self . _term . KEY_ESCAPE ) <EOL> @ property <EOL> def position ( self ) : <EOL> """<STR_LIT>""" <EOL> return ( self . _horiz_shift , self . _horiz_pos ) <EOL> @ property <EOL> def eol ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _input_length >= self . max_length <EOL> @ property <EOL> def bell ( self ) : <EOL> """<STR_LIT>""" <EOL> margin = int ( float ( self . visible_width ) * <EOL> ( float ( self . scroll_pct ) * <NUM_LIT> ) ) <EOL> return bool ( self . _input_length >= self . visible_width - margin ) <EOL> @ bell . setter <EOL> def bell ( self , value ) : <EOL> self . _bell = value <EOL> @ property <EOL> def carriage_returned ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _carriage_returned <EOL> @ property <EOL> def quit ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _quit <EOL> @ property <EOL> def is_scrolled ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . _horiz_shift ) <EOL> @ property <EOL> def scroll_amt ( self ) : <EOL> """<STR_LIT>""" <EOL> return int ( float ( self . visible_width ) * ( float ( self . scroll_pct ) * <NUM_LIT> ) ) <EOL> @ property <EOL> def margin_amt ( self ) : <EOL> """<STR_LIT>""" <EOL> return int ( float ( self . visible_width ) * ( float ( self . margin_pct ) * <NUM_LIT> ) ) <EOL> @ property <EOL> def scroll_pct ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _scroll_pct <EOL> @ scroll_pct . setter <EOL> def scroll_pct ( self , value ) : <EOL> self . _scroll_pct = float ( value ) <EOL> assert value < <NUM_LIT:50> , ( "<STR_LIT>" ) <EOL> @ property <EOL> def margin_pct ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _margin_pct <EOL> @ margin_pct . setter <EOL> def margin_pct ( self , value ) : <EOL> self . _margin_pct = float ( value ) <EOL> @ property <EOL> def max_length ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . _max_length : <EOL> warnings . warn ( "<STR_LIT>" ) <EOL> return self . _max_length or float ( '<STR_LIT>' ) <EOL> @ max_length . setter <EOL> def max_length ( self , value ) : <EOL> self . _max_length = value <EOL> @ property <EOL> def content ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _content <EOL> @ content . setter <EOL> def content ( self , value ) : <EOL> self . _content = value <EOL> self . _input_length = self . _term . length ( value ) <EOL> def process_keystroke ( self , keystroke ) : <EOL> """<STR_LIT>""" <EOL> self . _quit = False <EOL> rstr = u'<STR_LIT>' <EOL> keystroke = hasattr ( keystroke , '<STR_LIT:code>' ) and keystroke . code or keystroke <EOL> if keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> rstr = self . refresh ( ) <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> rstr = self . backspace ( ) <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> rstr = self . backword ( ) <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> self . _carriage_returned = True <EOL> rstr = u'<STR_LIT>' <EOL> elif keystroke in self . keyset [ '<STR_LIT>' ] : <EOL> self . _quit = True <EOL> rstr = u'<STR_LIT>' <EOL> elif isinstance ( keystroke , int ) : <EOL> rstr = u'<STR_LIT>' <EOL> else : <EOL> if ord ( keystroke ) >= <NUM_LIT> : <EOL> rstr = self . add ( keystroke ) <EOL> return rstr <EOL> def read ( self ) : <EOL> """<STR_LIT>""" <EOL> echo ( self . refresh ( ) ) <EOL> self . _quit = False <EOL> self . _carriage_returned = False <EOL> while not ( self . quit or self . carriage_returned ) : <EOL> inp = getch ( ) <EOL> echo ( self . process_keystroke ( inp ) ) <EOL> if not self . quit : <EOL> return self . content <EOL> return None <EOL> def fixate ( self , x_adjust = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> xpos = self . _xpadding + self . _horiz_pos + x_adjust <EOL> return self . pos ( <NUM_LIT:1> , xpos ) + self . _term . cursor_visible <EOL> def refresh ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _horiz_lastshift = self . _horiz_shift <EOL> self . _horiz_shift = <NUM_LIT:0> <EOL> self . _horiz_pos = <NUM_LIT:0> <EOL> for _ in range ( self . _input_length ) : <EOL> if ( self . _horiz_pos > <EOL> ( self . visible_width - self . scroll_amt ) ) : <EOL> self . _horiz_shift += self . scroll_amt <EOL> self . _horiz_pos -= self . scroll_amt <EOL> self . _horiz_pos += <NUM_LIT:1> <EOL> if self . _horiz_shift > <NUM_LIT:0> : <EOL> self . _horiz_shift += len ( self . glyphs [ '<STR_LIT>' ] ) <EOL> prnt = u'<STR_LIT>' . join ( ( <EOL> self . glyphs [ '<STR_LIT>' ] , <EOL> self . content [ self . _horiz_shift : ] , ) ) <EOL> else : <EOL> prnt = self . content <EOL> return u'<STR_LIT>' . join ( ( <EOL> self . pos ( self . ypadding , self . xpadding ) , <EOL> self . _term . normal , <EOL> self . colors . get ( '<STR_LIT>' , u'<STR_LIT>' ) , <EOL> self . align ( prnt ) , <EOL> self . fixate ( ) , ) ) <EOL> def backword ( self ) : <EOL> """<STR_LIT>""" <EOL> if <NUM_LIT:0> == len ( self . content ) : <EOL> return u'<STR_LIT>' <EOL> ridx = self . content . rstrip ( ) . rfind ( '<STR_LIT:U+0020>' ) + <NUM_LIT:1> <EOL> self . content = self . content [ : ridx ] <EOL> return self . refresh ( ) <EOL> def backspace ( self ) : <EOL> """<STR_LIT>""" <EOL> if <NUM_LIT:0> == len ( self . content ) : <EOL> return u'<STR_LIT>' <EOL> rstr = u'<STR_LIT>' <EOL> len_toss = self . _term . length ( self . content [ - <NUM_LIT:1> ] ) <EOL> len_move = <NUM_LIT:1> <EOL> self . content = self . content [ : - <NUM_LIT:1> ] <EOL> if self . is_scrolled and ( self . _horiz_pos < self . scroll_amt ) : <EOL> self . _horiz_shift -= self . scroll_amt <EOL> self . _horiz_pos += self . scroll_amt <EOL> rstr += self . refresh ( ) <EOL> else : <EOL> rstr += u'<STR_LIT>' . join ( ( <EOL> self . fixate ( <NUM_LIT:0> ) , <EOL> u'<STR_LIT>' * len_toss , <EOL> u'<STR_LIT:U+0020>' * len_move , <EOL> u'<STR_LIT>' * len_move , ) ) <EOL> self . _horiz_pos -= <NUM_LIT:1> <EOL> return rstr <EOL> def update ( self , ucs = u'<STR_LIT>' ) : <EOL> """<STR_LIT>""" <EOL> self . _horiz_shift = <NUM_LIT:0> <EOL> self . _horiz_pos = <NUM_LIT:0> <EOL> self . content = ucs <EOL> self . _carriage_returned = False <EOL> self . _quit = False <EOL> assert unichr ( <NUM_LIT> ) not in ucs , ( '<STR_LIT>' ) <EOL> def add ( self , u_chr ) : <EOL> """<STR_LIT>""" <EOL> if self . eol : <EOL> return u'<STR_LIT>' <EOL> self . _content += u_chr <EOL> self . _input_length += self . _term . length ( u_chr ) <EOL> self . _horiz_pos += <NUM_LIT:1> <EOL> if self . _horiz_pos >= ( self . visible_width - self . margin_amt ) : <EOL> return self . refresh ( ) <EOL> return self . _term . normal + self . colors [ '<STR_LIT>' ] + u_chr </s>
