Skip to content

Commit

Permalink
more quit commands prompt-toolkit#125
Browse files Browse the repository at this point in the history
  • Loading branch information
nakagami committed Jul 7, 2024
1 parent 10cbf46 commit 88398ff
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 23 deletions.
51 changes: 31 additions & 20 deletions pyvim/commands/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ def buffer_add(editor, location):
editor.window_arrangement.open_buffer(location)


@cmd('files')
@cmd('ls')
@cmd('buffers')
def buffer_list(editor):
"""
Expand Down Expand Up @@ -280,22 +282,18 @@ def buffer_edit(editor, location, force=False):

@cmd('q', accepts_force=True)
@cmd('quit', accepts_force=True)
def quit(editor, all_=False, force=False):
def quit(editor, force=False):
"""
Quit.
"""
ebs = editor.window_arrangement.editor_buffers

# When there are buffers that have unsaved changes, show balloon.
if not force and any(eb.has_unsaved_changes for eb in ebs):
eb = editor.window_arrangement.active_editor_buffer
eb_is_open_in_another_window = len(list(editor.window_arrangement.get_windows_for_buffer(eb))) > 1
if not force and eb.has_unsaved_changes and not eb_is_open_in_another_window:
editor.show_message(_NO_WRITE_SINCE_LAST_CHANGE_TEXT)

# When there is more than one buffer open.
elif not all_ and len(ebs) > 1:
editor.show_message('%i more files to edit' % (len(ebs) - 1))

else:
elif editor.window_arrangement.active_tab.window_count() == 1 and len(editor.window_arrangement.tab_pages) == 1:
editor.application.exit()
else:
editor.window_arrangement.close_window()


@cmd('qa', accepts_force=True)
Expand All @@ -304,7 +302,11 @@ def quit_all(editor, force=False):
"""
Quit all.
"""
quit(editor, all_=True, force=force)
ebs = editor.window_arrangement.editor_buffers
if not force and any(eb.has_unsaved_changes for eb in ebs):
editor.show_message(_NO_WRITE_SINCE_LAST_CHANGE_TEXT)
else:
editor.application.exit()


@location_cmd('w', accepts_force=True)
Expand All @@ -329,7 +331,7 @@ def write_and_quit(editor, location, force=False):
Write file and quit.
"""
write(editor, location, force=force)
editor.application.exit()
quit(editor)


@cmd('cq')
Expand All @@ -343,17 +345,26 @@ def quit_nonzero(editor):
editor.application.exit()


@cmd('wa')
def write_all(editor):
"""
Write all changed buffers
"""
for eb in editor.window_arrangement.editor_buffers:
if eb.location is None:
editor.show_message(_NO_FILE_NAME)
break
else:
eb.write()


@cmd('wqa')
def write_and_quit_all(editor):
"""
Write current buffer and quit all.
Write all changed buffers and quit all.
"""
eb = editor.window_arrangement.active_editor_buffer
if eb.location is None:
editor.show_message(_NO_FILE_NAME)
else:
eb.write()
quit(editor, all_=True, force=False)
write_all(editor)
quit_all(editor)


@cmd('h')
Expand Down
27 changes: 26 additions & 1 deletion pyvim/key_bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from prompt_toolkit.filters import Condition, has_focus, vi_insert_mode, vi_navigation_mode
from prompt_toolkit.key_binding import KeyBindings

from .commands.commands import write_and_quit, quit

import os

__all__ = (
Expand Down Expand Up @@ -36,6 +38,29 @@ def vi_buffer_focussed():
in_insert_mode = vi_insert_mode & vi_buffer_focussed
in_navigation_mode = vi_navigation_mode & vi_buffer_focussed

@kb.add('Z', 'Z', filter=in_navigation_mode)
def _(event):
"""
Write and quit.
"""
write_and_quit(editor, None)
editor.sync_with_prompt_toolkit()

@kb.add('Z', 'Q', filter=in_navigation_mode)
def _(event):
"""
Quit and discard changes.
"""
quit(editor, force=True)
editor.sync_with_prompt_toolkit()

@kb.add('c-z', filter=in_navigation_mode)
def _(event):
"""
Suspend process to background.
"""
event.app.suspend_to_background()

@kb.add('c-t')
def _(event):
"""
Expand All @@ -50,7 +75,7 @@ def indent_line(event):
"""
Indent current line.
"""
b = event.application.current_buffer
b = event.app.current_buffer

# Move to start of line.
pos = b.document.get_start_of_line_position(after_whitespace=True)
Expand Down
15 changes: 13 additions & 2 deletions pyvim/window_arrangement.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class HSplit(list):


class VSplit(list):
""" Horizontal split. """
""" Vertical split. """


class Window(object):
Expand Down Expand Up @@ -101,6 +101,10 @@ def _get_split_parent(self, split):
if child == split:
return parent

def get_windows_for_buffer(self, editor_buffer):
""" Return a list of all windows in this tab page. """
return (window for _, window in self._walk_through_windows() if window.editor_buffer == editor_buffer)

def _split(self, split_cls, editor_buffer=None):
"""
Split horizontal or vertical.
Expand Down Expand Up @@ -258,11 +262,18 @@ def get_editor_buffer_for_buffer_name(self, buffer_name):
if eb.buffer_name == buffer_name:
return eb

def get_windows_for_buffer(self, editor_buffer):
""" Return a list of all windows in this tab page. """
return (b for t in self.tab_pages for b in t.get_windows_for_buffer(editor_buffer))

def close_window(self):
"""
Close active window of active tab.
"""
self.active_tab.close_active_window()
if self.active_tab.window_count() > 1:
self.active_tab.close_active_window()
else:
self.close_tab()

# Clean up buffers.
self._auto_close_new_empty_buffers()
Expand Down
16 changes: 16 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,19 @@ def window(editor_buffer):
@pytest.fixture
def tab_page(window):
return TabPage(window)


@pytest.fixture
def tab_page_with_splits(editor_buffer, window):
editor_buffer2 = EditorBuffer(editor)

tab_page = TabPage(Window(editor_buffer))
tab_page.vsplit(editor_buffer)
tab_page.vsplit(editor_buffer2)
tab_page.hsplit(editor_buffer)
return tab_page


@pytest.fixture
def window_arrangement(editor):
return WindowArrangement(editor)
36 changes: 36 additions & 0 deletions tests/test_window_arrangements.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,39 @@ def test_vsplit(editor, tab_page):

assert isinstance(tab_page.root, VSplit)
assert len(tab_page.root) == 2


def test_tab_page_get_windows_for_buffer(editor, editor_buffer, tab_page_with_splits):
tab_page1 = tab_page_with_splits

windows = list(tab_page1.get_windows_for_buffer(editor_buffer))
assert all(w.editor_buffer == editor_buffer for w in windows)
assert len(windows) == 3


def test_window_arrangement_get_windows_for_buffer(editor, editor_buffer, tab_page_with_splits, window_arrangement):
tab_page1 = tab_page_with_splits
tab_page2 = TabPage(Window(editor_buffer))

window_arrangement.tab_pages[:] = [tab_page1, tab_page2]
windows = list(window_arrangement.get_windows_for_buffer(editor_buffer))
assert all(w.editor_buffer == editor_buffer for w in windows)
assert len(windows) == 4


def test_close_window_closes_split(editor):
editor.window_arrangement.create_tab()
editor.window_arrangement.hsplit()
assert len(editor.window_arrangement.tab_pages) == 2

assert editor.window_arrangement.active_tab.window_count() == 2
editor.window_arrangement.close_window()
assert editor.window_arrangement.active_tab.window_count() == 1


def test_close_window_also_closes_empty_tab(editor):
editor.window_arrangement.create_tab()

assert len(editor.window_arrangement.tab_pages) == 2
editor.window_arrangement.close_window()
assert len(editor.window_arrangement.tab_pages) == 1

0 comments on commit 88398ff

Please sign in to comment.