<s> """<STR_LIT>""" <EOL> from __future__ import unicode_literals <EOL> from . auto_suggest import AutoSuggest <EOL> from . clipboard import ClipboardData <EOL> from . completion import Completer , Completion , CompleteEvent <EOL> from . document import Document <EOL> from . enums import IncrementalSearchDirection <EOL> from . filters import to_simple_filter <EOL> from . history import History , InMemoryHistory <EOL> from . search_state import SearchState <EOL> from . selection import SelectionType , SelectionState <EOL> from . utils import Callback <EOL> from . cache import FastDictCache <EOL> from . validation import ValidationError <EOL> from six . moves import range <EOL> import os <EOL> import re <EOL> import six <EOL> import subprocess <EOL> import tempfile <EOL> __all__ = ( <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> ) <EOL> class EditReadOnlyBuffer ( Exception ) : <EOL> "<STR_LIT>" <EOL> class AcceptAction ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , handler = None ) : <EOL> assert handler is None or callable ( handler ) <EOL> self . handler = handler <EOL> @ classmethod <EOL> def run_in_terminal ( cls , handler , render_cli_done = False ) : <EOL> """<STR_LIT>""" <EOL> def _handler ( cli , buffer ) : <EOL> cli . run_in_terminal ( lambda : handler ( cli , buffer ) , render_cli_done = render_cli_done ) <EOL> return AcceptAction ( handler = _handler ) <EOL> @ property <EOL> def is_returnable ( self ) : <EOL> """<STR_LIT>""" <EOL> return bool ( self . handler ) <EOL> def validate_and_handle ( self , cli , buffer ) : <EOL> """<STR_LIT>""" <EOL> if buffer . validate ( ) : <EOL> if self . handler : <EOL> self . handler ( cli , buffer ) <EOL> buffer . append_to_history ( ) <EOL> def _return_document_handler ( cli , buffer ) : <EOL> cli . set_return_value ( buffer . document ) <EOL> AcceptAction . RETURN_DOCUMENT = AcceptAction ( _return_document_handler ) <EOL> AcceptAction . IGNORE = AcceptAction ( handler = None ) <EOL> class CompletionState ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , original_document , current_completions = None , complete_index = None ) : <EOL> self . original_document = original_document <EOL> self . current_completions = current_completions or [ ] <EOL> self . complete_index = complete_index <EOL> def __repr__ ( self ) : <EOL> return '<STR_LIT>' % ( <EOL> self . __class__ . __name__ , <EOL> self . original_document , len ( self . current_completions ) , self . complete_index ) <EOL> def go_to_index ( self , index ) : <EOL> """<STR_LIT>""" <EOL> return CompletionState ( self . original_document , self . current_completions , complete_index = index ) <EOL> def new_text_and_position ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . complete_index is None : <EOL> return self . original_document . text , self . original_document . cursor_position <EOL> else : <EOL> original_text_before_cursor = self . original_document . text_before_cursor <EOL> original_text_after_cursor = self . original_document . text_after_cursor <EOL> c = self . current_completions [ self . complete_index ] <EOL> if c . start_position == <NUM_LIT:0> : <EOL> before = original_text_before_cursor <EOL> else : <EOL> before = original_text_before_cursor [ : c . start_position ] <EOL> new_text = before + c . text + original_text_after_cursor <EOL> new_cursor_position = len ( before ) + len ( c . text ) <EOL> return new_text , new_cursor_position <EOL> @ property <EOL> def current_completion ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . complete_index is not None : <EOL> return self . current_completions [ self . complete_index ] <EOL> class Buffer ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , completer = None , auto_suggest = None , history = None , <EOL> validator = None , tempfile_suffix = '<STR_LIT>' , <EOL> is_multiline = False , complete_while_typing = False , <EOL> enable_history_search = False , initial_document = None , <EOL> accept_action = AcceptAction . IGNORE , read_only = False , <EOL> on_text_changed = None , on_text_insert = None , on_cursor_position_changed = None ) : <EOL> enable_history_search = to_simple_filter ( enable_history_search ) <EOL> is_multiline = to_simple_filter ( is_multiline ) <EOL> complete_while_typing = to_simple_filter ( complete_while_typing ) <EOL> read_only = to_simple_filter ( read_only ) <EOL> assert completer is None or isinstance ( completer , Completer ) <EOL> assert auto_suggest is None or isinstance ( auto_suggest , AutoSuggest ) <EOL> assert history is None or isinstance ( history , History ) <EOL> assert on_text_changed is None or isinstance ( on_text_changed , Callback ) <EOL> assert on_text_insert is None or isinstance ( on_text_insert , Callback ) <EOL> assert on_cursor_position_changed is None or isinstance ( on_cursor_position_changed , Callback ) <EOL> self . completer = completer <EOL> self . auto_suggest = auto_suggest <EOL> self . validator = validator <EOL> self . tempfile_suffix = tempfile_suffix <EOL> self . accept_action = accept_action <EOL> self . is_multiline = is_multiline <EOL> self . complete_while_typing = complete_while_typing <EOL> self . enable_history_search = enable_history_search <EOL> self . read_only = read_only <EOL> self . text_width = <NUM_LIT:0> <EOL> self . history = InMemoryHistory ( ) if history is None else history <EOL> self . __cursor_position = <NUM_LIT:0> <EOL> self . on_text_changed = on_text_changed or Callback ( ) <EOL> self . on_text_insert = on_text_insert or Callback ( ) <EOL> self . on_cursor_position_changed = on_cursor_position_changed or Callback ( ) <EOL> self . _document_cache = FastDictCache ( Document , size = <NUM_LIT:10> ) <EOL> self . reset ( initial_document = initial_document ) <EOL> def reset ( self , initial_document = None , append_to_history = False ) : <EOL> """<STR_LIT>""" <EOL> assert initial_document is None or isinstance ( initial_document , Document ) <EOL> if append_to_history : <EOL> self . append_to_history ( ) <EOL> initial_document = initial_document or Document ( ) <EOL> self . __cursor_position = initial_document . cursor_position <EOL> self . validation_error = None <EOL> self . selection_state = None <EOL> self . preferred_column = None <EOL> self . complete_state = None <EOL> self . suggestion = None <EOL> self . history_search_text = None <EOL> self . _undo_stack = [ ] <EOL> self . _redo_stack = [ ] <EOL> self . _working_lines = self . history . strings [ : ] <EOL> self . _working_lines . append ( initial_document . text ) <EOL> self . __working_index = len ( self . _working_lines ) - <NUM_LIT:1> <EOL> def _set_text ( self , value ) : <EOL> """<STR_LIT>""" <EOL> working_index = self . working_index <EOL> working_lines = self . _working_lines <EOL> original_value = working_lines [ working_index ] <EOL> working_lines [ working_index ] = value <EOL> if len ( value ) != len ( original_value ) : <EOL> return True <EOL> elif value != original_value : <EOL> return True <EOL> return False <EOL> def _set_cursor_position ( self , value ) : <EOL> """<STR_LIT>""" <EOL> original_position = self . __cursor_position <EOL> self . __cursor_position = max ( <NUM_LIT:0> , value ) <EOL> return value != original_position <EOL> @ property <EOL> def text ( self ) : <EOL> return self . _working_lines [ self . working_index ] <EOL> @ text . setter <EOL> def text ( self , value ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( value , six . text_type ) , '<STR_LIT>' % value <EOL> assert self . cursor_position <= len ( value ) <EOL> if self . read_only ( ) : <EOL> raise EditReadOnlyBuffer ( ) <EOL> changed = self . _set_text ( value ) <EOL> if changed : <EOL> self . _text_changed ( ) <EOL> self . history_search_text = None <EOL> @ property <EOL> def cursor_position ( self ) : <EOL> return self . __cursor_position <EOL> @ cursor_position . setter <EOL> def cursor_position ( self , value ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( value , int ) <EOL> assert value <= len ( self . text ) <EOL> changed = self . _set_cursor_position ( value ) <EOL> if changed : <EOL> self . _cursor_position_changed ( ) <EOL> @ property <EOL> def working_index ( self ) : <EOL> return self . __working_index <EOL> @ working_index . setter <EOL> def working_index ( self , value ) : <EOL> if self . __working_index != value : <EOL> self . __working_index = value <EOL> self . _text_changed ( ) <EOL> def _text_changed ( self ) : <EOL> self . validation_error = None <EOL> self . complete_state = None <EOL> self . selection_state = None <EOL> self . suggestion = None <EOL> self . preferred_column = None <EOL> self . on_text_changed . fire ( ) <EOL> def _cursor_position_changed ( self ) : <EOL> self . validation_error = None <EOL> self . complete_state = None <EOL> self . preferred_column = None <EOL> self . on_cursor_position_changed . fire ( ) <EOL> @ property <EOL> def document ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _document_cache [ <EOL> self . text , self . cursor_position , self . selection_state ] <EOL> @ document . setter <EOL> def document ( self , value ) : <EOL> """<STR_LIT>""" <EOL> self . set_document ( value ) <EOL> def set_document ( self , value , bypass_readonly = False ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( value , Document ) <EOL> if not bypass_readonly and self . read_only ( ) : <EOL> raise EditReadOnlyBuffer ( ) <EOL> text_changed = self . _set_text ( value . text ) <EOL> cursor_position_changed = self . _set_cursor_position ( value . cursor_position ) <EOL> if text_changed : <EOL> self . _text_changed ( ) <EOL> if cursor_position_changed : <EOL> self . _cursor_position_changed ( ) <EOL> def save_to_undo_stack ( self , clear_redo_stack = True ) : <EOL> """<STR_LIT>""" <EOL> if self . _undo_stack and self . _undo_stack [ - <NUM_LIT:1> ] [ <NUM_LIT:0> ] == self . text : <EOL> self . _undo_stack [ - <NUM_LIT:1> ] = ( self . _undo_stack [ - <NUM_LIT:1> ] [ <NUM_LIT:0> ] , self . cursor_position ) <EOL> else : <EOL> self . _undo_stack . append ( ( self . text , self . cursor_position ) ) <EOL> if clear_redo_stack : <EOL> self . _redo_stack = [ ] <EOL> def transform_lines ( self , line_index_iterator , transform_callback ) : <EOL> """<STR_LIT>""" <EOL> lines = self . text . split ( '<STR_LIT:\n>' ) <EOL> for index in line_index_iterator : <EOL> try : <EOL> lines [ index ] = transform_callback ( lines [ index ] ) <EOL> except IndexError : <EOL> pass <EOL> return '<STR_LIT:\n>' . join ( lines ) <EOL> def transform_region ( self , from_ , to , transform_callback ) : <EOL> """<STR_LIT>""" <EOL> assert from_ < to <EOL> self . text = '<STR_LIT>' . join ( [ <EOL> self . text [ : from_ ] + <EOL> transform_callback ( self . text [ from_ : to ] ) + <EOL> self . text [ to : ] <EOL> ] ) <EOL> def cursor_left ( self , count = <NUM_LIT:1> ) : <EOL> self . cursor_position += self . document . get_cursor_left_position ( count = count ) <EOL> def cursor_right ( self , count = <NUM_LIT:1> ) : <EOL> self . cursor_position += self . document . get_cursor_right_position ( count = count ) <EOL> def cursor_up ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> original_column = self . preferred_column or self . document . cursor_position_col <EOL> self . cursor_position += self . document . get_cursor_up_position ( <EOL> count = count , preferred_column = original_column ) <EOL> self . preferred_column = original_column <EOL> def cursor_down ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> original_column = self . preferred_column or self . document . cursor_position_col <EOL> self . cursor_position += self . document . get_cursor_down_position ( <EOL> count = count , preferred_column = original_column ) <EOL> self . preferred_column = original_column <EOL> def auto_up ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> if self . complete_state : <EOL> self . complete_previous ( count = count ) <EOL> elif self . document . cursor_position_row > <NUM_LIT:0> : <EOL> self . cursor_up ( count = count ) <EOL> elif not self . selection_state : <EOL> self . history_backward ( count = count ) <EOL> def auto_down ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> if self . complete_state : <EOL> self . complete_next ( count = count ) <EOL> elif self . document . cursor_position_row < self . document . line_count - <NUM_LIT:1> : <EOL> self . cursor_down ( count = count ) <EOL> elif not self . selection_state : <EOL> self . history_forward ( count = count ) <EOL> def delete_before_cursor ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> assert count >= <NUM_LIT:0> <EOL> deleted = '<STR_LIT>' <EOL> if self . cursor_position > <NUM_LIT:0> : <EOL> deleted = self . text [ self . cursor_position - count : self . cursor_position ] <EOL> new_text = self . text [ : self . cursor_position - count ] + self . text [ self . cursor_position : ] <EOL> new_cursor_position = self . cursor_position - len ( deleted ) <EOL> self . document = Document ( new_text , new_cursor_position ) <EOL> return deleted <EOL> def delete ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> if self . cursor_position < len ( self . text ) : <EOL> deleted = self . document . text_after_cursor [ : count ] <EOL> self . text = self . text [ : self . cursor_position ] + self . text [ self . cursor_position + len ( deleted ) : ] <EOL> return deleted <EOL> else : <EOL> return '<STR_LIT>' <EOL> def join_next_line ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . document . on_last_line : <EOL> self . cursor_position += self . document . get_end_of_line_position ( ) <EOL> self . delete ( ) <EOL> self . text = ( self . document . text_before_cursor + '<STR_LIT:U+0020>' + <EOL> self . document . text_after_cursor . lstrip ( '<STR_LIT:U+0020>' ) ) <EOL> def join_selected_lines ( self ) : <EOL> """<STR_LIT>""" <EOL> assert self . selection_state <EOL> from_ , to = sorted ( [ self . cursor_position , self . selection_state . original_cursor_position ] ) <EOL> before = self . text [ : from_ ] <EOL> lines = self . text [ from_ : to ] . splitlines ( ) <EOL> after = self . text [ to : ] <EOL> lines = [ l . lstrip ( '<STR_LIT:U+0020>' ) + '<STR_LIT:U+0020>' for l in lines ] <EOL> self . document = Document ( text = before + '<STR_LIT>' . join ( lines ) + after , <EOL> cursor_position = len ( before + '<STR_LIT>' . join ( lines [ : - <NUM_LIT:1> ] ) ) - <NUM_LIT:1> ) <EOL> def swap_characters_before_cursor ( self ) : <EOL> """<STR_LIT>""" <EOL> pos = self . cursor_position <EOL> if pos >= <NUM_LIT:2> : <EOL> a = self . text [ pos - <NUM_LIT:2> ] <EOL> b = self . text [ pos - <NUM_LIT:1> ] <EOL> self . text = self . text [ : pos - <NUM_LIT:2> ] + b + a + self . text [ pos : ] <EOL> def go_to_history ( self , index ) : <EOL> """<STR_LIT>""" <EOL> if index < len ( self . _working_lines ) : <EOL> self . working_index = index <EOL> self . cursor_position = len ( self . text ) <EOL> def complete_next ( self , count = <NUM_LIT:1> , disable_wrap_around = False ) : <EOL> """<STR_LIT>""" <EOL> if self . complete_state : <EOL> completions_count = len ( self . complete_state . current_completions ) <EOL> if self . complete_state . complete_index is None : <EOL> index = <NUM_LIT:0> <EOL> elif self . complete_state . complete_index == completions_count - <NUM_LIT:1> : <EOL> index = None <EOL> if disable_wrap_around : <EOL> return <EOL> else : <EOL> index = min ( completions_count - <NUM_LIT:1> , self . complete_state . complete_index + count ) <EOL> self . go_to_completion ( index ) <EOL> def complete_previous ( self , count = <NUM_LIT:1> , disable_wrap_around = False ) : <EOL> """<STR_LIT>""" <EOL> if self . complete_state : <EOL> if self . complete_state . complete_index == <NUM_LIT:0> : <EOL> index = None <EOL> if disable_wrap_around : <EOL> return <EOL> elif self . complete_state . complete_index is None : <EOL> index = len ( self . complete_state . current_completions ) - <NUM_LIT:1> <EOL> else : <EOL> index = max ( <NUM_LIT:0> , self . complete_state . complete_index - count ) <EOL> self . go_to_completion ( index ) <EOL> def cancel_completion ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . complete_state : <EOL> self . go_to_completion ( None ) <EOL> self . complete_state = None <EOL> def set_completions ( self , completions , go_to_first = True , go_to_last = False ) : <EOL> """<STR_LIT>""" <EOL> assert not ( go_to_first and go_to_last ) <EOL> if completions is None : <EOL> if self . completer : <EOL> completions = list ( self . completer . get_completions ( <EOL> self . document , <EOL> CompleteEvent ( completion_requested = True ) <EOL> ) ) <EOL> else : <EOL> completions = [ ] <EOL> if completions : <EOL> self . complete_state = CompletionState ( <EOL> original_document = self . document , <EOL> current_completions = completions ) <EOL> if go_to_first : <EOL> self . go_to_completion ( <NUM_LIT:0> ) <EOL> elif go_to_last : <EOL> self . go_to_completion ( len ( completions ) - <NUM_LIT:1> ) <EOL> else : <EOL> self . go_to_completion ( None ) <EOL> else : <EOL> self . complete_state = None <EOL> def start_history_lines_completion ( self ) : <EOL> """<STR_LIT>""" <EOL> found_completions = set ( ) <EOL> completions = [ ] <EOL> current_line = self . document . current_line_before_cursor . lstrip ( ) <EOL> for i , string in enumerate ( self . _working_lines ) : <EOL> for j , l in enumerate ( string . split ( '<STR_LIT:\n>' ) ) : <EOL> l = l . strip ( ) <EOL> if l and l . startswith ( current_line ) : <EOL> if l not in found_completions : <EOL> found_completions . add ( l ) <EOL> if i == self . working_index : <EOL> display_meta = "<STR_LIT>" % ( j + <NUM_LIT:1> ) <EOL> else : <EOL> display_meta = "<STR_LIT>" % ( i + <NUM_LIT:1> , j + <NUM_LIT:1> ) <EOL> completions . append ( Completion ( <EOL> l , <EOL> start_position = - len ( current_line ) , <EOL> display_meta = display_meta ) ) <EOL> self . set_completions ( completions = completions [ : : - <NUM_LIT:1> ] ) <EOL> def go_to_completion ( self , index ) : <EOL> """<STR_LIT>""" <EOL> assert index is None or isinstance ( index , int ) <EOL> assert self . complete_state <EOL> state = self . complete_state . go_to_index ( index ) <EOL> new_text , new_cursor_position = state . new_text_and_position ( ) <EOL> self . document = Document ( new_text , new_cursor_position ) <EOL> self . complete_state = state <EOL> def apply_completion ( self , completion ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( completion , Completion ) <EOL> if self . complete_state : <EOL> self . go_to_completion ( None ) <EOL> self . complete_state = None <EOL> self . delete_before_cursor ( - completion . start_position ) <EOL> self . insert_text ( completion . text ) <EOL> def _set_history_search ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . enable_history_search ( ) : <EOL> if self . history_search_text is None : <EOL> self . history_search_text = self . text <EOL> else : <EOL> self . history_search_text = None <EOL> def _history_matches ( self , i ) : <EOL> """<STR_LIT>""" <EOL> return ( self . history_search_text is None or <EOL> self . _working_lines [ i ] . startswith ( self . history_search_text ) ) <EOL> def history_forward ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> self . _set_history_search ( ) <EOL> found_something = False <EOL> for i in range ( self . working_index + <NUM_LIT:1> , len ( self . _working_lines ) ) : <EOL> if self . _history_matches ( i ) : <EOL> self . working_index = i <EOL> count -= <NUM_LIT:1> <EOL> found_something = True <EOL> if count == <NUM_LIT:0> : <EOL> break <EOL> if found_something : <EOL> self . cursor_position = <NUM_LIT:0> <EOL> self . cursor_position += self . document . get_end_of_line_position ( ) <EOL> def history_backward ( self , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> self . _set_history_search ( ) <EOL> found_something = False <EOL> for i in range ( self . working_index - <NUM_LIT:1> , - <NUM_LIT:1> , - <NUM_LIT:1> ) : <EOL> if self . _history_matches ( i ) : <EOL> self . working_index = i <EOL> count -= <NUM_LIT:1> <EOL> found_something = True <EOL> if count == <NUM_LIT:0> : <EOL> break <EOL> if found_something : <EOL> self . cursor_position = len ( self . text ) <EOL> def start_selection ( self , selection_type = SelectionType . CHARACTERS ) : <EOL> """<STR_LIT>""" <EOL> self . selection_state = SelectionState ( self . cursor_position , selection_type ) <EOL> def copy_selection ( self , _cut = False ) : <EOL> """<STR_LIT>""" <EOL> new_document , clipboard_data = self . document . cut_selection ( ) <EOL> if _cut : <EOL> self . document = new_document <EOL> self . selection_state = None <EOL> return clipboard_data <EOL> def cut_selection ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . copy_selection ( _cut = True ) <EOL> def paste_clipboard_data ( self , data , before = False , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( data , ClipboardData ) <EOL> self . document = self . document . paste_clipboard_data ( data , before = before , count = count ) <EOL> def newline ( self , copy_margin = True ) : <EOL> """<STR_LIT>""" <EOL> if copy_margin : <EOL> self . insert_text ( '<STR_LIT:\n>' + self . document . leading_whitespace_in_current_line ) <EOL> else : <EOL> self . insert_text ( '<STR_LIT:\n>' ) <EOL> def insert_line_above ( self , copy_margin = True ) : <EOL> """<STR_LIT>""" <EOL> if copy_margin : <EOL> insert = self . document . leading_whitespace_in_current_line + '<STR_LIT:\n>' <EOL> else : <EOL> insert = '<STR_LIT:\n>' <EOL> self . cursor_position += self . document . get_start_of_line_position ( ) <EOL> self . insert_text ( insert ) <EOL> self . cursor_position -= <NUM_LIT:1> <EOL> def insert_line_below ( self , copy_margin = True ) : <EOL> """<STR_LIT>""" <EOL> if copy_margin : <EOL> insert = '<STR_LIT:\n>' + self . document . leading_whitespace_in_current_line <EOL> else : <EOL> insert = '<STR_LIT:\n>' <EOL> self . cursor_position += self . document . get_end_of_line_position ( ) <EOL> self . insert_text ( insert ) <EOL> def insert_text ( self , data , overwrite = False , move_cursor = True , fire_event = True ) : <EOL> """<STR_LIT>""" <EOL> otext = self . text <EOL> ocpos = self . cursor_position <EOL> if overwrite : <EOL> overwritten_text = otext [ ocpos : ocpos + len ( data ) ] <EOL> if '<STR_LIT:\n>' in overwritten_text : <EOL> overwritten_text = overwritten_text [ : overwritten_text . find ( '<STR_LIT:\n>' ) ] <EOL> self . text = otext [ : ocpos ] + data + otext [ ocpos + len ( overwritten_text ) : ] <EOL> else : <EOL> self . text = otext [ : ocpos ] + data + otext [ ocpos : ] <EOL> if move_cursor : <EOL> self . cursor_position += len ( data ) <EOL> if fire_event : <EOL> self . on_text_insert . fire ( ) <EOL> def undo ( self ) : <EOL> while self . _undo_stack : <EOL> text , pos = self . _undo_stack . pop ( ) <EOL> if text != self . text : <EOL> self . _redo_stack . append ( ( self . text , self . cursor_position ) ) <EOL> self . document = Document ( text , cursor_position = pos ) <EOL> break <EOL> def redo ( self ) : <EOL> if self . _redo_stack : <EOL> self . save_to_undo_stack ( clear_redo_stack = False ) <EOL> text , pos = self . _redo_stack . pop ( ) <EOL> self . document = Document ( text , cursor_position = pos ) <EOL> def validate ( self ) : <EOL> """<STR_LIT>""" <EOL> self . validation_error = None <EOL> if self . validator : <EOL> try : <EOL> self . validator . validate ( self . document ) <EOL> except ValidationError as e : <EOL> cursor_position = e . cursor_position <EOL> self . cursor_position = min ( max ( <NUM_LIT:0> , cursor_position ) , len ( self . text ) ) <EOL> self . validation_error = e <EOL> return False <EOL> return True <EOL> def append_to_history ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . validate ( ) : <EOL> return <EOL> if self . text and ( not len ( self . history ) or self . history [ - <NUM_LIT:1> ] != self . text ) : <EOL> self . history . append ( self . text ) <EOL> def _search ( self , search_state , include_current_position = False , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> assert isinstance ( search_state , SearchState ) <EOL> assert isinstance ( count , int ) and count > <NUM_LIT:0> <EOL> text = search_state . text <EOL> direction = search_state . direction <EOL> ignore_case = search_state . ignore_case ( ) <EOL> def search_once ( working_index , document ) : <EOL> """<STR_LIT>""" <EOL> if direction == IncrementalSearchDirection . FORWARD : <EOL> new_index = document . find ( <EOL> text , include_current_position = include_current_position , <EOL> ignore_case = ignore_case ) <EOL> if new_index is not None : <EOL> return ( working_index , <EOL> Document ( document . text , document . cursor_position + new_index ) ) <EOL> else : <EOL> for i in range ( working_index + <NUM_LIT:1> , len ( self . _working_lines ) + <NUM_LIT:1> ) : <EOL> i %= len ( self . _working_lines ) <EOL> document = Document ( self . _working_lines [ i ] , <NUM_LIT:0> ) <EOL> new_index = document . find ( text , include_current_position = True , <EOL> ignore_case = ignore_case ) <EOL> if new_index is not None : <EOL> return ( i , Document ( document . text , new_index ) ) <EOL> else : <EOL> new_index = document . find_backwards ( <EOL> text , ignore_case = ignore_case ) <EOL> if new_index is not None : <EOL> return ( working_index , <EOL> Document ( document . text , document . cursor_position + new_index ) ) <EOL> else : <EOL> for i in range ( working_index - <NUM_LIT:1> , - <NUM_LIT:2> , - <NUM_LIT:1> ) : <EOL> i %= len ( self . _working_lines ) <EOL> document = Document ( self . _working_lines [ i ] , len ( self . _working_lines [ i ] ) ) <EOL> new_index = document . find_backwards ( <EOL> text , ignore_case = ignore_case ) <EOL> if new_index is not None : <EOL> return ( i , Document ( document . text , len ( document . text ) + new_index ) ) <EOL> working_index = self . working_index <EOL> document = self . document <EOL> for _ in range ( count ) : <EOL> result = search_once ( working_index , document ) <EOL> if result is None : <EOL> return <EOL> else : <EOL> working_index , document = result <EOL> return ( working_index , document . cursor_position ) <EOL> def document_for_search ( self , search_state ) : <EOL> """<STR_LIT>""" <EOL> search_result = self . _search ( search_state , include_current_position = True ) <EOL> if search_result is None : <EOL> return self . document <EOL> else : <EOL> working_index , cursor_position = search_result <EOL> return Document ( self . _working_lines [ working_index ] , cursor_position ) <EOL> def apply_search ( self , search_state , include_current_position = True , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> search_result = self . _search ( <EOL> search_state , include_current_position = include_current_position , count = count ) <EOL> if search_result is not None : <EOL> working_index , cursor_position = search_result <EOL> self . working_index = working_index <EOL> self . cursor_position = cursor_position <EOL> def exit_selection ( self ) : <EOL> self . selection_state = None <EOL> def open_in_editor ( self , cli ) : <EOL> """<STR_LIT>""" <EOL> if self . read_only ( ) : <EOL> raise EditReadOnlyBuffer ( ) <EOL> descriptor , filename = tempfile . mkstemp ( self . tempfile_suffix ) <EOL> os . write ( descriptor , self . text . encode ( '<STR_LIT:utf-8>' ) ) <EOL> os . close ( descriptor ) <EOL> succes = cli . run_in_terminal ( lambda : self . _open_file_in_editor ( filename ) ) <EOL> if succes : <EOL> with open ( filename , '<STR_LIT:rb>' ) as f : <EOL> text = f . read ( ) . decode ( '<STR_LIT:utf-8>' ) <EOL> if text . endswith ( '<STR_LIT:\n>' ) : <EOL> text = text [ : - <NUM_LIT:1> ] <EOL> self . document = Document ( <EOL> text = text , <EOL> cursor_position = len ( text ) ) <EOL> os . remove ( filename ) <EOL> def _open_file_in_editor ( self , filename ) : <EOL> """<STR_LIT>""" <EOL> editor = os . environ . get ( '<STR_LIT>' ) <EOL> editors = [ <EOL> editor , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> '<STR_LIT>' , <EOL> ] <EOL> for e in editors : <EOL> if e : <EOL> try : <EOL> returncode = subprocess . call ( [ e , filename ] ) <EOL> return returncode == <NUM_LIT:0> <EOL> except OSError : <EOL> pass <EOL> return False <EOL> def indent ( buffer , from_row , to_row , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> current_row = buffer . document . cursor_position_row <EOL> line_range = range ( from_row , to_row ) <EOL> new_text = buffer . transform_lines ( line_range , lambda l : '<STR_LIT:U+0020>' * count + l ) <EOL> buffer . document = Document ( <EOL> new_text , <EOL> Document ( new_text ) . translate_row_col_to_index ( current_row , <NUM_LIT:0> ) ) <EOL> buffer . cursor_position += buffer . document . get_start_of_line_position ( after_whitespace = True ) <EOL> def unindent ( buffer , from_row , to_row , count = <NUM_LIT:1> ) : <EOL> """<STR_LIT>""" <EOL> current_row = buffer . document . cursor_position_row <EOL> line_range = range ( from_row , to_row ) <EOL> def transform ( text ) : <EOL> remove = '<STR_LIT:U+0020>' * count <EOL> if text . startswith ( remove ) : <EOL> return text [ len ( remove ) : ] <EOL> else : <EOL> return text . lstrip ( ) <EOL> new_text = buffer . transform_lines ( line_range , transform ) <EOL> buffer . document = Document ( <EOL> new_text , <EOL> Document ( new_text ) . translate_row_col_to_index ( current_row , <NUM_LIT:0> ) ) <EOL> buffer . cursor_position += buffer . document . get_start_of_line_position ( after_whitespace = True ) <EOL> def reshape_text ( buffer , from_row , to_row ) : <EOL> """<STR_LIT>""" <EOL> lines = buffer . text . splitlines ( True ) <EOL> lines_before = lines [ : from_row ] <EOL> lines_after = lines [ to_row + <NUM_LIT:1> : ] <EOL> lines_to_reformat = lines [ from_row : to_row + <NUM_LIT:1> ] <EOL> if lines_to_reformat : <EOL> length = re . search ( r'<STR_LIT>' , lines_to_reformat [ <NUM_LIT:0> ] ) . end ( ) <EOL> indent = lines_to_reformat [ <NUM_LIT:0> ] [ : length ] . replace ( '<STR_LIT:\n>' , '<STR_LIT>' ) <EOL> words = '<STR_LIT>' . join ( lines_to_reformat ) . split ( ) <EOL> width = ( buffer . text_width or <NUM_LIT> ) - len ( indent ) <EOL> reshaped_text = [ indent ] <EOL> current_width = <NUM_LIT:0> <EOL> for w in words : <EOL> if current_width : <EOL> if len ( w ) + current_width + <NUM_LIT:1> > width : <EOL> reshaped_text . append ( '<STR_LIT:\n>' ) <EOL> reshaped_text . append ( indent ) <EOL> current_width = <NUM_LIT:0> <EOL> else : <EOL> reshaped_text . append ( '<STR_LIT:U+0020>' ) <EOL> current_width += <NUM_LIT:1> <EOL> reshaped_text . append ( w ) <EOL> current_width += len ( w ) <EOL> if reshaped_text [ - <NUM_LIT:1> ] != '<STR_LIT:\n>' : <EOL> reshaped_text . append ( '<STR_LIT:\n>' ) <EOL> buffer . document = Document ( <EOL> text = '<STR_LIT>' . join ( lines_before + reshaped_text + lines_after ) , <EOL> cursor_position = len ( '<STR_LIT>' . join ( lines_before + reshaped_text ) ) ) </s>
