def print_container(container, file=None): """ Print any layout to the output in a non-interactive way. Example usage:: from prompt_toolkit.widgets import Frame, TextArea print_container( Frame(TextArea(text='Hello world!'))) """ if file: output = create_output(stdout=file) else: output = get_default_output() def exit_immediately(): # Use `call_from_executor` to exit "soon", so that we still render one # initial time, before exiting the application. get_event_loop().call_from_executor( lambda: app.exit()) app = Application( layout=Layout(container=container), output=output, input=DummyInput()) app.run(pre_run=exit_immediately)
def main(etmdir=""): global item, settings, ampm, style, etmstyle, application ampm = settings['ampm'] terminal_style = settings['style'] if terminal_style == "dark": style = dark_style etmstyle = dark_etmstyle else: style = light_style etmstyle = light_etmstyle agenda_view() application = Application( layout=Layout( root_container, focused_element=text_area, ), key_bindings=bindings, enable_page_navigation_bindings=True, mouse_support=True, style=style, full_screen=True) # Tell prompt_toolkit to use asyncio. use_asyncio_event_loop() # Run application async. loop = get_event_loop() loop.call_later(0, event_handler, loop) loop.run_until_complete( application.run_async().to_asyncio_future())
def build_application(container: Container, keys: KeyBindings) -> Application: return Application( layout=Layout(container), key_bindings=keys, full_screen=True, style=Style([ ("header", "bg:#005fff fg:black") ]) )
def __init__(self, vi_mode=False, style=None, search_text=None, titlebar_tokens=None): assert isinstance(vi_mode, bool) assert style is None or isinstance(style, Style) self.sources = [] self.current_source = 0 # Index in `self.sources`. self.vi_mode = vi_mode self.highlight_search = True self.in_colon_mode = False self.message = None self.displaying_help = False self.search_text = search_text self.display_titlebar = bool(titlebar_tokens) self.titlebar_tokens = titlebar_tokens or [] # When this is True, always make sure that the cursor goes to the # bottom of the visible content. This is similar to 'tail -f'. self.forward_forever = False # Status information for all sources. Source -> _SourceInfo. # (Remember this info as long as the Source object exists.) self.source_info = weakref.WeakKeyDictionary() # Create prompt_toolkit stuff. self.buffers = BufferMapping({}) def open_file(cli, buff): # Open file. self.open_file(buff.text) # Focus main buffer again. self.buffers.focus(cli, self.source_info[self.source].buffer_name) buff.reset() self.buffers['EXAMINE'] = Buffer( # Buffer for the 'Examine:' input. completer=PathCompleter(expanduser=True), accept_action=AcceptAction(open_file)) self.layout = Layout(self) registry = create_key_bindings(self) self.application = Application(layout=self.layout.container, buffers=self.buffers, key_bindings_registry=registry, style=style or create_style(), mouse_support=True, on_render=self._on_render, use_alternate_screen=True, on_initialize=self._on_cli_initialize) self.cli = None self.eventloop = None
async def shell(): global crow input_field = TextArea(height=1, prompt='> ', style='class:input-field', multiline=False, wrap_lines=False) captures = VSplit([capture1, capture2]) container = HSplit([ captures, output_field, Window(height=1, char='/', style='class:line', content=FormattedTextControl(text='druid////'), align=WindowAlign.RIGHT), input_field ]) def cwrite(xs): global crow try: crow.write(xs) except: crowreconnect() def accept(buff): try: myprint('\n> ' + input_field.text + '\n') druidparser(cwrite, input_field.text) except ValueError as err: print(err) get_app().exit() input_field.accept_handler = accept kb = KeyBindings() @kb.add('c-c', eager=True) @kb.add('c-q', eager=True) def _(event): event.app.exit() style = Style([ ('capture-field', '#747369'), ('output-field', '#d3d0c8'), ('input-field', '#f2f0ec'), ('line', '#747369'), ]) application = Application( layout=Layout(container, focused_element=input_field), key_bindings=kb, style=style, mouse_support=True, full_screen=True, ) result = await application.run_async()
def show_error_dialog(messages): texts = [] for message in messages: texts.append( Label(message, style='class:error', dont_extend_height=True)) dialog = Dialog(title='Some inputs are invalid', body=HSplit(texts, padding=1), buttons=[ Button(text='Ok', handler=lambda: get_app().exit()), ], with_background=True) app = Application(layout=Layout(dialog), key_bindings=load_key_bindings(), mouse_support=True, style=for_dialog(), full_screen=True) app.run()
def set_dummy_app(): """ Return a context manager that makes sure that this dummy application is active. This is important, because we need an `Application` with `is_done=False` flag, otherwise no keys will be processed. """ app = Application(layout=Layout(Window()), output=DummyOutput(), input=create_pipe_input()) return set_app(app)
def run(self): """Start the python_prompt application with ctui's default settings""" Path(self._project_folder).mkdir(parents=True, exist_ok=True) if Path(self._project_path).exists( ): # start with clean default project at each start Path.unlink(Path(self._project_path)) self._init_db() self.layout = CtuiLayout(self) self.style = CtuiStyle() self._mode = 'term_ui' # For future headless mode layout = Layout(self.layout.root_container, focused_element=self.layout.input_field) self.app = Application(layout=layout, key_bindings=get_key_bindings(self), style=self.style.dark_theme, enable_page_navigation_bindings=False, mouse_support=True, full_screen=True) self.app.run()
def mock_app(mocker): app = Application( input=create_pipe_input(), output=DummyOutput(), ) mocker.patch('upsies.uis.tui.tui.TUI._make_app', Mock(return_value=app)) mocker.patch('upsies.uis.tui.tui.TUI._jobs_container', Mock(children=[]), create=True) mocker.patch('upsies.uis.tui.tui.TUI._layout', Mock(), create=True)
def pager(self, html, end="\n"): """ Construct pager using prompt_toolkit """ my_buffer = Buffer() my_window = Window( BufferControl( buffer=my_buffer, focusable=True, preview_search=True, input_processors=[FormatText()], )) my_buffer.text = html my_buffer.read_only = to_filter(True) root_container = HSplit([ my_window, ]) bindings = KeyBindings() @bindings.add("c-c") @bindings.add("q") def _(event): "Quit." event.app.exit() application = Application( layout=Layout( root_container, focused_element=my_window, ), key_bindings=bindings, enable_page_navigation_bindings=True, mouse_support=True, full_screen=True, ) application.run() super().msg(html=html, end=end)
def __init__(self, configuration, exchange): self._project_name = configuration.project.name self._local_dir = configuration.local_dir self._remote_directory = None self._exchange = exchange self._loop = get_event_loop() self._current_screen = None self.root_container = HSplit([Window()]) self.layout = Layout(container=self.root_container) self._render() self.bindings = self._create_bindings() self.application = Application(layout=self.layout, key_bindings=self.bindings, full_screen=True) self._exchange.subscribe(Messages.REMOTE_DIRECTORY_SET, self._set_remote_dir)
def repl(parser, interpreter, style_name='default'): registry = load_key_bindings() @registry.add_binding(Keys.Escape, Keys.Enter) # meta-enter/alt-enter def _(event): '''Evaluate the buffer ''' code = buffers[DEFAULT_BUFFER].text try: ast = parser.parse(code) except (UnexpectedToken, UnexpectedInput) as e: toolbar_value = str(e) return try: start_eval_time = time.time() retval = interpreter.eval(ast) except Exception as e: toolbar_value = "Error: %s" % e.args return else: buffers['RESULT'].text = str(retval) toolbar_value = "Time: {:0.4f}, Value: {}".format( time.time() - start_eval_time, str(retval)) @registry.add_binding(Keys.ControlC, eager=True) @registry.add_binding(Keys.ControlQ, eager=True) def _(event): '''Exit the REPL ''' event.cli.set_return_value(None) buffers = { DEFAULT_BUFFER: Buffer(is_multiline=True), 'RESULT': Buffer(is_multiline=True), } style = style_from_pygments(get_style_by_name(style_name)) application = Application(layout=layout, buffers=buffers, mouse_support=True, style=style, use_alternate_screen=True, key_bindings_registry=registry) eventloop = create_eventloop() try: cli = CommandLineInterface(application=application, eventloop=eventloop) cli.run() finally: eventloop.close()
def run(): content = [] for line in iter(sys.stdin.readline, ""): content.append([line.strip(), False]) chk = CheckboxList(content) root_container = chk layout = Layout(root_container) kb = KeyBindings() @kb.add('q') def exit_(event): event.app.exit() app = Application(input=create_input(sys.stdout), key_bindings=kb, layout=layout, full_screen=True) app.run()
def prompt( title: str, options: Sequence[Tuple[RadioListType, AnyFormattedText]]) -> RadioListType: control = RadioList(options_to_html(options)) application: Application[None] = Application( layout=Layout(HSplit([Label(HTML(title)), control])), mouse_support=False, full_screen=False, ) return cast(RadioListType, application.run())
def __init__(self, input_handler: Callable, bindings: KeyBindings, completer: Completer): use_asyncio_event_loop() self.input_field = create_input_field(completer=completer) self.output_field = create_output_field() self.log_field = create_log_field() self.layout = generate_layout(self.input_field, self.output_field, self.log_field) self.bindings = bindings self.input_handler = input_handler self.input_field.accept_handler = self.accept self.app = Application(layout=self.layout, full_screen=True, key_bindings=self.bindings, style=load_style(), mouse_support=True, clipboard=PyperclipClipboard()) # settings self.prompt_text = ">>> " self.pending_input = None self.input_event = None self.hide_input = False
def test_keybindings(): from prompt_toolkit.application import Application from prompt_toolkit.layout import Layout from prompt_toolkit.layout.containers import FormattedTextControl, Window textarea = FormattedTextControl( text='Press "a b c" to quit.', show_cursor=False, ) kb = KeyBindings() @kb.add('a', 'b', 'c') def _(event): event.app.exit() @kb.add('<any>') def _(event): textarea.text += "\n{}".format(event.key_sequence) app = Application(layout=Layout(Window(textarea)), key_bindings=kb) app.run()
def __init__(self, use_theme): self.statusbar = Window(height=1, char='/', style='class:line', content=FormattedTextControl(text='druid////'), align=WindowAlign.RIGHT) self.content = HSplit([ Window(), self.statusbar, Window(height=1), ]) self.container = FloatContainer( content=self.content, floats=[ Float( xcursor=True, ycursor=True, content=CompletionsMenu(max_height=16, scroll_offset=1), ), ], ) self.key_bindings = KeyBindings() @self.key_bindings.add('c-c', eager=True) @self.key_bindings.add('c-q', eager=True) def quit_druid(event): event.app.exit() if use_theme: self.style = Style([ ('capture-field', '#747369'), ('output-field', '#d3d0c8'), ('input-field', '#f2f0ec'), ('line', '#747369'), ('scrollbar.background', 'bg:#000000'), ('scrollbar.button', 'bg:#747369'), ]) else: self.style = Style([]) self.layout = Layout(self.container) self.app = Application( layout=self.layout, key_bindings=self.key_bindings, style=self.style, mouse_support=True, full_screen=True, ) self.pages = dict() self.current_page = None
def _create_app(dialog: AnyContainer, style: Optional[BaseStyle]) -> Application[Any]: # Key bindings. bindings = KeyBindings() bindings.add("tab")(focus_next) bindings.add("s-tab")(focus_previous) return Application( layout=Layout(dialog), key_bindings=merge_key_bindings([load_key_bindings(), bindings]), mouse_support=True, style=style, full_screen=True, )
def select_prompt(message, options, mark='>'): control = SelectControl(options) def get_formatted_text(): return control.select_option_text(mark) layout = Layout( HSplit([ Window( height=Dimension.exact(1), content=FormattedTextControl(lambda: message + '\n', show_cursor=False), ), Window(height=Dimension.exact(len(control.options)), content=FormattedTextControl(get_formatted_text)), ConditionalContainer(Window(control), filter=~IsDone()) ])) app = Application(layout=layout, key_bindings=control.key_bindings, full_screen=False) return app.run()
def main(): def done(): application.exit() term = Terminal( width=D(preferred=60), height=D(preferred=25), done_callback=done) application = Application( layout=Layout( container=Dialog( title='Terminal demo', body=term, with_background=True ), focused_element=term ), full_screen=True, mouse_support=True, ) application.run()
def print_container(container, file=None): """ Print any layout to the output in a non-interactive way. Example usage:: from prompt_toolkit.widgets import Frame, TextArea print_container( Frame(TextArea(text='Hello world!'))) """ if file: output = create_output(stdout=file) else: output = get_default_output() def exit_immediately(): # Use `call_from_executor` to exit "soon", so that we still render one # initial time, before exiting the application. get_event_loop().call_from_executor(lambda: app.exit()) app = Application(layout=Layout(container=container), output=output) app.run(pre_run=exit_immediately)
def __init__(self, input_handler: Callable, bindings: KeyBindings, completer: Completer): self.search_field = create_search_field() self.input_field = create_input_field(completer=completer) self.output_field = create_output_field() self.log_field = create_log_field(self.search_field) self.timer = create_timer() self.process_usage = create_process_monitor() self.trade_monitor = create_trade_monitor() self.layout = generate_layout(self.input_field, self.output_field, self.log_field, self.search_field, self.timer, self.process_usage, self.trade_monitor) # add self.to_stop_config to know if cancel is triggered self.to_stop_config: bool = False self.live_updates = False self.bindings = bindings self.input_handler = input_handler self.input_field.accept_handler = self.accept self.app = Application(layout=self.layout, full_screen=True, key_bindings=self.bindings, style=load_style(), mouse_support=True, clipboard=PyperclipClipboard()) # settings self.prompt_text = ">>> " self.pending_input = None self.input_event = None self.hide_input = False # start ui tasks loop = asyncio.get_event_loop() loop.create_task(start_timer(self.timer)) loop.create_task(start_process_monitor(self.process_usage)) loop.create_task(start_trade_monitor(self.trade_monitor))
def radiolist_dialog(title='', values=None, style=None, async_=False): # Add exit key binding. kb = KeyBindings() @kb.add('c-c') @kb.add("escape") def exit_(event): """ Pressing Ctrl-c will exit the user interface. """ event.app.exit() radio_list = SingleSelectList(values) application = Application( layout=Layout(HSplit([Label(title), radio_list])), key_bindings=kb, mouse_support=True, style=style, full_screen=False, ) if async_: return application.run_async() else: return application.run()
def _create_app(dialog, style): # Key bindings. bindings = KeyBindings() bindings.add('tab')(focus_next) bindings.add('s-tab')(focus_previous) return Application(layout=Layout(dialog), key_bindings=merge_key_bindings([ load_key_bindings(), bindings, ]), mouse_support=True, style=style, full_screen=True)
def radiolist_dialog(title='', values=None, style=None, async_=False): # Add exit key binding. bindings = KeyBindings() @bindings.add('c-d') def exit_(event): """ Pressing Ctrl-d will exit the user interface. """ event.app.exit() radio_list = RadioListFast(values) application = Application( layout=Layout(HSplit([Label(title), radio_list])), key_bindings=merge_key_bindings([load_key_bindings(), bindings]), mouse_support=True, style=style, full_screen=False) if async_: return application.run_async() else: return application.run()
async def start_application(tab_completer): ui.core.input_field.accept_handler = c.handle_input ui.core.input_field.completer = tab_completer application = Application( layout=Layout(ui.core.container, focused_element=ui.core.input_field), key_bindings=ui.core.kb, style=ui.core.style, mouse_support=True, full_screen=True, ) await application.run_async(set_exception_handler=True)
def get_app(self): bindings = KeyBindings() @bindings.add(Keys.ControlC) def _ctrl_c(event): get_app().exit(exception=KeyboardInterrupt) @bindings.add(Keys.Enter) def _enter(event): get_app().exit(result=self.get_answer()) return Application(layout=Layout(self.get_layout()), key_bindings=merge_key_bindings( [load_key_bindings(), bindings]), style=get_theme_manager().get_current_style())
def setup_application(self): """docstring for setup_application""" self._clipboard = InMemoryClipboard() self._application = Application(key_bindings_registry=self._key_binding_registry, layout=self._layout, mouse_support=bool(egc.EDITOR_MOUSE_SUPPORT), use_alternate_screen=True, initial_focussed_buffer=self._editor_buffer_name, clipboard=self._clipboard, get_title=self.get_editor_title, editing_mode=EditingMode.VI if egc.EDITOR_EDITING_MODE == 'VI' else EditingMode.EMACS, on_initialize=self.editor_started_callback, on_render=self.editor_rendered_callback, on_buffer_changed=self.editor_content_changed )
def __init__(self): self._current_channel = None self._message_text_area = TextArea(read_only=True, focusable=False) self._message_input = TextArea(height=3, multiline=False) self._message_input.accept_handler = self._handle_message_entered self._root_container = HSplit([ Frame(Window(height=1, content=FormattedTextControl(lambda: [("class:title", self.get_title())]), align=WindowAlign.CENTER)), self._message_text_area, Frame(self._message_input) ]) self._keybindings = KeyBindings() @self._keybindings.add("c-c") def _(event): event.app.exit() self._app = Application(layout=Layout(self._root_container), full_screen=True, key_bindings=self._keybindings) self._app.run()
def __init__(self, python_input, original_document): """ Create an `Application` for the history screen. This has to be run as a sub application of `python_input`. When this application runs and returns, it retuns the selected lines. """ self.python_input = python_input history_mapping = HistoryMapping(self, python_input.history, original_document) self.history_mapping = history_mapping document = Document(history_mapping.concatenated_history) document = Document( document.text, cursor_position=document.cursor_position + document.get_start_of_line_position(), ) self.history_buffer = Buffer( document=document, on_cursor_position_changed=self._history_buffer_pos_changed, accept_handler=( lambda buff: get_app().exit(result=self.default_buffer.text)), read_only=True, ) self.default_buffer = Buffer( name=DEFAULT_BUFFER, document=history_mapping.get_new_document(), on_cursor_position_changed=self._default_buffer_pos_changed, read_only=True, ) self.help_buffer = Buffer(document=Document(HELP_TEXT, 0), read_only=True) self.history_layout = HistoryLayout(self) self.app = Application( layout=self.history_layout.layout, full_screen=True, style=python_input._current_style, mouse_support=Condition(lambda: python_input.enable_mouse_support), key_bindings=create_key_bindings(self, python_input, history_mapping), )
def _create_application(self, editing_mode, erase_when_done): prompt_bindings = self._create_prompt_bindings() search_mode_bindings = self._create_search_mode_bindings() application = Application( layout=self.layout, full_screen=True, key_bindings=merge_key_bindings([ merge_key_bindings([search_mode_bindings, prompt_bindings]), ]), color_depth=lambda: self.color_depth, input=self.input, output=self.output) return application
def __init__(self, opt_ns, srv_c, inst_xml): manager = KeyBindingManager() # Start with the `KeyBindingManager`. self.srv_text = ServiceOutput(opt_ns, srv_c, inst_xml) layout = HSplit( [ # One window that holds the BufferControl with the default buffer on the # left. Window( height=D.exact(1), content=TokenListControl( self.get_title_line, default_char=Char(" ", token=Token.String.ICSW.Header) ) ), Window( height=D.exact(1), content=FillControl('-', token=Token.Line) ), # Display the text 'Hello world' on the right. Window( content=TokenListControl( self.get_icsw_output, ) ), ] ) self._updating = False @manager.registry.add_binding(Keys.ControlC, eager=True) @manager.registry.add_binding("q", eager=True) def _handler_data(event): event.cli.set_return_value(0) our_style = style_from_dict(logging_tools.get_icsw_prompt_styles()) application = Application( layout=layout, use_alternate_screen=True, style=our_style, on_input_timeout=self.input_timeout, key_bindings_registry=manager.registry, ) event_loop = create_eventloop() self.application = application self.event_loop = event_loop
def __init__(self, player): self.player = player self.playerClans = ' '.join(self.player.clantags) if len(self.player.clantags) > 0 : self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ('', ' '), ('#cc00cc', self.playerClans, "utf-8"), ]) else: self.playerClans = self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ]) self.result = None self.mainRadiosRows = [] self.listOfItems = [] self.populateMainRadios() # declares self.mainRadios self.currentRadios = self.mainRadios self.description = self.mainRadios.description # description is whataver is in the description box on the right self.requestingConfirmation = False self.bindings = KeyBindings() self.bindings.add('right' )(focus_next) self.bindings.add('tab' )(focus_next) self.bindings.add('s-tab')(focus_previous) self.bindings.add('left')(focus_previous) self.bindings.add('c-m')(self.handleEnter) self.bindings.add('escape')(self.handleEscape) self.style = Style.from_dict({ 'dialog.body': 'bg:#000000 #ffcccc', #background color, text color }) self.application = Application( layout=Layout( self.getRootContainer(), focused_element=self.mainRadios, ), key_bindings=self.bindings, style=self.style, mouse_support=True, full_screen=True, )
def __init__(self, player, nameOfShop, shopInventory, shopKeeperAsciiArt=None, customCurrency=None): '''shopInventory is a list of items''' self.player = player self.name = nameOfShop self.shopInventory = shopInventory self.shopKeeperAsciiArt = shopKeeperAsciiArt if self.shopKeeperAsciiArt == None: self.shopKeeperAsciiArt =''' _\|/^ (_oo what can i get for ya | /|\\ | LL ''' self.playerClans = ' '.join(self.player.clantags) if len(self.player.clantags) > 0 : self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ('', ' '), ('#cc00cc', self.playerClans, "utf-8"), ]) else: self.playerClans = self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ]) if customCurrency == None: self.currency = "dollars" else: self.currency = customCurrency self.result = None self.buySellRadiosRows = [] self.listOfItems = [] self.populateBuySellRadios() # declares self.buySellRadios self.currentRadios = self.buySellRadios self.rightWindowDescription = self.buySellRadios.description # description is whataver is in the description box on the right self.requestingConfirmation = False self.playerIs = "at buy/sell menu" self.bindings = KeyBindings() self.bindings.add('right' )(focus_next) self.bindings.add('tab' )(focus_next) self.bindings.add('s-tab')(focus_previous) self.bindings.add('left')(focus_previous) self.bindings.add('c-m')(self.handleEnter) self.bindings.add('escape')(self.handleEscape) self.style = Style.from_dict({ 'dialog.body': 'bg:#000000 #ffcccc', #background color, text color }) self.application = Application( layout=Layout( self.getShopContainer(), focused_element=self.buySellRadios, ), key_bindings=self.bindings, style=self.style, mouse_support=True, full_screen=True, )
def __enter__(self): # Create UI Application. title_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: self.title), height=1, style='class:progressbar,title'), filter=Condition(lambda: self.title is not None)) bottom_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: self.bottom_toolbar, style='class:bottom-toolbar.text'), style='class:bottom-toolbar', height=1), filter=~is_done & renderer_height_is_known & Condition(lambda: self.bottom_toolbar is not None)) def width_for_formatter(formatter): # Needs to be passed as callable (partial) to the 'width' # parameter, because we want to call it on every resize. return formatter.get_width(progress_bar=self) progress_controls = [ Window( content=_ProgressControl(self, f), width=functools.partial(width_for_formatter, f)) for f in self.formatters ] self.app = Application( min_redraw_interval=.05, layout=Layout(HSplit([ title_toolbar, VSplit(progress_controls, height=lambda: D( preferred=len(self.counters), max=len(self.counters))), Window(), bottom_toolbar, ])), style=self.style, key_bindings=self.key_bindings, color_depth=self.color_depth, output=self.output, input=self.input) # Run application in different thread. def run(): with _auto_refresh_context(self.app, .3): try: self.app.run() except BaseException as e: traceback.print_exc() print(e) self._thread = threading.Thread(target=run) self._thread.start() # Attach WINCH signal handler in main thread. # (Interrupt that we receive during resize events.) self._has_sigwinch = hasattr(signal, 'SIGWINCH') and in_main_thread() if self._has_sigwinch: self._previous_winch_handler = self._loop.add_signal_handler( signal.SIGWINCH, self.app.invalidate) return self
def main(): # The layout. search_field = SearchToolbar() # For reverse search. output_field = TextArea(style='class:output-field', text=help_text) input_field = TextArea( height=1, prompt='>>> ', style='class:input-field', multiline=False, wrap_lines=False, search_field=search_field) container = HSplit([ output_field, Window(height=1, char='-', style='class:line'), input_field, search_field, ]) # Attach accept handler to the input field. We do this by assigning the # handler to the `TextArea` that we created earlier. it is also possible to # pass it to the constructor of `TextArea`. # NOTE: It's better to assign an `accept_handler`, rather then adding a # custom ENTER key binding. This will automatically reset the input # field and add the strings to the history. def accept(buff): # Evaluate "calculator" expression. try: output = '\n\nIn: {}\nOut: {}'.format( input_field.text, eval(input_field.text)) # Don't do 'eval' in real code! except BaseException as e: output = '\n\n{}'.format(e) new_text = output_field.text + output # Add text to output buffer. output_field.buffer.document = Document( text=new_text, cursor_position=len(new_text)) input_field.accept_handler = accept # The key bindings. kb = KeyBindings() @kb.add('c-c') @kb.add('c-q') def _(event): " Pressing Ctrl-Q or Ctrl-C will exit the user interface. " event.app.exit() # Style. style = Style([ ('output-field', 'bg:#000044 #ffffff'), ('input-field', 'bg:#000000 #ffffff'), ('line', '#004400'), ]) # Run application. application = Application( layout=Layout(container, focused_element=input_field), key_bindings=kb, style=style, mouse_support=True, full_screen=True) application.run()
def _create_app(self): """ Create `Application` instance for this . """ pymux = self.pymux def on_focus_changed(): """ When the focus changes to a read/write buffer, make sure to go to insert mode. This happens when the ViState was set to NAVIGATION in the copy buffer. """ vi_state = app.vi_state if app.current_buffer.read_only(): vi_state.input_mode = InputMode.NAVIGATION else: vi_state.input_mode = InputMode.INSERT app = Application( output=self.output, input=self.input, color_depth=self.color_depth, layout=Layout(container=self.layout_manager.layout), key_bindings=pymux.key_bindings_manager.key_bindings, mouse_support=Condition(lambda: pymux.enable_mouse_support), full_screen=True, style=self.pymux.style, style_transformation=ConditionalStyleTransformation( SwapLightAndDarkStyleTransformation(), Condition(lambda: self.pymux.swap_dark_and_light), ), on_invalidate=(lambda _: pymux.invalidate())) # Synchronize the Vi state with the CLI object. # (This is stored in the current class, but expected to be in the # CommandLineInterface.) def sync_vi_state(_): VI = EditingMode.VI EMACS = EditingMode.EMACS if self.confirm_text or self.prompt_command or self.command_mode: app.editing_mode = VI if pymux.status_keys_vi_mode else EMACS else: app.editing_mode = VI if pymux.mode_keys_vi_mode else EMACS app.key_processor.before_key_press += sync_vi_state app.key_processor.after_key_press += sync_vi_state app.key_processor.after_key_press += self.sync_focus # Set render postpone time. (.1 instead of 0). # This small change ensures that if for a split second a process # outputs a lot of information, we don't give the highest priority to # rendering output. (Nobody reads that fast in real-time.) app.max_render_postpone_time = .1 # Second. # Hide message when a key has been pressed. def key_pressed(_): self.message = None app.key_processor.before_key_press += key_pressed # The following code needs to run with the application active. # Especially, `create_window` needs to know what the current # application is, in order to focus the new pane. with set_app(app): # Redraw all CLIs. (Adding a new client could mean that the others # change size, so everything has to be redrawn.) pymux.invalidate() pymux.startup() return app
def __init__(self, player, enemy, song='worry 2.wav'): self.song = Sound( player,fileName = song, loop=-1) self.player = player self.playerClans = ' '.join(self.player.clantags) if len(self.player.clantags) > 0 : self.playerName = FormattedText([ ('#ffffff', str(player.aspect['name'])), ('', ' '), ('#cc00cc', str(self.playerClans)), ]) else: self.playerClans = self.playerName = FormattedText([ ('#ffffff', str(player.aspect['name'])), ]) self.enemy = enemy self.playerGoesNext = True # by default, enemy always gets first strike self.playerJustDodged = False self.escapeTries = 0 self.escapeChance = .3 self.battleLog = '\n\n\n\n\n\n' self.maxHeightOfBattleLogWindow = 7 self.totalWidth = 90 self.actionsWidth = 30 self.statsWidth = 20 self.selectedIndexText = '' self.result = None self.playerHPBar = ProgressBar() self.setHealthProgressBar(self.playerHPBar, self.toPercent(self.player.hp, self.player.maxhp)) self.enemyHPBar = ProgressBar() self.setHealthProgressBar(self.enemyHPBar, 100) self.radios = RadioList( values=[ #value, lable ('Attack', 'Attack'), # use eqipped weapon ('Dodge', 'Dodge'), # icrease miss chance for enemy ('Item', 'Item'), ('Run', 'Run') # try to escape # more options could be: # check - returns text about enemy potentially indicating weaknessess ], player = self.player, width = self.actionsWidth) self.bindings = KeyBindings() self.bindings.add('right' )(focus_next) self.bindings.add('tab' )(focus_next) self.bindings.add('s-tab')(focus_previous) self.bindings.add('left')(focus_previous) self.bindings.add('c-m')(self.handleEnter) self.bindings.add('escape')(self.tryToEscape) # self.bindings.add('up')(self.setSelectedIndexTextUp) # TODO: make secret easter egg key bindings # self.bindings.add('a', 'a')(self.test) self.style = Style.from_dict({ 'dialog.body': 'bg:#000000 #ffcccc', #background color, text color }) self.application = Application( layout=Layout( self.getRootContainer(), focused_element=self.radios, ), key_bindings=self.bindings, style=self.style, mouse_support=True, full_screen=True, )
class CombatUI(): def __init__(self, player, enemy, song='worry 2.wav'): self.song = Sound( player,fileName = song, loop=-1) self.player = player self.playerClans = ' '.join(self.player.clantags) if len(self.player.clantags) > 0 : self.playerName = FormattedText([ ('#ffffff', str(player.aspect['name'])), ('', ' '), ('#cc00cc', str(self.playerClans)), ]) else: self.playerClans = self.playerName = FormattedText([ ('#ffffff', str(player.aspect['name'])), ]) self.enemy = enemy self.playerGoesNext = True # by default, enemy always gets first strike self.playerJustDodged = False self.escapeTries = 0 self.escapeChance = .3 self.battleLog = '\n\n\n\n\n\n' self.maxHeightOfBattleLogWindow = 7 self.totalWidth = 90 self.actionsWidth = 30 self.statsWidth = 20 self.selectedIndexText = '' self.result = None self.playerHPBar = ProgressBar() self.setHealthProgressBar(self.playerHPBar, self.toPercent(self.player.hp, self.player.maxhp)) self.enemyHPBar = ProgressBar() self.setHealthProgressBar(self.enemyHPBar, 100) self.radios = RadioList( values=[ #value, lable ('Attack', 'Attack'), # use eqipped weapon ('Dodge', 'Dodge'), # icrease miss chance for enemy ('Item', 'Item'), ('Run', 'Run') # try to escape # more options could be: # check - returns text about enemy potentially indicating weaknessess ], player = self.player, width = self.actionsWidth) self.bindings = KeyBindings() self.bindings.add('right' )(focus_next) self.bindings.add('tab' )(focus_next) self.bindings.add('s-tab')(focus_previous) self.bindings.add('left')(focus_previous) self.bindings.add('c-m')(self.handleEnter) self.bindings.add('escape')(self.tryToEscape) # self.bindings.add('up')(self.setSelectedIndexTextUp) # TODO: make secret easter egg key bindings # self.bindings.add('a', 'a')(self.test) self.style = Style.from_dict({ 'dialog.body': 'bg:#000000 #ffcccc', #background color, text color }) self.application = Application( layout=Layout( self.getRootContainer(), focused_element=self.radios, ), key_bindings=self.bindings, style=self.style, mouse_support=True, full_screen=True, ) # call this function to change the value a progress bar (prog) to a percent def setHealthProgressBar(self,progbar, percent): if percent < 0: # should never happen but for safety percent = 0 progbar.container = FloatContainer( content=Window(height=1), floats=[ Float(left=0, top=0, right=0, bottom=0, content=VSplit([ Window(style='bg:#00cc00', # health, green width=lambda: D(weight=int(percent))), Window(style='bg:#ff0000', # damage, red width=lambda: D(weight=int(100 - percent))), ])), ]) def toPercent(self, value, max): return int(100*(float(value)/float(max))) def handleEnter(self, event): if not self.playerGoesNext: # check if it's actually your turn return self.playerGoesNext = False choice = self.radios.values[self.radios._selected_index][0] s = '' if choice == "Attack": self.attackEnemy() return # return early so attackEnemy can go to enemy turn so damaging consunmables work elif choice == "Dodge": # dodging increases chance for enemy to miss by 30% SCALING s += "You tried to dodge... " self.playerJustDodged = True elif choice == "Item": # doesnt take your turn self.playerGoesNext = True self.done(result='inventory') return elif choice == "Run": s += self.tryToEscape() else: s += "How did you do that!?" self.enemyTurn(s) def attackEnemy(self, alwaysHit=True, consumableDamage=None, consumableName=None ): s = '' if not consumableDamage == None: # if has consumable damage damage = consumableDamage # better also have a name s += "You threw the " + str(consumableName) + "... " else: s += "You tried to attack... " damage = self.player.getTotalAttackPower() s += " and did " s += str(damage) s += " damage!" # TODO color self.enemy.hp = self.enemy.hp - int(damage) if self.enemy.hp < 0: self.enemy.hp = 0 self.setHealthProgressBar(self.enemyHPBar, self.toPercent(self.enemy.hp, self.enemy.maxhp)) self.enemyTurn(s) def tryToEscape(self, event=None): s = '' s += "You tried to run..." randomChance = random.uniform(0,1) - (self.escapeTries-1) *.1 # each try makes it 10 percent easier to escape after first try if self.escapeChance > randomChance and self.escapeTries>0: #has to have already tried to escape once s += " and escaped the combat!" # TODO advanced combat: isnt ever visible self.done("escaped") else: s += " but failed to escape!" self.escapeTries += 1 return s def enemyTurn(self, textOfPlayerTurn=False): if self.enemy.hp == 0: # check if he dead self.done("win") return # for now, always try to attack TODO advanced combat self.playerGoesNext = True s='' s += self.enemy.name + " tried to " attack = self.enemy.getRandomAttack() if attack[-1] == "*": # if attack finishes the sentence s += attack[:-1] # remove * else : s += str(attack) s += " you... " # calculate hit chance and handle dodgeModifier = 0 # TODO advanced combat dodge modifier if self.playerJustDodged == True: dodgeModifier = 30 self.playerJustDodged = False if self.enemy.missChancePercent + dodgeModifier > random.randint(0,100): # missed if not attack[-1] == "*": s += " but missed!" else: s += " But missed!" else: # hit damage = self.enemy.attack if not attack[-1] == "*": s += " and dealt " + str(damage) + " damage!" else: s += " It dealt " + str(damage) + " damage!" self.player.hp = self.player.hp - damage # lose health #t1 = threading.Thread(target=self.rollNumbers(self.player.hp, self.player.hp - damage), args=()) #t1.start() # self.rollNumbers(self.player.hp, self.player.hp - damage) if self.player.hp < 0: self.player.hp = 0 self.setHealthProgressBar(self.playerHPBar, self.toPercent(self.player.hp, self.player.maxhp)) if self.player.hp == 0: #dead # TODO make death less awkwawrd self.done("lose") return if textOfPlayerTurn: self.battleLog = textOfPlayerTurn + '\n\n' + s else: self.battleLog = s self.refresh() def rollNumbers(self, start, end, speed=1.5): r = start-end # range maxSpeed = .01 if r < 0: r *= -1 startTime = .5 for t in range(r): startTime /= speed time = startTime for c in range(r+1): s = int(start - c ) self.player.hp = s self.refresh() if time < maxSpeed: wait(maxSpeed) else: wait(time) time *= speed def refresh(self): self.fillBattleLogWithNewlines() self.application.layout=Layout( self.getRootContainer(), focused_element=self.radios) def fillBattleLogWithNewlines(self): self.battleLog = wrap(self.battleLog, limit=self.totalWidth-self.actionsWidth-self.statsWidth) slicedBattleLog = self.battleLog.split('\n') # list of rows of the battlelog while True: if len(slicedBattleLog) < self.maxHeightOfBattleLogWindow: slicedBattleLog.append('\n') else: break self.battleLog = '\n'.join(slicedBattleLog) # def suspense(self): # doesnt work because ui updates on run method, not during other methods # for i in range(3): # wait(.5) # self.battleLog += '.' # self.refresh() def makeFormattedText(self, text, color='#ffffff'): return FormattedText([ (color, str(text)) ]) # returns new root container (updates text and stuff) def getRootContainer(self): height = self.maxHeightOfBattleLogWindow enemyName = self.makeFormattedText(self.enemy.name) battleLogTitle = FormattedText([ ('#ffffff', "Battle Log") ]) actionsTitle = FormattedText([ ('#ffffff', "Actions") ]) statsTitle = FormattedText([ ('#ffffff', "Stats") ]) root_container = HSplit([ VSplit([ Dialog( # actions title=actionsTitle, body=HSplit([ self.radios, ], height= height), width=self.actionsWidth ), # battlelog Dialog( title = battleLogTitle, body=Label(self.battleLog), width=self.totalWidth-self.actionsWidth - self.statsWidth ), Dialog( # stats title = statsTitle, body=Label(getStats(self.player)), width=self.statsWidth , ), ], padding=0, width = self.actionsWidth, height=height+2 ), # health bars # VSplit([ Frame( body=self.playerHPBar, title=self.playerName, width=int(self.totalWidth/2) ), Frame( body=self.enemyHPBar, title=enemyName, width=int(self.totalWidth/2) ), ], padding=0, width = self.totalWidth) ]) return root_container def run(self): self.application.run() def done(self, result='?'): self.result = result if self.result != 'inventory': self.song.stopSound() get_app().exit(result=self.result)
class Pager(object): """ The Pager main application. Usage:: p = Pager() p.add_source(...) p.run() :param source: :class:`.Source` instance. :param lexer: Prompt_toolkit `lexer` instance. :param vi_mode: Enable Vi key bindings. :param style: Prompt_toolkit `Style` instance. :param search_text: `None` or the search string that is highlighted. """ def __init__(self, vi_mode=False, style=None, search_text=None, titlebar_tokens=None): assert isinstance(vi_mode, bool) assert style is None or isinstance(style, Style) self.sources = [] self.current_source_index = 0 # Index in `self.sources`. self.highlight_search = True self.in_colon_mode = False self.message = None self.displaying_help = False self.search_text = search_text self.display_titlebar = bool(titlebar_tokens) self.titlebar_tokens = titlebar_tokens or [] self._dummy_source = DummySource() # When this is True, always make sure that the cursor goes to the # bottom of the visible content. This is similar to 'tail -f'. self.forward_forever = False # Status information for all sources. Source -> _SourceInfo. # (Remember this info as long as the Source object exists.) self.source_info = weakref.WeakKeyDictionary() # Create prompt_toolkit stuff. def open_file(buff): # Open file. self.open_file(buff.text) # Focus main buffer again. buff.reset() # Buffer for the 'Examine:' input. self.examine_buffer = Buffer( name='EXAMINE', completer=PathCompleter(expanduser=True), accept_handler=open_file, multiline=False) # Search buffer. self.search_buffer = Buffer(multiline=False) self.layout = PagerLayout(self) bindings = create_key_bindings(self) self.application = Application( input=create_input(sys.stdout), layout=Layout(container=self.layout.container), enable_page_navigation_bindings=True, key_bindings=bindings, style=style or Style.from_dict(ui_style), mouse_support=True, after_render=self._after_render, full_screen=True) # Hide message when a key is pressed. def key_pressed(_): self.message = None self.application.key_processor.before_key_press += key_pressed if vi_mode: self.application.editing_mode = EditingMode.VI @classmethod def from_pipe(cls, lexer=None): """ Create a pager from another process that pipes in our stdin. """ assert not sys.stdin.isatty() self = cls() self.add_source(PipeSource(fileno=sys.stdin.fileno(), lexer=lexer)) return self @property def current_source(self): " The current `Source`. " try: return self.sources[self.current_source_index] except IndexError: return self._dummy_source @property def current_source_info(self): try: return self.source_info[self.current_source] except KeyError: return _SourceInfo(self, self.current_source) def open_file(self, filename): """ Open this file. """ lexer = PygmentsLexer.from_filename(filename, sync_from_start=False) try: source = FileSource(filename, lexer=lexer) except IOError as e: self.message = '{}'.format(e) else: self.add_source(source) def add_source(self, source): """ Add a new :class:`.Source` instance. """ assert isinstance(source, Source) source_info = _SourceInfo(self, source) self.source_info[source] = source_info self.sources.append(source) # Focus self.current_source_index = len(self.sources) - 1 self.application.layout.focus(source_info.window) def remove_current_source(self): """ Remove the current source from the pager. (If >1 source is left.) """ if len(self.sources) > 1: current_source_index = self.current_source # Focus the previous source. self.focus_previous_source() # Remove the last source. self.sources.remove(current_source_index) else: self.message = "Can't remove the last buffer." def focus_previous_source(self): self.current_source_index = (self.current_source_index - 1) % len(self.sources) self.application.layout.focus(self.current_source_info.window) self.in_colon_mode = False def focus_next_source(self): self.current_source_index = (self.current_source_index + 1) % len(self.sources) self.application.layout.focus(self.current_source_info.window) self.in_colon_mode = False def display_help(self): """ Display help text. """ if not self.displaying_help: source = FormattedTextSource(HELP, name='<help>') self.add_source(source) self.displaying_help = True def quit_help(self): """ Hide the help text. """ if self.displaying_help: self.remove_current_source() self.displaying_help = False def _after_render(self, app): """ Each time when the rendering is done, we should see whether we need to read more data from the input pipe. """ # When the bottom is visible, read more input. # Try at least `info.window_height`, if this amount of data is # available. info = self.layout.dynamic_body.get_render_info() source = self.current_source source_info = self.source_info[source] b = source_info.buffer line_tokens = source_info.line_tokens if not source_info.waiting_for_input_stream and not source.eof() and info: lines_below_bottom = info.ui_content.line_count - info.last_visible_line() # Make sure to preload at least 2x the amount of lines on a page. if lines_below_bottom < info.window_height * 2 or self.forward_forever: # Lines to be loaded. lines = [info.window_height * 2 - lines_below_bottom] # nonlocal fd = source.get_fd() def handle_content(tokens): """ Handle tokens, update `line_tokens`, decrease line count and return list of characters. """ data = [] for token_char in tokens: char = token_char[1] if char == '\n': line_tokens.append([]) # Decrease line count. lines[0] -= 1 else: line_tokens[-1].append(token_char) data.append(char) return data def insert_text(list_of_fragments): document = Document(b.text + ''.join(list_of_fragments), b.cursor_position) b.set_document(document, bypass_readonly=True) if self.forward_forever: b.cursor_position = len(b.text) def receive_content_from_fd(): # Read data from the source. tokens = source.read_chunk() data = handle_content(tokens) # Set document. insert_text(data) # Remove the reader when we received another whole page. # or when there is nothing more to read. if lines[0] <= 0 or source.eof(): if fd is not None: get_event_loop().remove_reader(fd) source_info.waiting_for_input_stream = False # Redraw. self.application.invalidate() def receive_content_from_generator(): " (in executor) Read data from generator. " # Call `read_chunk` as long as we need more lines. while lines[0] > 0 and not source.eof(): tokens = source.read_chunk() data = handle_content(tokens) insert_text(data) # Schedule redraw. self.application.invalidate() source_info.waiting_for_input_stream = False # Set 'waiting_for_input_stream' and render. source_info.waiting_for_input_stream = True self.application.invalidate() # Add reader for stdin. if fd is not None: get_event_loop().add_reader(fd, receive_content_from_fd) else: # Execute receive_content_from_generator in thread. # (Don't use 'run_in_executor', because we need a daemon. t = threading.Thread(target=receive_content_from_generator) t.daemon = True t.start() def run(self): """ Create an event loop for the application and run it. """ try: # Set search highlighting. if self.search_text: self.application.search_state.text = self.search_text return self.application.run() finally: # XXX: Close all sources which are opened by the pager itself. pass
class ShopUI(): def __init__(self, player, nameOfShop, shopInventory, shopKeeperAsciiArt=None, customCurrency=None): '''shopInventory is a list of items''' self.player = player self.name = nameOfShop self.shopInventory = shopInventory self.shopKeeperAsciiArt = shopKeeperAsciiArt if self.shopKeeperAsciiArt == None: self.shopKeeperAsciiArt =''' _\|/^ (_oo what can i get for ya | /|\\ | LL ''' self.playerClans = ' '.join(self.player.clantags) if len(self.player.clantags) > 0 : self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ('', ' '), ('#cc00cc', self.playerClans, "utf-8"), ]) else: self.playerClans = self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ]) if customCurrency == None: self.currency = "dollars" else: self.currency = customCurrency self.result = None self.buySellRadiosRows = [] self.listOfItems = [] self.populateBuySellRadios() # declares self.buySellRadios self.currentRadios = self.buySellRadios self.rightWindowDescription = self.buySellRadios.description # description is whataver is in the description box on the right self.requestingConfirmation = False self.playerIs = "at buy/sell menu" self.bindings = KeyBindings() self.bindings.add('right' )(focus_next) self.bindings.add('tab' )(focus_next) self.bindings.add('s-tab')(focus_previous) self.bindings.add('left')(focus_previous) self.bindings.add('c-m')(self.handleEnter) self.bindings.add('escape')(self.handleEscape) self.style = Style.from_dict({ 'dialog.body': 'bg:#000000 #ffcccc', #background color, text color }) self.application = Application( layout=Layout( self.getShopContainer(), focused_element=self.buySellRadios, ), key_bindings=self.bindings, style=self.style, mouse_support=True, full_screen=True, ) def handleEscape(self, event): self.requestingConfirmation = False if self.currentRadios == self.buySellRadios: self.done() else: # return to main page self.playerIs = "at buy/sell menu" self.populateBuySellRadios() self.currentRadios = self.buySellRadios # self.description = self.buySellRadios.description self.refresh() def handleEnter(self, event): if self.requestingConfirmation: self.requestingConfirmation = False if self.playerIs == "buying": self.buy() self.listOfItems = self.shopInventory elif self.playerIs == "selling": self.sell() self.listOfItems = self.player.getAllInventoryItemsAsObjectList() if self.handleEmptiness(self.listOfItems): return self.makeListCurrentRadios(self.listOfItems) # TODO sound music, sound effect of eating a consumable return elif self.currentRadios == self.buySellRadios: # if on main page if self.currentRadios._selected_index == 0: # BUY, show shops inventory self.playerIs = "buying" self.listOfItems = self.shopInventory elif self.currentRadios._selected_index == 1: # SELL, show player inventory self.playerIs = "selling" self.listOfItems = self.player.getAllInventoryItemsAsObjectList() else:log("what the f**k") if self.handleEmptiness(self.listOfItems): return self.makeListCurrentRadios(self.listOfItems) elif self.currentRadios == self.selectedRadios: # if not on main page self.requestingConfirmation = True price = self.getCurrentlySelectedItem().sellValue if price == 1 and self.currency.endswith('s'): currency = 'dollar' else: currency = self.currency nameOfItem = self.getCurrentlySelectedItem().name if self.playerIs == "buying": self.refresh(setDescription="Purchase " + str(nameOfItem) +" for " + str(price) + " " + currency + "?") elif self.playerIs == "selling": self.refresh(setDescription="Sell " + str(nameOfItem) +" for " + str(price) + " " + currency + "?") def buy(self): item = self.getCurrentlySelectedItem() if item.sellValue > self.player.money: self.refresh(setDescription="You can't afford that.") else: self.player.money = self.player.money - item.sellValue # subtract funds self.player.money = round(self.player.money, 2) # round to cents item.sellValue = item.sellValue /2 # half the worth of the item after buying self.shopInventory.remove(item) self.player.addToInventory(item, printAboutIt=False) def sell(self): item = self.getCurrentlySelectedItem() if item.equipped == True: self.player.unequip(item=item) self.player.inventory.remove(item) # remove item from player inventory self.player.money = self.player.money + item.sellValue # get paid self.player.money = round(self.player.money, 2) # round just in case self.shopInventory.append(item) # give item to shop owner def getCurrentlySelectedItem(self): return self.listOfItems[self.currentRadios._selected_index] def handleEmptiness(self, lis): if len(self.listOfItems) == 0: self.currentRadios = self.buySellRadios if self.playerIs == "buying": self.playerIs = "at buy/sell menu" self.refresh(setDescription="Sold out!") elif self.playerIs == "selling": self.playerIs = "at buy/sell menu" self.refresh(setDescription="You've got nothing left!") return True def makeListCurrentRadios(self, lisp, selectedIndex=0): lisp = self.refreshItemDescriptions(lisp) self.listOfItemsTupled = self.tuplify(lisp) self.selectedRadios = RadioList2( values=self.listOfItemsTupled, app = self) self.selectedRadios._selected_index = selectedIndex self.currentRadios = self.selectedRadios # self.description = self.currentRadios.values[selectedIndex] self.refresh() def refreshItemDescriptions(self, lis): for i in lis: i.description = i.buildItemDescriptionString() return lis def tuplify(self, listt): if len(listt) == 0: return [] # should never see this newlist=[] for i in range(len(listt)): l = [] l.append(self.unicodify(listt[i].description)) l.append(self.unicodify(colorItem(listt[i], useGetName=True))) # colors newlist.append( tuple(l) ) return newlist def refresh(self, setDescription=False): index = self.currentRadios._selected_index if setDescription: self.rightWindowDescription = setDescription else: self.rightWindowDescription = self.currentRadios.values[index][0] self.application.layout=Layout( self.getShopContainer(), focused_element=self.currentRadios) def populateBuySellRadios(self): self.buySellRadiosRows = [] self.populateBuySellRadiosHelper('Buy') self.populateBuySellRadiosHelper('Sell') self.buySellRadios = RadioList2( values=self.buySellRadiosRows, app = self) def populateBuySellRadiosHelper(self, category): desc = self.shopKeeperAsciiArt tup = [] tup.append(desc) tup.append(category.capitalize()) self.buySellRadiosRows.append( tuple(tup) ) def unicodify(self, text): if isinstance(text, str): return str(text) else: return text def getShopContainer(self): width = 40 smallerWidth = 30 statsWidth = 20 height = 10 if self.playerIs == "at buy/sell menu": leftWindowTitle = "" descriptionArea =makeFormattedText(self.name) desc = self.rightWindowDescription elif self.playerIs == "buying": leftWindowTitle = makeFormattedText(self.name) descriptionArea = colorItem(self.getCurrentlySelectedItem()) desc = wrap(self.rightWindowDescription, width-2) elif self.playerIs == "selling": leftWindowTitle = makeFormattedText(self.player.aspect["name"]) descriptionArea = colorItem(self.getCurrentlySelectedItem()) desc = wrap(self.rightWindowDescription, width-2) root_container = VSplit([ HSplit([ Dialog( title=leftWindowTitle, body=HSplit([ self.currentRadios, ], ) ), ], padding=0, width = smallerWidth, ), HSplit([ Dialog( title = descriptionArea, body=Label(desc), ), ], padding=0, width = width,), HSplit([ Dialog( title = makeFormattedText("Stats"), body=Label(getStats(self.player)), ), ], padding=0, width = statsWidth, height= height,), ]) return root_container def run(self): self.application.run() def done(self): self.result = "hit escape" get_app().exit(result="hit escape") # TODO: # colors
class InventoryUI(): def __init__(self, player): self.player = player self.playerClans = ' '.join(self.player.clantags) if len(self.player.clantags) > 0 : self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ('', ' '), ('#cc00cc', self.playerClans, "utf-8"), ]) else: self.playerClans = self.playerName = FormattedText([ ('#ffffff', player.aspect['name']), ]) self.result = None self.mainRadiosRows = [] self.listOfItems = [] self.populateMainRadios() # declares self.mainRadios self.currentRadios = self.mainRadios self.description = self.mainRadios.description # description is whataver is in the description box on the right self.requestingConfirmation = False self.bindings = KeyBindings() self.bindings.add('right' )(focus_next) self.bindings.add('tab' )(focus_next) self.bindings.add('s-tab')(focus_previous) self.bindings.add('left')(focus_previous) self.bindings.add('c-m')(self.handleEnter) self.bindings.add('escape')(self.handleEscape) self.style = Style.from_dict({ 'dialog.body': 'bg:#000000 #ffcccc', #background color, text color }) self.application = Application( layout=Layout( self.getRootContainer(), focused_element=self.mainRadios, ), key_bindings=self.bindings, style=self.style, mouse_support=True, full_screen=True, ) def handleEscape(self, event): self.requestingConfirmation = False if self.currentRadios == self.mainRadios: self.done() else: # return to main page self.populateMainRadios() self.currentRadios = self.mainRadios # self.description = self.mainRadios.description self.refresh() def handleEnter(self, event): if self.requestingConfirmation: self.requestingConfirmation = False result = self.player.activateItem(self.getCurrentlySelectedItem()) if not isinstance(result, str): # if result isnt a string self.done(result)# this should be different self.updateListOfItems() self.makeListCurrentRadios(self.listOfItems) self.refresh(setDescription=result) # TODO sound music, sound effect of eating a consumable return if self.currentRadios == self.mainRadios: # if on main page self.updateListOfItems() self.makeListCurrentRadios(self.listOfItems) elif self.currentRadios == self.selectedRadios: # if not on main page currentItem = self.listOfItems[self.currentRadios._selected_index] if currentItem.type == "consumable": if currentItem.consumable.consumableType == 'xp': description = 'Eat it?' elif currentItem.consumable.consumableType == 'damage': description = 'Throw it?' elif currentItem.consumable.consumableType == 'heal': description = 'Eat it?' else: description = 'Crash the game?' # shouldnt ever see self.requestingConfirmation = True self.refresh(setDescription=description) return self.player.activateItem(self.listOfItems[self.currentRadios._selected_index]) # can delete items self.makeListCurrentRadios(self.listOfItems,self.selectedRadios._selected_index) def updateListOfItems(self): category = self.mainRadios.values[self.mainRadios._selected_index][1] if category == 'Weapons': self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='weapon') elif category == 'Armour': self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='armour') elif category == 'Consumable': self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='consumable') elif category == 'Quest': self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='quest') elif category == 'Misc': self.listOfItems = self.player.getAllInventoryItemsAsObjectList(_type='misc') if len(self.listOfItems) == 0: self.populateMainRadios() self.currentRadios = self.mainRadios self.refresh() def makeListCurrentRadios(self, lisp, selectedIndex=0): if len(lisp) == 0: self.populateMainRadios() self.currentRadios = self.mainRadios else: lisp = self.refreshItemDescriptions(lisp) self.listOfItemsTupled = self.tuplify(lisp) self.selectedRadios = RadioList2( values=self.listOfItemsTupled, app = self) self.selectedRadios._selected_index = selectedIndex self.currentRadios = self.selectedRadios # self.description = self.currentRadios.values[selectedIndex] self.refresh() def refreshItemDescriptions(self, lis): for i in lis: i.description = i.buildItemDescriptionString() return lis def tuplify(self, listt): if len(listt) == 0: return [] # should never see this newlist=[] for i in listt: l = [] l.append(self.unicodify(i.description)) l.append(self.unicodify(colorItem(i, useGetName=True))) # colors newlist.append( tuple(l) ) return newlist def refresh(self, setDescription=False): index = self.currentRadios._selected_index if setDescription: self.description = setDescription else: self.description = self.currentRadios.values[index][0] self.application.layout=Layout( self.getRootContainer(), focused_element=self.currentRadios) def populateMainRadios(self): self.mainRadiosRows = [] self.populateMainRadiosHelper('weapon') self.populateMainRadiosHelper('armour') self.populateMainRadiosHelper('consumable') self.populateMainRadiosHelper('quest') self.populateMainRadiosHelper('misc') self.mainRadios = RadioList2( values=self.mainRadiosRows, app = self) def populateMainRadiosHelper(self, category): s = self.unicodify(self.player.getAllInventoryItemsAsString(_type=category, showEquipped=True)) if not s == '': tup = [] tup.append(s) if category == 'weapon': tup.append('Weapons') else: tup.append(category.capitalize()) self.mainRadiosRows.append( tuple(tup) ) def unicodify(self, text): if isinstance(text, str): return str(text) else: return text def getCurrentlySelectedItem(self): return self.listOfItems[self.currentRadios._selected_index] # returns new root container (updates text and stuff) def getRootContainer(self): statsWidth = 20 largerWidth = 40 smallerWidth = 30 if self.currentRadios != self.mainRadios: descriptionTitle = colorItem(self.getCurrentlySelectedItem()) else: descriptionTitle = FormattedText([('#ffffff', "Description")]) actionsTitle = FormattedText([('#ffffff', "Inventory")]) stats = FormattedText([('#ffffff', "Stats")]) desc = wrap(self.description, largerWidth-2) root_container = VSplit([ HSplit([ Dialog( title=actionsTitle, body=HSplit([ self.currentRadios, ], ) ), ], padding=0, width = smallerWidth, ), HSplit([ Dialog( title = descriptionTitle, body=Label(desc), ), ], padding=0, width = largerWidth, ), HSplit([ Dialog( title = stats, body=Label(getStats(self.player)), ), ], padding=0, width=statsWidth ), ]) return root_container def run(self): self.application.run() def done(self, result="hit escape"): self.result = result get_app().exit(result=self.result) # TODO: # colors
def __init__(self, vi_mode=False, style=None, search_text=None, titlebar_tokens=None): assert isinstance(vi_mode, bool) assert style is None or isinstance(style, Style) self.sources = [] self.current_source_index = 0 # Index in `self.sources`. self.highlight_search = True self.in_colon_mode = False self.message = None self.displaying_help = False self.search_text = search_text self.display_titlebar = bool(titlebar_tokens) self.titlebar_tokens = titlebar_tokens or [] self._dummy_source = DummySource() # When this is True, always make sure that the cursor goes to the # bottom of the visible content. This is similar to 'tail -f'. self.forward_forever = False # Status information for all sources. Source -> _SourceInfo. # (Remember this info as long as the Source object exists.) self.source_info = weakref.WeakKeyDictionary() # Create prompt_toolkit stuff. def open_file(buff): # Open file. self.open_file(buff.text) # Focus main buffer again. buff.reset() # Buffer for the 'Examine:' input. self.examine_buffer = Buffer( name='EXAMINE', completer=PathCompleter(expanduser=True), accept_handler=open_file, multiline=False) # Search buffer. self.search_buffer = Buffer(multiline=False) self.layout = PagerLayout(self) bindings = create_key_bindings(self) self.application = Application( input=create_input(sys.stdout), layout=Layout(container=self.layout.container), enable_page_navigation_bindings=True, key_bindings=bindings, style=style or Style.from_dict(ui_style), mouse_support=True, after_render=self._after_render, full_screen=True) # Hide message when a key is pressed. def key_pressed(_): self.message = None self.application.key_processor.before_key_press += key_pressed if vi_mode: self.application.editing_mode = EditingMode.VI
class ProgressBar(object): """ Progress bar context manager. Usage :: with ProgressBar(...) as pb: for item in pb(data): ... :param title: Text to be displayed above the progress bars. This can be a callable or formatted text as well. :param formatters: List of :class:`.Formatter` instances. :param bottom_toolbar: Text to be displayed in the bottom toolbar. This can be a callable or formatted text. :param style: :class:`prompt_toolkit.styles.BaseStyle` instance. :param key_bindings: :class:`.KeyBindings` instance. :param file: The file object used for rendering, by default `sys.stderr` is used. :param color_depth: `prompt_toolkit` `ColorDepth` instance. :param output: :class:`~prompt_toolkit.output.Output` instance. :param input: :class:`~prompt_toolkit.input.Input` instance. """ def __init__(self, title=None, formatters=None, bottom_toolbar=None, style=None, key_bindings=None, file=None, color_depth=None, output=None, input=None): assert formatters is None or ( isinstance(formatters, list) and all(isinstance(fo, Formatter) for fo in formatters)) assert style is None or isinstance(style, BaseStyle) assert key_bindings is None or isinstance(key_bindings, KeyBindings) self.title = title self.formatters = formatters or create_default_formatters() self.bottom_toolbar = bottom_toolbar self.counters = [] self.style = style self.key_bindings = key_bindings # Note that we use __stderr__ as default error output, because that # works best with `patch_stdout`. self.color_depth = color_depth self.output = output or create_output(stdout=file or sys.__stderr__) self.input = input or get_default_input() self._thread = None self._loop = get_event_loop() self._previous_winch_handler = None self._has_sigwinch = False def __enter__(self): # Create UI Application. title_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: self.title), height=1, style='class:progressbar,title'), filter=Condition(lambda: self.title is not None)) bottom_toolbar = ConditionalContainer( Window(FormattedTextControl(lambda: self.bottom_toolbar, style='class:bottom-toolbar.text'), style='class:bottom-toolbar', height=1), filter=~is_done & renderer_height_is_known & Condition(lambda: self.bottom_toolbar is not None)) def width_for_formatter(formatter): # Needs to be passed as callable (partial) to the 'width' # parameter, because we want to call it on every resize. return formatter.get_width(progress_bar=self) progress_controls = [ Window( content=_ProgressControl(self, f), width=functools.partial(width_for_formatter, f)) for f in self.formatters ] self.app = Application( min_redraw_interval=.05, layout=Layout(HSplit([ title_toolbar, VSplit(progress_controls, height=lambda: D( preferred=len(self.counters), max=len(self.counters))), Window(), bottom_toolbar, ])), style=self.style, key_bindings=self.key_bindings, color_depth=self.color_depth, output=self.output, input=self.input) # Run application in different thread. def run(): with _auto_refresh_context(self.app, .3): try: self.app.run() except BaseException as e: traceback.print_exc() print(e) self._thread = threading.Thread(target=run) self._thread.start() # Attach WINCH signal handler in main thread. # (Interrupt that we receive during resize events.) self._has_sigwinch = hasattr(signal, 'SIGWINCH') and in_main_thread() if self._has_sigwinch: self._previous_winch_handler = self._loop.add_signal_handler( signal.SIGWINCH, self.app.invalidate) return self def __exit__(self, *a): # Quit UI application. if self.app.is_running: self.app.exit() # Remove WINCH handler. if self._has_sigwinch: self._loop.add_signal_handler(signal.SIGWINCH, self._previous_winch_handler) self._thread.join() def __call__(self, data=None, label='', remove_when_done=False, total=None): """ Start a new counter. :param label: Title text or description for this progress. (This can be formatted text as well). :param remove_when_done: When `True`, hide this progress bar. :param total: Specify the maximum value if it can't be calculated by calling ``len``. """ assert is_formatted_text(label) assert isinstance(remove_when_done, bool) counter = ProgressBarCounter( self, data, label=label, remove_when_done=remove_when_done, total=total) self.counters.append(counter) return counter def invalidate(self): self.app.invalidate()