|
83 | 83 | from prompt_toolkit.key_binding.key_processor import KeyPressEvent
|
84 | 84 | from prompt_toolkit.keys import Keys
|
85 | 85 | from prompt_toolkit.layout import Float, FloatContainer, HSplit, Window
|
86 |
| -from prompt_toolkit.layout.containers import ConditionalContainer, WindowAlign |
| 86 | +from prompt_toolkit.layout.containers import ( |
| 87 | + AnyContainer, |
| 88 | + ConditionalContainer, |
| 89 | + WindowAlign, |
| 90 | +) |
87 | 91 | from prompt_toolkit.layout.controls import (
|
88 | 92 | BufferControl,
|
89 | 93 | FormattedTextControl,
|
|
124 | 128 | to_str,
|
125 | 129 | )
|
126 | 130 | from prompt_toolkit.validation import DynamicValidator, Validator
|
| 131 | +from prompt_toolkit.widgets import Frame |
127 | 132 | from prompt_toolkit.widgets.toolbars import (
|
128 | 133 | SearchToolbar,
|
129 | 134 | SystemToolbar,
|
@@ -368,6 +373,7 @@ class PromptSession(Generic[_T]):
|
368 | 373 | "reserve_space_for_menu",
|
369 | 374 | "tempfile_suffix",
|
370 | 375 | "tempfile",
|
| 376 | + "show_frame", |
371 | 377 | )
|
372 | 378 |
|
373 | 379 | def __init__(
|
@@ -412,6 +418,7 @@ def __init__(
|
412 | 418 | tempfile_suffix: str | Callable[[], str] | None = ".txt",
|
413 | 419 | tempfile: str | Callable[[], str] | None = None,
|
414 | 420 | refresh_interval: float = 0,
|
| 421 | + show_frame: FilterOrBool = False, |
415 | 422 | input: Input | None = None,
|
416 | 423 | output: Output | None = None,
|
417 | 424 | interrupt_exception: type[BaseException] = KeyboardInterrupt,
|
@@ -465,6 +472,7 @@ def __init__(
|
465 | 472 | self.reserve_space_for_menu = reserve_space_for_menu
|
466 | 473 | self.tempfile_suffix = tempfile_suffix
|
467 | 474 | self.tempfile = tempfile
|
| 475 | + self.show_frame = show_frame |
468 | 476 | self.interrupt_exception = interrupt_exception
|
469 | 477 | self.eof_exception = eof_exception
|
470 | 478 |
|
@@ -632,69 +640,77 @@ def multi_column_complete_style() -> bool:
|
632 | 640 | return self.complete_style == CompleteStyle.MULTI_COLUMN
|
633 | 641 |
|
634 | 642 | # Build the layout.
|
635 |
| - layout = HSplit( |
636 |
| - [ |
637 |
| - # The main input, with completion menus floating on top of it. |
638 |
| - FloatContainer( |
639 |
| - HSplit( |
640 |
| - [ |
641 |
| - ConditionalContainer( |
642 |
| - Window( |
643 |
| - FormattedTextControl(get_prompt_text_1), |
644 |
| - dont_extend_height=True, |
645 |
| - ), |
646 |
| - Condition(has_before_fragments), |
647 |
| - ), |
648 |
| - ConditionalContainer( |
649 |
| - default_buffer_window, |
650 |
| - Condition( |
651 |
| - lambda: get_app().layout.current_control |
652 |
| - != search_buffer_control |
653 |
| - ), |
654 |
| - ), |
655 |
| - ConditionalContainer( |
656 |
| - Window(search_buffer_control), |
657 |
| - Condition( |
658 |
| - lambda: get_app().layout.current_control |
659 |
| - == search_buffer_control |
660 |
| - ), |
661 |
| - ), |
662 |
| - ] |
| 643 | + |
| 644 | + # The main input, with completion menus floating on top of it. |
| 645 | + main_input_container = FloatContainer( |
| 646 | + HSplit( |
| 647 | + [ |
| 648 | + ConditionalContainer( |
| 649 | + Window( |
| 650 | + FormattedTextControl(get_prompt_text_1), |
| 651 | + dont_extend_height=True, |
| 652 | + ), |
| 653 | + Condition(has_before_fragments), |
663 | 654 | ),
|
664 |
| - [ |
665 |
| - # Completion menus. |
666 |
| - # NOTE: Especially the multi-column menu needs to be |
667 |
| - # transparent, because the shape is not always |
668 |
| - # rectangular due to the meta-text below the menu. |
669 |
| - Float( |
670 |
| - xcursor=True, |
671 |
| - ycursor=True, |
672 |
| - transparent=True, |
673 |
| - content=CompletionsMenu( |
674 |
| - max_height=16, |
675 |
| - scroll_offset=1, |
676 |
| - extra_filter=has_focus(default_buffer) |
677 |
| - & ~multi_column_complete_style, |
678 |
| - ), |
| 655 | + ConditionalContainer( |
| 656 | + default_buffer_window, |
| 657 | + Condition( |
| 658 | + lambda: get_app().layout.current_control |
| 659 | + != search_buffer_control |
679 | 660 | ),
|
680 |
| - Float( |
681 |
| - xcursor=True, |
682 |
| - ycursor=True, |
683 |
| - transparent=True, |
684 |
| - content=MultiColumnCompletionsMenu( |
685 |
| - show_meta=True, |
686 |
| - extra_filter=has_focus(default_buffer) |
687 |
| - & multi_column_complete_style, |
688 |
| - ), |
689 |
| - ), |
690 |
| - # The right prompt. |
691 |
| - Float( |
692 |
| - right=0, |
693 |
| - top=0, |
694 |
| - hide_when_covering_content=True, |
695 |
| - content=_RPrompt(lambda: self.rprompt), |
| 661 | + ), |
| 662 | + ConditionalContainer( |
| 663 | + Window(search_buffer_control), |
| 664 | + Condition( |
| 665 | + lambda: get_app().layout.current_control |
| 666 | + == search_buffer_control |
696 | 667 | ),
|
697 |
| - ], |
| 668 | + ), |
| 669 | + ] |
| 670 | + ), |
| 671 | + [ |
| 672 | + # Completion menus. |
| 673 | + # NOTE: Especially the multi-column menu needs to be |
| 674 | + # transparent, because the shape is not always |
| 675 | + # rectangular due to the meta-text below the menu. |
| 676 | + Float( |
| 677 | + xcursor=True, |
| 678 | + ycursor=True, |
| 679 | + transparent=True, |
| 680 | + content=CompletionsMenu( |
| 681 | + max_height=16, |
| 682 | + scroll_offset=1, |
| 683 | + extra_filter=has_focus(default_buffer) |
| 684 | + & ~multi_column_complete_style, |
| 685 | + ), |
| 686 | + ), |
| 687 | + Float( |
| 688 | + xcursor=True, |
| 689 | + ycursor=True, |
| 690 | + transparent=True, |
| 691 | + content=MultiColumnCompletionsMenu( |
| 692 | + show_meta=True, |
| 693 | + extra_filter=has_focus(default_buffer) |
| 694 | + & multi_column_complete_style, |
| 695 | + ), |
| 696 | + ), |
| 697 | + # The right prompt. |
| 698 | + Float( |
| 699 | + right=0, |
| 700 | + top=0, |
| 701 | + hide_when_covering_content=True, |
| 702 | + content=_RPrompt(lambda: self.rprompt), |
| 703 | + ), |
| 704 | + ], |
| 705 | + ) |
| 706 | + |
| 707 | + layout = HSplit( |
| 708 | + [ |
| 709 | + # Wrap the main input in a frame, if requested. |
| 710 | + ConditionalContainer( |
| 711 | + Frame(main_input_container), |
| 712 | + filter=dyncond("show_frame"), |
| 713 | + alternative_content=main_input_container, |
698 | 714 | ),
|
699 | 715 | ConditionalContainer(ValidationToolbar(), filter=~is_done),
|
700 | 716 | ConditionalContainer(
|
@@ -897,6 +913,7 @@ def prompt(
|
897 | 913 | enable_open_in_editor: FilterOrBool | None = None,
|
898 | 914 | tempfile_suffix: str | Callable[[], str] | None = None,
|
899 | 915 | tempfile: str | Callable[[], str] | None = None,
|
| 916 | + show_frame: FilterOrBool | None = None, |
900 | 917 | # Following arguments are specific to the current `prompt()` call.
|
901 | 918 | default: str | Document = "",
|
902 | 919 | accept_default: bool = False,
|
@@ -1021,6 +1038,8 @@ class itself. For these, passing in ``None`` will keep the current
|
1021 | 1038 | self.tempfile_suffix = tempfile_suffix
|
1022 | 1039 | if tempfile is not None:
|
1023 | 1040 | self.tempfile = tempfile
|
| 1041 | + if show_frame is not None: |
| 1042 | + self.show_frame = show_frame |
1024 | 1043 |
|
1025 | 1044 | self._add_pre_run_callables(pre_run, accept_default)
|
1026 | 1045 | self.default_buffer.reset(
|
@@ -1407,6 +1426,7 @@ def prompt(
|
1407 | 1426 | enable_open_in_editor: FilterOrBool | None = None,
|
1408 | 1427 | tempfile_suffix: str | Callable[[], str] | None = None,
|
1409 | 1428 | tempfile: str | Callable[[], str] | None = None,
|
| 1429 | + show_frame: FilterOrBool | None = None, |
1410 | 1430 | # Following arguments are specific to the current `prompt()` call.
|
1411 | 1431 | default: str = "",
|
1412 | 1432 | accept_default: bool = False,
|
@@ -1462,6 +1482,7 @@ def prompt(
|
1462 | 1482 | enable_open_in_editor=enable_open_in_editor,
|
1463 | 1483 | tempfile_suffix=tempfile_suffix,
|
1464 | 1484 | tempfile=tempfile,
|
| 1485 | + show_frame=show_frame, |
1465 | 1486 | default=default,
|
1466 | 1487 | accept_default=accept_default,
|
1467 | 1488 | pre_run=pre_run,
|
|
0 commit comments