Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of edit mask made by coordinated input text areas #1677

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions examples/prompts/edit-mask.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#!/usr/bin/env python
from typing import Any

from prompt_toolkit.application import Application
from prompt_toolkit.application.current import get_app
from prompt_toolkit.completion import FuzzyWordCompleter
from prompt_toolkit.filters import Condition
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.layout.containers import Float, FloatContainer, HSplit, Window
from prompt_toolkit.layout.controls import FormattedTextControl
from prompt_toolkit.layout.dimension import D
from prompt_toolkit.layout.layout import Layout
from prompt_toolkit.layout.menus import CompletionsMenu, CompletionsMenuControl
from prompt_toolkit.widgets import TextArea


class EditMask:
def __init__(self, animals: Any, colors: Any, cities: Any, names: Any) -> None:
self.animal_completer = FuzzyWordCompleter(animals)
self.color_completer = FuzzyWordCompleter(colors)
self.city_completer = FuzzyWordCompleter(cities)
self.name_completer = FuzzyWordCompleter(names)

self.finish_event = ""

kb = KeyBindings()

@Condition
def is_not_autocompleting() -> bool:
"Check if the completion menu is visible"
for vw in get_app().layout.visible_windows:
if type(vw.content) is CompletionsMenuControl:
return False
return True

@kb.add("down", filter=is_not_autocompleting)
def _(event) -> None:
"Move to next item."
get_app().layout.focus_next()

@kb.add("up", filter=is_not_autocompleting)
def _(event) -> None:
"Move to previous item."
get_app().layout.focus_previous()

@kb.add("c-c")
def _(event) -> None:
"Quit application without saving."
self.finish_event = "quit"
event.app.exit()

@kb.add("c-s")
def _(event) -> None:
"Save and quit application."
self.finish_event = "save"
event.app.exit()

self.text_area = {
"Animal": self.factory_area(
"Animal", prefix_min_width=15, completer=self.animal_completer
),
"Color": self.factory_area(
"Color", prefix_min_width=15, completer=self.color_completer
),
"City": self.factory_area(
"City", prefix_min_width=15, completer=self.city_completer
),
"Name": self.factory_area(
"Name", prefix_min_width=15, completer=self.name_completer
),
"Other info 1": self.factory_area("Other info 1", prefix_min_width=15),
"Other info 2": self.factory_area("Other info 2", prefix_min_width=15),
}

self.completion_menu = CompletionsMenu(max_height=16, scroll_offset=1)

self.float_area = Float(
xcursor=True,
ycursor=True,
content=self.completion_menu,
)

self.body = FloatContainer(
content=HSplit(
[
Window(
FormattedTextControl(
"Ctrl-S - Save and quit | Ctrl-C - Quit without save"
),
height=1,
style="reverse",
),
self.text_area["Animal"],
self.text_area["Color"],
self.text_area["City"],
self.text_area["Name"],
self.text_area["Other info 1"],
self.text_area["Other info 2"],
]
),
floats=[
self.float_area,
],
)

# self.application = Application(
# layout=Layout(self.body),
# key_bindings=kb,
# full_screen=True
# )
self.application = Application(layout=Layout(self.body), key_bindings=kb)

def accept_text(self, buf):
get_app().layout.focus_next()
buf.complete_state = None
return True

def factory_area(
self, prefix: str, prefix_min_width: int = 0, completer: Any = None
) -> TextArea:
"""Generate a text area component."""
ta = TextArea(
multiline=False,
completer=completer,
width=D(preferred=40),
accept_handler=self.accept_text,
get_line_prefix=lambda lineno, wrap_count: prefix
+ (" " * (prefix_min_width - len(prefix) - 2))
+ ": ",
)
ta.control.buffer.name = prefix
return ta

def run(self) -> None:
self.application.run()
if self.finish_event == "quit":
print("Quitting without saving")
elif self.finish_event == "save":
for key, item in self.text_area.items():
print(key, ":", item.text)


def main() -> None:
animals = ["alligator", "crocodile", "bird", "cat", "dog"]
colors = ["red", "yellow", "green", "blue", "pink"]
cities = ["Rome", "Paris", "Madrid", "Athene", "Lisbon"]
names = ["Tullio", "Frank", "Jodi", "Mark"]
editor = EditMask(animals=animals, colors=colors, cities=cities, names=names)
editor.run()


if __name__ == "__main__":
main()