<s> from __future__ import unicode_literals <EOL> import io <EOL> import os <EOL> import stat <EOL> from itertools import islice <EOL> from six . moves import range <EOL> from bpython . translations import _ <EOL> from bpython . filelock import FileLock <EOL> class History ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , entries = None , duplicates = True , hist_size = <NUM_LIT:100> ) : <EOL> if entries is None : <EOL> self . entries = [ '<STR_LIT>' ] <EOL> else : <EOL> self . entries = list ( entries ) <EOL> self . index = <NUM_LIT:0> <EOL> self . saved_line = '<STR_LIT>' <EOL> self . duplicates = duplicates <EOL> self . hist_size = hist_size <EOL> def append ( self , line ) : <EOL> self . append_to ( self . entries , line ) <EOL> def append_to ( self , entries , line ) : <EOL> line = line . rstrip ( '<STR_LIT:\n>' ) <EOL> if line : <EOL> if not self . duplicates : <EOL> try : <EOL> while True : <EOL> entries . remove ( line ) <EOL> except ValueError : <EOL> pass <EOL> entries . append ( line ) <EOL> def first ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . is_at_end : <EOL> self . index = len ( self . entries ) <EOL> return self . entries [ - self . index ] <EOL> def back ( self , start = True , search = False , target = None , <EOL> include_current = False ) : <EOL> """<STR_LIT>""" <EOL> if target is None : <EOL> target = self . saved_line <EOL> if not self . is_at_end : <EOL> if search : <EOL> self . index += self . find_partial_match_backward ( target , <EOL> include_current ) <EOL> elif start : <EOL> self . index += self . find_match_backward ( target , include_current ) <EOL> else : <EOL> self . index += <NUM_LIT:1> <EOL> return self . entry <EOL> @ property <EOL> def entry ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . entries [ - self . index ] if self . index else self . saved_line <EOL> @ property <EOL> def entries_by_index ( self ) : <EOL> return list ( reversed ( self . entries + [ self . saved_line ] ) ) <EOL> def find_match_backward ( self , search_term , include_current = False ) : <EOL> add = <NUM_LIT:0> if include_current else <NUM_LIT:1> <EOL> start = self . index + add <EOL> for idx , val in enumerate ( islice ( self . entries_by_index , start , None ) ) : <EOL> if val . startswith ( search_term ) : <EOL> return idx + add <EOL> return <NUM_LIT:0> <EOL> def find_partial_match_backward ( self , search_term , include_current = False ) : <EOL> add = <NUM_LIT:0> if include_current else <NUM_LIT:1> <EOL> start = self . index + add <EOL> for idx , val in enumerate ( islice ( self . entries_by_index , start , None ) ) : <EOL> if search_term in val : <EOL> return idx + add <EOL> return <NUM_LIT:0> <EOL> def forward ( self , start = True , search = False , target = None , <EOL> include_current = False ) : <EOL> """<STR_LIT>""" <EOL> if target is None : <EOL> target = self . saved_line <EOL> if self . index > <NUM_LIT:1> : <EOL> if search : <EOL> self . index -= self . find_partial_match_forward ( target , <EOL> include_current ) <EOL> elif start : <EOL> self . index -= self . find_match_forward ( target , include_current ) <EOL> else : <EOL> self . index -= <NUM_LIT:1> <EOL> return self . entry <EOL> else : <EOL> self . index = <NUM_LIT:0> <EOL> return self . saved_line <EOL> def find_match_forward ( self , search_term , include_current = False ) : <EOL> add = <NUM_LIT:0> if include_current else <NUM_LIT:1> <EOL> end = max ( <NUM_LIT:0> , self . index - ( <NUM_LIT:1> - add ) ) <EOL> for idx in range ( end ) : <EOL> val = self . entries_by_index [ end - <NUM_LIT:1> - idx ] <EOL> if val . startswith ( search_term ) : <EOL> return idx + ( <NUM_LIT:0> if include_current else <NUM_LIT:1> ) <EOL> return self . index <EOL> def find_partial_match_forward ( self , search_term , include_current = False ) : <EOL> add = <NUM_LIT:0> if include_current else <NUM_LIT:1> <EOL> end = max ( <NUM_LIT:0> , self . index - ( <NUM_LIT:1> - add ) ) <EOL> for idx in range ( end ) : <EOL> val = self . entries_by_index [ end - <NUM_LIT:1> - idx ] <EOL> if search_term in val : <EOL> return idx + add <EOL> return self . index <EOL> def last ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . is_at_start : <EOL> self . index = <NUM_LIT:0> <EOL> return self . entries [ <NUM_LIT:0> ] <EOL> @ property <EOL> def is_at_end ( self ) : <EOL> return self . index >= len ( self . entries ) or self . index == - <NUM_LIT:1> <EOL> @ property <EOL> def is_at_start ( self ) : <EOL> return self . index == <NUM_LIT:0> <EOL> def enter ( self , line ) : <EOL> if self . index == <NUM_LIT:0> : <EOL> self . saved_line = line <EOL> @ classmethod <EOL> def from_filename ( cls , filename ) : <EOL> history = cls ( ) <EOL> history . load ( filename ) <EOL> return history <EOL> def reset ( self ) : <EOL> self . index = <NUM_LIT:0> <EOL> self . saved_line = '<STR_LIT>' <EOL> def load ( self , filename , encoding ) : <EOL> with io . open ( filename , '<STR_LIT:r>' , encoding = encoding , <EOL> errors = '<STR_LIT:ignore>' ) as hfile : <EOL> with FileLock ( hfile ) : <EOL> self . entries = self . load_from ( hfile ) <EOL> def load_from ( self , fd ) : <EOL> entries = [ ] <EOL> for line in fd : <EOL> self . append_to ( entries , line ) <EOL> return entries <EOL> def save ( self , filename , encoding , lines = <NUM_LIT:0> ) : <EOL> fd = os . open ( filename , os . O_WRONLY | os . O_CREAT | os . TRUNC , <EOL> stat . S_IRUSR | stat . S_IWUSR ) <EOL> with io . open ( fd , '<STR_LIT:w>' , encoding = encoding , <EOL> errors = '<STR_LIT:ignore>' ) as hfile : <EOL> with FileLock ( hfile ) : <EOL> self . save_to ( hfile , self . entries , lines ) <EOL> def save_to ( self , fd , entries = None , lines = <NUM_LIT:0> ) : <EOL> if entries is None : <EOL> entries = self . entries <EOL> for line in entries [ - lines : ] : <EOL> fd . write ( line ) <EOL> fd . write ( '<STR_LIT:\n>' ) <EOL> def append_reload_and_write ( self , s , filename , encoding ) : <EOL> if not self . hist_size : <EOL> return self . append ( s ) <EOL> try : <EOL> fd = os . open ( filename , os . O_APPEND | os . O_RDWR | os . O_CREAT , <EOL> stat . S_IRUSR | stat . S_IWUSR ) <EOL> with io . open ( fd , '<STR_LIT>' , encoding = encoding , <EOL> errors = '<STR_LIT:ignore>' ) as hfile : <EOL> with FileLock ( hfile ) : <EOL> hfile . seek ( <NUM_LIT:0> , os . SEEK_SET ) <EOL> entries = self . load_from ( hfile ) <EOL> self . append_to ( entries , s ) <EOL> hfile . seek ( <NUM_LIT:0> , os . SEEK_SET ) <EOL> hfile . truncate ( ) <EOL> self . save_to ( hfile , entries , self . hist_size ) <EOL> self . entries = entries <EOL> except EnvironmentError as err : <EOL> raise RuntimeError ( <EOL> _ ( '<STR_LIT>' ) <EOL> % ( filename , err . strerror ) ) <EOL> else : <EOL> if len ( self . entries ) == <NUM_LIT:0> : <EOL> self . entries = [ '<STR_LIT>' ] </s>
