Skip to content

Commit 88398ff

Browse files
committed
more quit commands prompt-toolkit#125
1 parent 10cbf46 commit 88398ff

File tree

5 files changed

+122
-23
lines changed

5 files changed

+122
-23
lines changed

pyvim/commands/commands.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ def buffer_add(editor, location):
209209
editor.window_arrangement.open_buffer(location)
210210

211211

212+
@cmd('files')
213+
@cmd('ls')
212214
@cmd('buffers')
213215
def buffer_list(editor):
214216
"""
@@ -280,22 +282,18 @@ def buffer_edit(editor, location, force=False):
280282

281283
@cmd('q', accepts_force=True)
282284
@cmd('quit', accepts_force=True)
283-
def quit(editor, all_=False, force=False):
285+
def quit(editor, force=False):
284286
"""
285287
Quit.
286288
"""
287-
ebs = editor.window_arrangement.editor_buffers
288-
289-
# When there are buffers that have unsaved changes, show balloon.
290-
if not force and any(eb.has_unsaved_changes for eb in ebs):
289+
eb = editor.window_arrangement.active_editor_buffer
290+
eb_is_open_in_another_window = len(list(editor.window_arrangement.get_windows_for_buffer(eb))) > 1
291+
if not force and eb.has_unsaved_changes and not eb_is_open_in_another_window:
291292
editor.show_message(_NO_WRITE_SINCE_LAST_CHANGE_TEXT)
292-
293-
# When there is more than one buffer open.
294-
elif not all_ and len(ebs) > 1:
295-
editor.show_message('%i more files to edit' % (len(ebs) - 1))
296-
297-
else:
293+
elif editor.window_arrangement.active_tab.window_count() == 1 and len(editor.window_arrangement.tab_pages) == 1:
298294
editor.application.exit()
295+
else:
296+
editor.window_arrangement.close_window()
299297

300298

301299
@cmd('qa', accepts_force=True)
@@ -304,7 +302,11 @@ def quit_all(editor, force=False):
304302
"""
305303
Quit all.
306304
"""
307-
quit(editor, all_=True, force=force)
305+
ebs = editor.window_arrangement.editor_buffers
306+
if not force and any(eb.has_unsaved_changes for eb in ebs):
307+
editor.show_message(_NO_WRITE_SINCE_LAST_CHANGE_TEXT)
308+
else:
309+
editor.application.exit()
308310

309311

310312
@location_cmd('w', accepts_force=True)
@@ -329,7 +331,7 @@ def write_and_quit(editor, location, force=False):
329331
Write file and quit.
330332
"""
331333
write(editor, location, force=force)
332-
editor.application.exit()
334+
quit(editor)
333335

334336

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

345347

348+
@cmd('wa')
349+
def write_all(editor):
350+
"""
351+
Write all changed buffers
352+
"""
353+
for eb in editor.window_arrangement.editor_buffers:
354+
if eb.location is None:
355+
editor.show_message(_NO_FILE_NAME)
356+
break
357+
else:
358+
eb.write()
359+
360+
346361
@cmd('wqa')
347362
def write_and_quit_all(editor):
348363
"""
349-
Write current buffer and quit all.
364+
Write all changed buffers and quit all.
350365
"""
351-
eb = editor.window_arrangement.active_editor_buffer
352-
if eb.location is None:
353-
editor.show_message(_NO_FILE_NAME)
354-
else:
355-
eb.write()
356-
quit(editor, all_=True, force=False)
366+
write_all(editor)
367+
quit_all(editor)
357368

358369

359370
@cmd('h')

pyvim/key_bindings.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from prompt_toolkit.filters import Condition, has_focus, vi_insert_mode, vi_navigation_mode
33
from prompt_toolkit.key_binding import KeyBindings
44

5+
from .commands.commands import write_and_quit, quit
6+
57
import os
68

79
__all__ = (
@@ -36,6 +38,29 @@ def vi_buffer_focussed():
3638
in_insert_mode = vi_insert_mode & vi_buffer_focussed
3739
in_navigation_mode = vi_navigation_mode & vi_buffer_focussed
3840

41+
@kb.add('Z', 'Z', filter=in_navigation_mode)
42+
def _(event):
43+
"""
44+
Write and quit.
45+
"""
46+
write_and_quit(editor, None)
47+
editor.sync_with_prompt_toolkit()
48+
49+
@kb.add('Z', 'Q', filter=in_navigation_mode)
50+
def _(event):
51+
"""
52+
Quit and discard changes.
53+
"""
54+
quit(editor, force=True)
55+
editor.sync_with_prompt_toolkit()
56+
57+
@kb.add('c-z', filter=in_navigation_mode)
58+
def _(event):
59+
"""
60+
Suspend process to background.
61+
"""
62+
event.app.suspend_to_background()
63+
3964
@kb.add('c-t')
4065
def _(event):
4166
"""
@@ -50,7 +75,7 @@ def indent_line(event):
5075
"""
5176
Indent current line.
5277
"""
53-
b = event.application.current_buffer
78+
b = event.app.current_buffer
5479

5580
# Move to start of line.
5681
pos = b.document.get_start_of_line_position(after_whitespace=True)

pyvim/window_arrangement.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class HSplit(list):
2020

2121

2222
class VSplit(list):
23-
""" Horizontal split. """
23+
""" Vertical split. """
2424

2525

2626
class Window(object):
@@ -101,6 +101,10 @@ def _get_split_parent(self, split):
101101
if child == split:
102102
return parent
103103

104+
def get_windows_for_buffer(self, editor_buffer):
105+
""" Return a list of all windows in this tab page. """
106+
return (window for _, window in self._walk_through_windows() if window.editor_buffer == editor_buffer)
107+
104108
def _split(self, split_cls, editor_buffer=None):
105109
"""
106110
Split horizontal or vertical.
@@ -258,11 +262,18 @@ def get_editor_buffer_for_buffer_name(self, buffer_name):
258262
if eb.buffer_name == buffer_name:
259263
return eb
260264

265+
def get_windows_for_buffer(self, editor_buffer):
266+
""" Return a list of all windows in this tab page. """
267+
return (b for t in self.tab_pages for b in t.get_windows_for_buffer(editor_buffer))
268+
261269
def close_window(self):
262270
"""
263271
Close active window of active tab.
264272
"""
265-
self.active_tab.close_active_window()
273+
if self.active_tab.window_count() > 1:
274+
self.active_tab.close_active_window()
275+
else:
276+
self.close_tab()
266277

267278
# Clean up buffers.
268279
self._auto_close_new_empty_buffers()

tests/conftest.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,19 @@ def window(editor_buffer):
2424
@pytest.fixture
2525
def tab_page(window):
2626
return TabPage(window)
27+
28+
29+
@pytest.fixture
30+
def tab_page_with_splits(editor_buffer, window):
31+
editor_buffer2 = EditorBuffer(editor)
32+
33+
tab_page = TabPage(Window(editor_buffer))
34+
tab_page.vsplit(editor_buffer)
35+
tab_page.vsplit(editor_buffer2)
36+
tab_page.hsplit(editor_buffer)
37+
return tab_page
38+
39+
40+
@pytest.fixture
41+
def window_arrangement(editor):
42+
return WindowArrangement(editor)

tests/test_window_arrangements.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,39 @@ def test_vsplit(editor, tab_page):
1515

1616
assert isinstance(tab_page.root, VSplit)
1717
assert len(tab_page.root) == 2
18+
19+
20+
def test_tab_page_get_windows_for_buffer(editor, editor_buffer, tab_page_with_splits):
21+
tab_page1 = tab_page_with_splits
22+
23+
windows = list(tab_page1.get_windows_for_buffer(editor_buffer))
24+
assert all(w.editor_buffer == editor_buffer for w in windows)
25+
assert len(windows) == 3
26+
27+
28+
def test_window_arrangement_get_windows_for_buffer(editor, editor_buffer, tab_page_with_splits, window_arrangement):
29+
tab_page1 = tab_page_with_splits
30+
tab_page2 = TabPage(Window(editor_buffer))
31+
32+
window_arrangement.tab_pages[:] = [tab_page1, tab_page2]
33+
windows = list(window_arrangement.get_windows_for_buffer(editor_buffer))
34+
assert all(w.editor_buffer == editor_buffer for w in windows)
35+
assert len(windows) == 4
36+
37+
38+
def test_close_window_closes_split(editor):
39+
editor.window_arrangement.create_tab()
40+
editor.window_arrangement.hsplit()
41+
assert len(editor.window_arrangement.tab_pages) == 2
42+
43+
assert editor.window_arrangement.active_tab.window_count() == 2
44+
editor.window_arrangement.close_window()
45+
assert editor.window_arrangement.active_tab.window_count() == 1
46+
47+
48+
def test_close_window_also_closes_empty_tab(editor):
49+
editor.window_arrangement.create_tab()
50+
51+
assert len(editor.window_arrangement.tab_pages) == 2
52+
editor.window_arrangement.close_window()
53+
assert len(editor.window_arrangement.tab_pages) == 1

0 commit comments

Comments
 (0)