implement find-replace
This commit is contained in:
@@ -796,7 +796,7 @@ def test_search_history_is_saved_between_sessions(xdg_data_home):
|
||||
h.press('Enter')
|
||||
|
||||
|
||||
def test_multiple_sessions_append_to_history(xdg_data_home):
|
||||
def test_search_multiple_sessions_append_to_history(xdg_data_home):
|
||||
xdg_data_home.join('babi/history/search').ensure().write(
|
||||
'orig\n'
|
||||
'history\n',
|
||||
@@ -930,6 +930,237 @@ def test_search_reverse_search_keeps_current_text_displayed():
|
||||
h.press('^C')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('key', ('^C', 'Enter'))
|
||||
def test_replace_cancel(key):
|
||||
with run() as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press(key)
|
||||
h.await_text('cancelled')
|
||||
|
||||
|
||||
def test_replace_invalid_regex():
|
||||
with run() as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('(')
|
||||
h.await_text("invalid regex: '('")
|
||||
|
||||
|
||||
def test_replace_cancel_at_replace_string():
|
||||
with run() as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('hello')
|
||||
h.await_text('replace with:')
|
||||
h.press('^C')
|
||||
h.await_text('cancelled')
|
||||
|
||||
|
||||
def test_replace_actual_contents(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('line_0')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('ohai')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_0')
|
||||
h.await_text('ohai')
|
||||
h.await_text(' *')
|
||||
h.await_text('replaced 1 occurrence')
|
||||
|
||||
|
||||
def test_replace_cancel_at_individual_replace(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter(r'line_\d')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('ohai')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('^C')
|
||||
h.await_text('cancelled')
|
||||
|
||||
|
||||
def test_replace_unknown_characters_at_individual_replace(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter(r'line_\d')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('ohai')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('?')
|
||||
h.press('^C')
|
||||
h.await_text('cancelled')
|
||||
|
||||
|
||||
def test_replace_say_no_to_individual_replace(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('line_[135]')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('ohai')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_1')
|
||||
h.press('n')
|
||||
h.await_text('line_3')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_5')
|
||||
h.await_text('replaced 2 occurrences')
|
||||
|
||||
|
||||
def test_replace_all(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter(r'line_(\d)')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter(r'ohai+\1')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('a')
|
||||
h.await_text_missing('line')
|
||||
h.await_text('ohai+1')
|
||||
h.await_text('replaced 10 occurrences')
|
||||
|
||||
|
||||
def test_replace_with_empty_string(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('line_1')
|
||||
h.await_text('replace with:')
|
||||
h.press('Enter')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_1')
|
||||
|
||||
|
||||
def test_replace_search_not_found(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('wat')
|
||||
# TODO: would be nice to not prompt for a replace string in this case
|
||||
h.await_text('replace with:')
|
||||
h.press('Enter')
|
||||
h.await_text('no matches')
|
||||
|
||||
|
||||
def test_replace_small_window_size(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('line')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('wat')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
|
||||
with h.resize(width=8, height=24):
|
||||
h.await_text('replace…')
|
||||
|
||||
h.press('^C')
|
||||
|
||||
|
||||
def test_replace_line_goes_off_screen():
|
||||
with run() as h, and_exit(h):
|
||||
h.press(f'{"a" * 20}{"b" * 90}')
|
||||
h.press('^A')
|
||||
h.await_text(f'{"a" * 20}{"b" * 59}»')
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('b+')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('wat')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.await_text(f'{"a" * 20}{"b" * 59}»')
|
||||
h.press('y')
|
||||
h.await_text(f'{"a" * 20}wat')
|
||||
h.await_text('replaced 1 occurrence')
|
||||
|
||||
|
||||
def test_replace_undo_undoes_only_one(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('line')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('wat')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_0')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_1')
|
||||
h.press('^C')
|
||||
h.press('M-u')
|
||||
h.await_text('line_1')
|
||||
h.await_text_missing('line_0')
|
||||
|
||||
|
||||
def test_replace_multiple_occurrences_in_line():
|
||||
with run() as h, and_exit(h):
|
||||
h.press('baaaaabaaaaa')
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('a+')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('q')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('a')
|
||||
h.await_text('bqbq')
|
||||
|
||||
|
||||
def test_replace_after_wrapping(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('Down')
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('line_[02]')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('ohai')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_2')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_0')
|
||||
h.await_text('replaced 2 occurrences')
|
||||
|
||||
|
||||
def test_replace_after_cursor_after_wrapping():
|
||||
with run() as h, and_exit(h):
|
||||
h.press('baaab')
|
||||
h.press('Left')
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('b')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('q')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('n')
|
||||
h.press('y')
|
||||
h.await_text('replaced 1 occurrence')
|
||||
h.await_text('qaaab')
|
||||
|
||||
|
||||
def test_replace_separate_line_after_wrapping(ten_lines):
|
||||
with run(str(ten_lines)) as h, and_exit(h):
|
||||
h.press('Down')
|
||||
h.press('Down')
|
||||
h.press('^\\')
|
||||
h.await_text('search (to replace):')
|
||||
h.press_and_enter('line_[01]')
|
||||
h.await_text('replace with:')
|
||||
h.press_and_enter('_')
|
||||
h.await_text('replace [y(es), n(o), a(ll)]?')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_0')
|
||||
h.press('y')
|
||||
h.await_text_missing('line_1')
|
||||
|
||||
|
||||
def test_scrolling_arrow_key_movement(ten_lines):
|
||||
with run(str(ten_lines), height=10) as h, and_exit(h):
|
||||
h.await_text('line_7')
|
||||
|
||||
Reference in New Issue
Block a user