pw_console: Enable floating vertical completion menu
Use a CompletionsMenu defined in the top Float container. This lets the
menu overlay other UI panes and exist outside the python input window.
- Turn on function signature display by default.
- Clear displayed function signatures on Ctrl-C
- Disable ptpython's CompletionMenus. They can still be re-enabled
in the F2 settings menu. If turned back on our CompletionMenu is
hidden.
Bug: 418
No-Docs-Update-Reason: No new functionality, readability improvement.
Change-Id: Ieff37dc6547fc9b5f6a20f048514d8e0ccad47fb
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/50863
Reviewed-by: Keir Mierle <keir@google.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Anthony DiGirolamo <tonymd@google.com>
diff --git a/pw_console/py/pw_console/console_app.py b/pw_console/py/pw_console/console_app.py
index e6c8c0e..efa586c 100644
--- a/pw_console/py/pw_console/console_app.py
+++ b/pw_console/py/pw_console/console_app.py
@@ -20,6 +20,7 @@
from threading import Thread
from typing import Iterable, Optional
+from prompt_toolkit.layout.menus import CompletionsMenu
from prompt_toolkit.application import Application
from prompt_toolkit.filters import Condition
from prompt_toolkit.styles import (
@@ -39,6 +40,7 @@
MenuItem,
)
from prompt_toolkit.key_binding import KeyBindings, merge_key_bindings
+from ptpython.layout import CompletionVisualisation # type: ignore
from ptpython.key_bindings import ( # type: ignore
load_python_bindings, load_sidebar_bindings,
)
@@ -242,9 +244,40 @@
# Callable to get width
width=self.help_window.content_width,
),
+ # Completion menu that can overlap other panes since it lives in
+ # the top level Float container.
+ Float(
+ xcursor=True,
+ ycursor=True,
+ content=ConditionalContainer(
+ content=CompletionsMenu(
+ scroll_offset=(lambda: self.pw_ptpython_repl.
+ completion_menu_scroll_offset),
+ max_height=16,
+ ),
+ # Only show our completion if ptpython's is disabled.
+ filter=Condition(lambda: self.pw_ptpython_repl.
+ completion_visualisation ==
+ CompletionVisualisation.NONE),
+ ),
+ ),
],
)
+ # NOTE: ptpython stores it's completion menus in this HSplit:
+ #
+ # self.pw_ptpython_repl.__pt_container__()
+ # .children[0].children[0].children[0].floats[0].content.children
+ #
+ # Index 1 is a CompletionsMenu and is shown when:
+ # self.pw_ptpython_repl
+ # .completion_visualisation == CompletionVisualisation.POP_UP
+ #
+ # Index 2 is a MultiColumnCompletionsMenu and is shown when:
+ # self.pw_ptpython_repl
+ # .completion_visualisation == CompletionVisualisation.MULTI_COLUMN
+ #
+
# Setup the prompt_toolkit layout with the repl pane as the initially
# focused element.
self.layout: Layout = Layout(
diff --git a/pw_console/py/pw_console/pw_ptpython_repl.py b/pw_console/py/pw_console/pw_ptpython_repl.py
index d1e012c..c1f6c2b 100644
--- a/pw_console/py/pw_console/pw_ptpython_repl.py
+++ b/pw_console/py/pw_console/pw_ptpython_repl.py
@@ -22,6 +22,7 @@
from prompt_toolkit.buffer import Buffer
import ptpython.repl # type: ignore
+from ptpython.layout import CompletionVisualisation # type: ignore
from ptpython.completer import CompletePrivateAttributes # type: ignore
import pw_console.helpers
@@ -49,6 +50,18 @@
self.complete_private_attributes = (
CompletePrivateAttributes.IF_NO_PUBLIC)
+ # Function signature that shows args, kwargs, and types under the cursor
+ # of the input window.
+ self.show_signature: bool = True
+ # Docstring of the current completed function that appears at the bottom
+ # of the input window.
+ self.show_docstring: bool = False
+
+ # Turn off the completion menu in ptpython. The CompletionsMenu in
+ # ConsoleApp.root_container will handle this.
+ self.completion_visualisation: CompletionVisualisation = (
+ CompletionVisualisation.NONE)
+
# Additional state variables.
self.repl_pane = None
self._last_result = None
diff --git a/pw_console/py/pw_console/repl_pane.py b/pw_console/py/pw_console/repl_pane.py
index 811d4bc..66d1aef 100644
--- a/pw_console/py/pw_console/repl_pane.py
+++ b/pw_console/py/pw_console/repl_pane.py
@@ -333,7 +333,10 @@
self.interrupt_last_code_execution()
def clear_input_buffer(self):
+ # Erase input buffer.
self.pw_ptpython_repl.default_buffer.reset()
+ # Clear any displayed function signatures.
+ self.pw_ptpython_repl.on_reset()
def interrupt_last_code_execution(self):
code = self._get_currently_running_code()