Skip to content

Commit 76f1a3e

Browse files
Improved mouse support.
1 parent 8b0dfad commit 76f1a3e

File tree

5 files changed

+109
-56
lines changed

5 files changed

+109
-56
lines changed

ptpython/history_browser.py

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
from pygments.lexers import RstLexer
3030
from pygments.token import Token
3131

32+
from .utils import if_mousedown
33+
3234
from ptpython.layout import get_inputmode_tokens
3335
from functools import partial
3436
import six
@@ -210,18 +212,26 @@ def _get_top_toolbar_tokens(cli):
210212

211213

212214
def _get_bottom_toolbar_tokens(cli, python_input):
215+
@if_mousedown
216+
def f1(cli, mouse_event):
217+
_toggle_help(cli)
218+
219+
@if_mousedown
220+
def tab(cli, mouse_event):
221+
_select_other_window(cli)
222+
213223
return [
214224
(Token.Toolbar.Status, ' ')
215225
] + get_inputmode_tokens(cli, python_input) + [
216226
(Token.Toolbar.Status, ' '),
217227
(Token.Toolbar.Status.Key, '[Space]'),
218228
(Token.Toolbar.Status, ' Toggle '),
219-
(Token.Toolbar.Status.Key, '[Tab]'),
220-
(Token.Toolbar.Status, ' Focus '),
229+
(Token.Toolbar.Status.Key, '[Tab]', tab),
230+
(Token.Toolbar.Status, ' Focus ', tab),
221231
(Token.Toolbar.Status.Key, '[Enter]'),
222232
(Token.Toolbar.Status, ' Accept '),
223-
(Token.Toolbar.Status.Key, '[F1]'),
224-
(Token.Toolbar.Status, ' Help '),
233+
(Token.Toolbar.Status.Key, '[F1]', f1),
234+
(Token.Toolbar.Status, ' Help ', f1),
225235
]
226236

227237

@@ -400,6 +410,23 @@ def update_default_buffer(self, cli):
400410
self.get_new_document(b.cursor_position), bypass_readonly=True)
401411

402412

413+
def _toggle_help(cli):
414+
" Display/hide help. "
415+
if cli.current_buffer_name == HELP_BUFFER:
416+
cli.pop_focus()
417+
else:
418+
cli.push_focus(HELP_BUFFER)
419+
420+
421+
def _select_other_window(cli):
422+
" Toggle focus between left/right window. "
423+
if cli.current_buffer_name == HISTORY_BUFFER:
424+
cli.focus(DEFAULT_BUFFER)
425+
426+
elif cli.current_buffer_name == DEFAULT_BUFFER:
427+
cli.focus(HISTORY_BUFFER)
428+
429+
403430
def create_key_bindings(python_input, history_mapping):
404431
"""
405432
Key bindings.
@@ -468,11 +495,7 @@ def _(event):
468495
@handle(Keys.ControlW, filter=main_buffer_focussed)
469496
def _(event):
470497
" Select other window. "
471-
if event.cli.current_buffer_name == HISTORY_BUFFER:
472-
event.cli.focus(DEFAULT_BUFFER)
473-
474-
elif event.cli.current_buffer_name == DEFAULT_BUFFER:
475-
event.cli.focus(HISTORY_BUFFER)
498+
_select_other_window(event.cli)
476499

477500
@handle(Keys.F4)
478501
def _(event):
@@ -482,10 +505,7 @@ def _(event):
482505
@handle(Keys.F1)
483506
def _(event):
484507
" Display/hide help. "
485-
if event.cli.current_buffer_name == HELP_BUFFER:
486-
event.cli.pop_focus()
487-
else:
488-
event.cli.push_focus(HELP_BUFFER)
508+
_toggle_help(event.cli)
489509

490510
@handle(Keys.ControlJ, filter=help_focussed)
491511
@handle(Keys.ControlC, filter=help_focussed)

ptpython/key_bindings.py

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
from prompt_toolkit.key_binding.vi_state import InputMode
88
from prompt_toolkit.keys import Keys
99

10-
from .history_browser import create_history_application
11-
1210
__all__ = (
1311
'load_python_bindings',
1412
'load_sidebar_bindings',
@@ -60,16 +58,7 @@ def _(event):
6058
"""
6159
Select from the history.
6260
"""
63-
python_input.key_bindings_manager.get_vi_state(event.cli).input_mode = InputMode.NAVIGATION
64-
65-
def done(result):
66-
if result is not None:
67-
event.cli.buffers[DEFAULT_BUFFER].document = result
68-
69-
python_input.key_bindings_manager.get_vi_state(event.cli).input_mode = InputMode.INSERT
70-
71-
event.cli.run_sub_application(create_history_application(
72-
python_input, event.cli.buffers[DEFAULT_BUFFER].document), done)
61+
python_input.enter_history(event.cli)
7362

7463
@handle(Keys.F4)
7564
def _(event):

ptpython/layout.py

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
from prompt_toolkit.layout.margins import Margin
1414
from prompt_toolkit.layout.menus import CompletionsMenu, MultiColumnCompletionsMenu
1515
from prompt_toolkit.layout.highlighters import SearchHighlighter, SelectionHighlighter, MatchingBracketHighlighter, ConditionalHighlighter
16-
from prompt_toolkit.layout.processors import HighlightMatchingBracketProcessor, ConditionalProcessor, AppendAutoSuggestion
16+
from prompt_toolkit.layout.processors import ConditionalProcessor, AppendAutoSuggestion
1717
from prompt_toolkit.layout.screen import Char
1818
from prompt_toolkit.layout.toolbars import CompletionsToolbar, ArgToolbar, SearchToolbar, ValidationToolbar, SystemToolbar, TokenListToolbar
1919
from prompt_toolkit.layout.utils import token_list_width
20-
from prompt_toolkit.mouse_events import MouseEventTypes
2120
from prompt_toolkit.reactive import Integer
2221
from prompt_toolkit.selection import SelectionType
2322
from prompt_toolkit.utils import get_cwidth
2423

25-
from ptpython.filters import HasSignature, ShowSidebar, ShowSignature, ShowDocstring
24+
from .filters import HasSignature, ShowSidebar, ShowSignature, ShowDocstring
25+
from .utils import if_mousedown
2626

2727
from pygments.lexers import PythonLexer
2828
from pygments.token import Token
@@ -71,18 +71,31 @@ def append_category(category):
7171
(T, '\n'),
7272
])
7373

74-
def append(selected, label, status):
74+
def append(index, label, status):
75+
selected = index == python_input.selected_option_index
76+
77+
@if_mousedown
78+
def select_item(cli, mouse_event):
79+
python_input.selected_option_index = index
80+
81+
@if_mousedown
82+
def goto_next(cli, mouse_event):
83+
" Select item and go to next value. "
84+
python_input.selected_option_index = index
85+
option = python_input.selected_option
86+
option.activate_next()
87+
7588
token = T.Selected if selected else T
7689

7790
tokens.append((T, ' >' if selected else ' '))
78-
tokens.append((token.Label, '%-24s' % label))
79-
tokens.append((token.Status, ' '))
80-
tokens.append((token.Status, '%s' % status))
91+
tokens.append((token.Label, '%-24s' % label, select_item))
92+
tokens.append((token.Status, ' ', select_item))
93+
tokens.append((token.Status, '%s' % status, goto_next))
8194

8295
if selected:
8396
tokens.append((Token.SetCursorPosition, ''))
8497

85-
tokens.append((token.Status, ' ' * (14 - len(status))))
98+
tokens.append((token.Status, ' ' * (14 - len(status)), goto_next))
8699
tokens.append((T, '<' if selected else ''))
87100
tokens.append((T, '\n'))
88101

@@ -91,8 +104,7 @@ def append(selected, label, status):
91104
append_category(category)
92105

93106
for option in category.options:
94-
append(i == python_input.selected_option_index,
95-
option.title, '%s' % option.get_current_value())
107+
append(i, option.title, '%s' % option.get_current_value())
96108
i += 1
97109

98110
tokens.pop() # Remove last newline.
@@ -282,11 +294,13 @@ def status_bar(key_bindings_manager, python_input):
282294
"""
283295
TB = Token.Toolbar.Status
284296

297+
@if_mousedown
285298
def toggle_paste_mode(cli, mouse_event):
286-
if mouse_event.event_type == MouseEventTypes.MOUSE_DOWN:
287-
python_input.paste_mode = not python_input.paste_mode
288-
else:
289-
return NotImplemented
299+
python_input.paste_mode = not python_input.paste_mode
300+
301+
@if_mousedown
302+
def enter_history(cli, mouse_event):
303+
python_input.enter_history(cli)
290304

291305
def get_tokens(cli):
292306
python_buffer = cli.buffers[DEFAULT_BUFFER]
@@ -310,8 +324,8 @@ def get_tokens(cli):
310324
append((TB, '[Ctrl-W] Cut [Meta-W] Copy [Ctrl-Y] Paste [Ctrl-G] Cancel'))
311325
else:
312326
result.extend([
313-
(TB.Key, '[F3]'),
314-
(TB, ' History '),
327+
(TB.Key, '[F3]', enter_history),
328+
(TB, ' History ', enter_history),
315329
(TB.Key, '[F6]', toggle_paste_mode),
316330
(TB, ' ', toggle_paste_mode),
317331
])
@@ -338,11 +352,9 @@ def get_inputmode_tokens(cli, python_input):
338352
339353
:param cli: `CommandLineInterface` instance.
340354
"""
355+
@if_mousedown
341356
def toggle_vi_mode(cli, mouse_event):
342-
if mouse_event.event_type == MouseEventTypes.MOUSE_DOWN:
343-
python_input.vi_mode = not python_input.vi_mode
344-
else:
345-
return NotImplemented
357+
python_input.vi_mode = not python_input.vi_mode
346358

347359
token = Token.Toolbar.Status
348360

@@ -381,12 +393,10 @@ def show_sidebar_button_info(python_input):
381393
Create `Layout` for the information in the right-bottom corner.
382394
(The right part of the status bar.)
383395
"""
396+
@if_mousedown
384397
def toggle_sidebar(cli, mouse_event):
385398
" Click handler for the menu. "
386-
if mouse_event.event_type == MouseEventTypes.MOUSE_DOWN:
387-
python_input.show_sidebar = not python_input.show_sidebar
388-
else:
389-
return NotImplemented
399+
python_input.show_sidebar = not python_input.show_sidebar
390400

391401
token = Token.Toolbar.Status
392402

ptpython/python_input.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,21 @@
1818
from prompt_toolkit.history import FileHistory, InMemoryHistory
1919
from prompt_toolkit.interface import CommandLineInterface, Application, AcceptAction
2020
from prompt_toolkit.key_binding.manager import KeyBindingManager
21+
from prompt_toolkit.key_binding.vi_state import InputMode
2122
from prompt_toolkit.layout.lexers import PygmentsLexer
2223
from prompt_toolkit.shortcuts import create_output
2324
from prompt_toolkit.styles import DynamicStyle
2425
from prompt_toolkit.utils import Callback, is_windows
2526
from prompt_toolkit.validation import ConditionalValidator
2627

27-
from ptpython.completer import PythonCompleter
28-
from ptpython.key_bindings import load_python_bindings, load_sidebar_bindings, load_confirm_exit_bindings
29-
from ptpython.layout import create_layout, CompletionVisualisation
30-
from ptpython.style import get_all_code_styles, get_all_ui_styles, generate_style
31-
from ptpython.utils import get_jedi_script_from_document, document_is_multiline_python
32-
from ptpython.validator import PythonValidator
33-
from ptpython.prompt_style import IPythonPrompt, ClassicPrompt
28+
from .completer import PythonCompleter
29+
from .history_browser import create_history_application
30+
from .key_bindings import load_python_bindings, load_sidebar_bindings, load_confirm_exit_bindings
31+
from .layout import create_layout, CompletionVisualisation
32+
from .prompt_style import IPythonPrompt, ClassicPrompt
33+
from .style import get_all_code_styles, get_all_ui_styles, generate_style
34+
from .utils import get_jedi_script_from_document, document_is_multiline_python
35+
from .validator import PythonValidator
3436

3537
from functools import partial
3638

@@ -616,6 +618,21 @@ def on_reset(self, cli):
616618
self.key_bindings_manager.reset()
617619
self.signatures = []
618620

621+
def enter_history(self, cli):
622+
"""
623+
Display the history.
624+
"""
625+
self.key_bindings_manager.get_vi_state(cli).input_mode = InputMode.NAVIGATION
626+
627+
def done(result):
628+
if result is not None:
629+
cli.buffers[DEFAULT_BUFFER].document = result
630+
631+
self.key_bindings_manager.get_vi_state(cli).input_mode = InputMode.INSERT
632+
633+
cli.run_sub_application(create_history_application(
634+
self, cli.buffers[DEFAULT_BUFFER].document), done)
635+
619636

620637
class PythonCommandLineInterface(CommandLineInterface):
621638
def __init__(self, eventloop=None, python_input=None, input=None, output=None):

ptpython/utils.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44
from __future__ import unicode_literals
55

6+
from prompt_toolkit.mouse_events import MouseEventTypes
67
import re
78

89
__all__ = (
@@ -108,3 +109,19 @@ def line_ends_with_colon():
108109
return True
109110

110111
return False
112+
113+
114+
def if_mousedown(handler):
115+
"""
116+
Decorator for mouse handlers.
117+
Only handle event when the user pressed mouse down.
118+
119+
(When applied to a token list. Scroll events will bubble up and are handled
120+
by the Window.)
121+
"""
122+
def handle_if_mouse_down(cli, mouse_event):
123+
if mouse_event.event_type == MouseEventTypes.MOUSE_DOWN:
124+
return handler(cli, mouse_event)
125+
else:
126+
return NotImplemented
127+
return handle_if_mouse_down

0 commit comments

Comments
 (0)