55from unittest import TestCase
66from unittest .mock import patch
77
8- from .support import FakeConsole , handle_all_events , handle_events_narrow_console
9- from .support import more_lines , multiline_input , code_to_events
8+ from .support import (
9+ FakeConsole ,
10+ handle_all_events ,
11+ handle_events_narrow_console ,
12+ more_lines ,
13+ multiline_input ,
14+ code_to_events ,
15+ )
1016from _pyrepl .console import Event
1117from _pyrepl .readline import ReadlineAlikeReader , ReadlineConfig
1218from _pyrepl .readline import multiline_input as readline_multiline_input
1319
1420
1521class TestCursorPosition (TestCase ):
22+ def prepare_reader (self , events ):
23+ console = FakeConsole (events )
24+ config = ReadlineConfig (readline_completer = None )
25+ reader = ReadlineAlikeReader (console = console , config = config )
26+ return reader
27+
1628 def test_up_arrow_simple (self ):
1729 # fmt: off
1830 code = (
@@ -300,6 +312,79 @@ def test_cursor_position_after_wrap_and_move_up(self):
300312 self .assertEqual (reader .pos , 10 )
301313 self .assertEqual (reader .cxy , (1 , 1 ))
302314
315+ def test_auto_indent_default (self ):
316+ # fmt: off
317+ input_code = (
318+ 'def f():\n '
319+ 'pass\n \n '
320+ )
321+
322+ output_code = (
323+ 'def f():\n '
324+ ' pass\n '
325+ ' '
326+ )
327+ # fmt: on
328+
329+ def test_auto_indent_continuation (self ):
330+ # auto indenting according to previous user indentation
331+ # fmt: off
332+ events = itertools .chain (
333+ code_to_events ("def f():\n " ),
334+ # add backspace to delete default auto-indent
335+ [
336+ Event (evt = "key" , data = "backspace" , raw = bytearray (b"\x7f " )),
337+ ],
338+ code_to_events (
339+ " pass\n "
340+ "pass\n \n "
341+ ),
342+ )
343+
344+ output_code = (
345+ 'def f():\n '
346+ ' pass\n '
347+ ' pass\n '
348+ ' '
349+ )
350+ # fmt: on
351+
352+ reader = self .prepare_reader (events )
353+ output = multiline_input (reader )
354+ self .assertEqual (output , output_code )
355+
356+ def test_auto_indent_prev_block (self ):
357+ # auto indenting according to indentation in different block
358+ # fmt: off
359+ events = itertools .chain (
360+ code_to_events ("def f():\n " ),
361+ # add backspace to delete default auto-indent
362+ [
363+ Event (evt = "key" , data = "backspace" , raw = bytearray (b"\x7f " )),
364+ ],
365+ code_to_events (
366+ " pass\n "
367+ "pass\n \n "
368+ ),
369+ code_to_events (
370+ 'def g():\n '
371+ 'pass\n \n '
372+ ),
373+ )
374+
375+
376+ output_code = (
377+ 'def g():\n '
378+ ' pass\n '
379+ ' '
380+ )
381+ # fmt: on
382+
383+ reader = self .prepare_reader (events )
384+ output1 = multiline_input (reader )
385+ output2 = multiline_input (reader )
386+ self .assertEqual (output2 , output_code )
387+
303388
304389class TestPyReplOutput (TestCase ):
305390 def prepare_reader (self , events ):
@@ -316,14 +401,12 @@ def test_basic(self):
316401
317402 def test_multiline_edit (self ):
318403 events = itertools .chain (
319- code_to_events ("def f():\n ...\n \n " ),
404+ code_to_events ("def f():\n ...\n \n " ),
320405 [
321406 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
322407 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
323408 Event (evt = "key" , data = "up" , raw = bytearray (b"\x1b OA" )),
324409 Event (evt = "key" , data = "right" , raw = bytearray (b"\x1b OC" )),
325- Event (evt = "key" , data = "right" , raw = bytearray (b"\x1b OC" )),
326- Event (evt = "key" , data = "right" , raw = bytearray (b"\x1b OC" )),
327410 Event (evt = "key" , data = "backspace" , raw = bytearray (b"\x7f " )),
328411 Event (evt = "key" , data = "g" , raw = bytearray (b"g" )),
329412 Event (evt = "key" , data = "down" , raw = bytearray (b"\x1b OB" )),
@@ -334,9 +417,9 @@ def test_multiline_edit(self):
334417 reader = self .prepare_reader (events )
335418
336419 output = multiline_input (reader )
337- self .assertEqual (output , "def f():\n ...\n " )
420+ self .assertEqual (output , "def f():\n ...\n " )
338421 output = multiline_input (reader )
339- self .assertEqual (output , "def g():\n ...\n " )
422+ self .assertEqual (output , "def g():\n ...\n " )
340423
341424 def test_history_navigation_with_up_arrow (self ):
342425 events = itertools .chain (
@@ -559,14 +642,14 @@ def test_paste_mid_newlines_not_in_paste_mode(self):
559642 # fmt: off
560643 code = (
561644 'def f():\n '
562- ' x = y\n '
563- ' \n '
564- ' y = z\n \n '
645+ ' x = y\n '
646+ ' \n '
647+ ' y = z\n \n '
565648 )
566649
567650 expected = (
568651 'def f():\n '
569- ' x = y\n '
652+ ' x = y\n '
570653 ' '
571654 )
572655 # fmt: on
@@ -580,19 +663,19 @@ def test_paste_not_in_paste_mode(self):
580663 # fmt: off
581664 input_code = (
582665 'def a():\n '
583- ' for x in range(10):\n '
584- ' if x%2:\n '
585- ' print(x)\n '
586- ' else:\n '
587- ' pass\n \n '
666+ ' for x in range(10):\n '
667+ ' if x%2:\n '
668+ ' print(x)\n '
669+ ' else:\n '
670+ ' pass\n \n '
588671 )
589672
590673 output_code = (
591674 'def a():\n '
592- ' for x in range(10):\n '
593- ' if x%2:\n '
675+ ' for x in range(10):\n '
676+ ' if x%2:\n '
594677 ' print(x)\n '
595- ' else:'
678+ ' else:'
596679 )
597680 # fmt: on
598681
0 commit comments