| Server IP : 3.96.16.70 / Your IP : 216.73.216.15 Web Server : Apache System : Linux ip-172-31-26-103.ca-central-1.compute.internal 6.1.163-186.299.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Tue Feb 24 16:35:42 UTC 2026 x86_64 User : ec2-user ( 1000) PHP Version : 8.4.18 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /proc/thread-self/root/lib/python3.9/site-packages/awscli/autoprompt/ |
Upload File : |
# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# http://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import os
from functools import partial
from prompt_toolkit.application import get_app
from prompt_toolkit.buffer import Buffer
from prompt_toolkit.document import Document
from prompt_toolkit.filters import has_focus
from prompt_toolkit.formatted_text import HTML, to_formatted_text
from prompt_toolkit.formatted_text.utils import fragment_list_to_text
from prompt_toolkit.key_binding import KeyBindings
from prompt_toolkit.keys import Keys
from prompt_toolkit.layout import (
ConditionalContainer,
Float,
FloatContainer,
HSplit,
VSplit,
Window,
)
from prompt_toolkit.layout.controls import BufferControl
from prompt_toolkit.layout.dimension import Dimension
from prompt_toolkit.layout.processors import Processor, Transformation
from prompt_toolkit.widgets import (
Button,
Dialog,
Frame,
HorizontalLine,
Label,
TextArea,
)
from prompt_toolkit.widgets.base import Border
from awscli.autoprompt.filters import (
doc_window_has_focus,
help_section_visible,
input_buffer_has_focus,
is_debug_mode,
is_history_mode,
search_input_has_focus,
)
class FormatTextProcessor(Processor):
"""This Processor is used to transform formatted text into a useable
format inside a ``prompt_toolkit.buffer.Buffer``.
"""
def apply_transformation(self, text_input):
# https://python-prompt-toolkit.readthedocs.io/en/master/pages/reference.html#module-prompt_toolkit.formatted_text
fragments = to_formatted_text(
HTML(fragment_list_to_text(text_input.fragments))
)
return Transformation(fragments)
class TitleLine:
def __init__(self, title):
fill = partial(Window, style='class:frame.border')
self.container = VSplit(
[
fill(char=Border.HORIZONTAL),
fill(width=1, height=1, char='|'),
Label(
title, style='class:frame.label', dont_extend_width=True
),
fill(width=1, height=1, char='|'),
fill(char=Border.HORIZONTAL),
],
height=1,
)
def __pt_container__(self):
return self.container
class BaseHelpContainer(ConditionalContainer):
STYLE = '<style fg="darkturquoise">'
NAME = None
CONDITION = None
DIMENSIONS = {}
FOCUSABLE = False
def __init__(self):
window = self.create_window(self.create_buffer())
super().__init__(window, self.CONDITION)
@property
def help_text(self):
pass
def create_buffer(self):
document = Document(text=self.help_text, cursor_position=0)
help_buffer = Buffer(name=self.NAME, read_only=True)
help_buffer.set_document(document, bypass_readonly=True)
return help_buffer
def create_window(self, help_buffer):
return Window(
content=BufferControl(
buffer=help_buffer,
input_processors=[FormatTextProcessor()],
focusable=self.FOCUSABLE,
),
wrap_lines=True,
**self.DIMENSIONS,
)
class BaseHelpView(BaseHelpContainer):
TITLE = None
DIMENSIONS = {'width': Dimension(max=35, preferred=25)}
def create_window(self, help_buffer):
return Frame(
super(BaseHelpView, self).create_window(help_buffer),
title=self.TITLE,
)
class InputHelpView(BaseHelpView):
TITLE = 'Prompt panel help'
NAME = 'help_input'
CONDITION = has_focus('input_buffer')
@property
def help_text(self):
return (
f'{self.STYLE}[ENTER]</style> Autocomplete Choice/Execute Command\n'
f'{self.STYLE}[F1]</style> Hide Shortkey Help\n'
f'{self.STYLE}[F2]</style> Focus on next panel\n'
f'{self.STYLE}[F3]</style> Hide/Show Docs\n'
f'{self.STYLE}[F4]</style> One/Multi column prompt\n'
f'{self.STYLE}[F5]</style> Hide/Show Output\n'
f'{self.STYLE}[CONTROL+R]</style> On/Off bck-i-search'
)
class OutputHelpView(BaseHelpView):
TITLE = 'Output panel help'
NAME = 'output_input'
CONDITION = has_focus('output_buffer')
@property
def help_text(self):
return (
f'{self.STYLE}[/]</style> Search Forward\n'
f'{self.STYLE}[?]</style> Search Backward\n'
f'{self.STYLE}[n]</style> Find Next Match\n'
f'{self.STYLE}[N]</style> Find Previous Match\n'
f'{self.STYLE}[F1]</style> Hide Shortkey Help\n'
f'{self.STYLE}[F2]</style> Focus on next panel\n'
f'{self.STYLE}[F3]</style> Hide/Show Docs\n'
f'{self.STYLE}[F5]</style> Hide/Show Output\n'
)
class DocHelpView(BaseHelpView):
TITLE = 'Doc panel help'
NAME = 'help_doc'
CONDITION = doc_window_has_focus | search_input_has_focus
@property
def help_text(self):
return (
f'{self.STYLE}[/]</style> Search Forward\n'
f'{self.STYLE}[?]</style> Search Backward\n'
f'{self.STYLE}[n]</style> Find Next Match\n'
f'{self.STYLE}[N]</style> Find Previous Match\n'
f'{self.STYLE}[w]</style> Go Up a Page\n'
f'{self.STYLE}[z]</style> Go Down a Page\n'
f'{self.STYLE}[j]</style> Go Up a Line\n'
f'{self.STYLE}[k]</style> Go Down a Line\n'
f'{self.STYLE}[g]</style> Go to Top\n'
f'{self.STYLE}[G]</style> Go to Bottom\n'
f'{self.STYLE}[F1]</style> Hide Shortkey Help\n'
f'{self.STYLE}[F2]</style> Focus on next panel\n'
f'{self.STYLE}[q]</style> Focus on Input\n'
f'{self.STYLE}[F5]</style> Hide/Show Output'
)
class BaseToolbarView(BaseHelpContainer):
DIMENSIONS = {'height': Dimension(max=2)}
SPACING = ' '
class DocToolbarView(BaseToolbarView):
NAME = 'toolbar_doc'
CONDITION = doc_window_has_focus | search_input_has_focus
@property
def help_text(self):
return (
f'{self.STYLE}[F1]</style> Show Shortkey Help{self.SPACING}'
f'{self.STYLE}[F2]</style> Focus on next panel{self.SPACING}'
f'{self.STYLE}[[q]</style> Focus on Input'
)
class InputToolbarView(BaseToolbarView):
NAME = 'toolbar_input'
CONDITION = has_focus('input_buffer')
@property
def help_text(self):
return (
f'{self.STYLE}[ENTER]</style> Autocomplete '
f'Choice/Execute Command{self.SPACING}'
f'{self.STYLE}[F1]</style> Show Shortkey Help{self.SPACING}'
f'{self.STYLE}[F2]</style> Focus on next panel{self.SPACING}'
f'{self.STYLE}[F3]</style> Hide/Show Docs{self.SPACING}'
f'{self.STYLE}[F5]</style> Hide/Show Output'
)
class OutputToolbarView(BaseToolbarView):
NAME = 'output_input'
CONDITION = has_focus('output_buffer')
@property
def help_text(self):
return (
f'{self.STYLE}[F1]</style> Show Shortkey Help{self.SPACING}'
f'{self.STYLE}[F2]</style> Focus on next panel{self.SPACING}'
f'{self.STYLE}[F3]</style> Hide/Show Docs{self.SPACING}'
f'{self.STYLE}[F5]</style> Hide/Show Output'
)
class DebugToolbarView(BaseToolbarView):
NAME = 'toolbar_input'
CONDITION = is_debug_mode
@property
def help_text(self):
return f'{self.STYLE}[CONTROL+S]</style> Save log to file'
class HistorySignToolbarView(BaseToolbarView):
NAME = 'history_sign'
STYLE = '<style fg="ansired" bg="#00ff44">'
CONDITION = is_history_mode
DIMENSIONS = {
'height': Dimension(max=2),
'width': Dimension(max=13),
}
@property
def help_text(self):
return f'{self.STYLE}bck-i-search</style>{self.SPACING}'
class ToolbarWidget:
def __init__(self):
self.container = HSplit(
[
ConditionalContainer(HorizontalLine(), ~help_section_visible),
VSplit(
[
HistorySignToolbarView(),
ConditionalContainer(
VSplit(
[
InputToolbarView(),
DocToolbarView(),
OutputToolbarView(),
]
),
~help_section_visible,
),
]
),
]
)
def __pt_container__(self):
return self.container
class HelpPanelWidget:
def __init__(self):
self.container = ConditionalContainer(
HSplit([DocHelpView(), InputHelpView(), OutputHelpView()]),
help_section_visible,
)
def __pt_container__(self):
return self.container
class DebugPanelWidget:
DIMENSIONS = {
'width': Dimension(max=40, preferred=20),
}
def __init__(self):
self._dialog_prev_focus = None
self.dialog = self.create_save_file_dialog()
_kb = KeyBindings()
_kb.add(Keys.ControlS, filter=is_debug_mode, is_global=True)(
self._activate_dialog
)
self.float_container = FloatContainer(
Window(
content=BufferControl(
buffer=Buffer(name='debug_buffer', read_only=True)
),
wrap_lines=True,
),
key_bindings=_kb,
floats=[],
)
self.container = ConditionalContainer(
Frame(
HSplit(
[
self.float_container,
HorizontalLine(),
DebugToolbarView(),
]
),
**self.DIMENSIONS,
title='Debug panel',
),
filter=is_debug_mode,
)
def _activate_dialog(self, event):
layout = event.app.layout
self._dialog_prev_focus = event.app.current_buffer
self.float_container.floats.append(Float(content=self.dialog))
layout.focus(self.dialog)
def create_save_file_dialog(self):
default_filename = 'prompt_debug.log'
def cancel_handler():
app = get_app()
textfield.text = default_filename
app.layout.focus(textfield)
self.float_container.floats.pop()
app.layout.focus(self._dialog_prev_focus)
def ok_handler(*args, **kwargs):
app = get_app()
buffer = app.layout.get_buffer_by_name('debug_buffer')
with open(os.path.expanduser(textfield.text), 'w') as f:
f.write(buffer.document.text)
textfield.text = default_filename
app.layout.focus(textfield)
self.float_container.floats.pop()
app.layout.focus(self._dialog_prev_focus)
ok_button = Button(text='Save', handler=ok_handler)
cancel_button = Button(text='Cancel', handler=cancel_handler)
textfield = TextArea(text=default_filename, multiline=False)
dialog = Dialog(
title='Save logs to file',
body=HSplit(
[
Label(text='Log file name', dont_extend_height=True),
textfield,
],
padding=Dimension(preferred=1, max=1),
),
buttons=[ok_button, cancel_button],
with_background=True,
)
# add keybinding to save file on press Enter in textfield
dialog.container.body.container.content.key_bindings.add(
Keys.Enter, filter=has_focus(textfield)
)(ok_handler)
return dialog
def __pt_container__(self):
return self.container