def python_sidebar(python_input): """ Create the `Layout` for the sidebar with the configurable options. """ def get_tokens(cli): tokens = [] T = Token.Sidebar def append_category(category): tokens.extend([ (T, ' '), (T.Title, ' %-36s' % category.title), (T, '\n'), ]) def append(index, label, status): selected = index == python_input.selected_option_index @if_mousedown def select_item(cli, mouse_event): python_input.selected_option_index = index @if_mousedown def goto_next(cli, mouse_event): " Select item and go to next value. " python_input.selected_option_index = index option = python_input.selected_option option.activate_next() token = T.Selected if selected else T tokens.append((T, ' >' if selected else ' ')) tokens.append((token.Label, '%-24s' % label, select_item)) tokens.append((token.Status, ' ', select_item)) tokens.append((token.Status, '%s' % status, goto_next)) if selected: tokens.append((Token.SetCursorPosition, '')) tokens.append((token.Status, ' ' * (13 - len(status)), goto_next)) tokens.append((T, '<' if selected else '')) tokens.append((T, '\n')) i = 0 for category in python_input.options: append_category(category) for option in category.options: append(i, option.title, '%s' % option.get_current_value()) i += 1 tokens.pop() # Remove last newline. return tokens class Control(TokenListControl): def move_cursor_down(self, cli): python_input.selected_option_index += 1 def move_cursor_up(self, cli): python_input.selected_option_index -= 1 return ConditionalContainer(content=Window( Control(get_tokens, Char(token=Token.Sidebar), has_focus=ShowSidebar(python_input) & ~IsDone()), width=LayoutDimension.exact(43), height=LayoutDimension(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=ShowSidebar(python_input) & ~IsDone())
def __init__( self, options, default_index=0, header_filter=lambda x: x, match_filter=lambda x: x, custom_filter=None, search_buffer=Buffer(multiline=False), cpu_count=multiprocessing.cpu_count() ): assert(isinstance(options, list)) assert(callable(header_filter)) assert(callable(match_filter)) assert(isinstance(default_index, int)) self.search_buffer = search_buffer self.last_query_text = '' self.search_buffer.on_text_changed += self.update self.header_filter = header_filter self.match_filter = match_filter self.current_index = default_index self.entries_left_offset = 0 self.pool = multiprocessing.Pool(cpu_count) self.options_headers_linecount = [] self._indices_to_lines = [] self._options = [] self.marks = [] self.max_entry_height = 1 # Options are processed here also through the setter self.options = options self.cursor = Point(0, 0) self.content = FormattedTextControl( text=self.get_tokens, focusable=False, key_bindings=None, get_cursor_position=lambda: self.cursor, ) self.content_window = Window( content=self.content, wrap_lines=False, allow_scroll_beyond_bottom=True, scroll_offsets=ScrollOffsets(bottom=self.max_entry_height), cursorline=False, cursorcolumn=False, # right_margins=[NumberedMargin()], # left_margins=[NumberedMargin()], align=WindowAlign.LEFT, height=None, get_line_prefix=self.get_line_prefix # get_line_prefix=lambda line, b: [('bg:red', ' ')] ) self.update() super(OptionsList, self).__init__( content=self.content_window, filter=( custom_filter if custom_filter is not None else has_focus(self.search_buffer) ) )
def __init__(self, my_app: "sqlApp") -> None: self.my_app = my_app self.search_field = SearchToolbar() history_file = config_location() + 'history' ensure_dir_exists(history_file) hist = ThreadedHistory(FileHistory(expanduser(history_file))) self.input_buffer = Buffer( name="defaultbuffer", tempfile_suffix=".py", multiline=MultilineFilter(self.my_app), history=hist, completer=DynamicCompleter( lambda: ThreadedCompleter(self.my_app.completer)), # lambda: self.my_app.completer), auto_suggest=ThreadedAutoSuggest(AutoSuggestFromHistory()), complete_while_typing=Condition( lambda: self.my_app.active_conn is not None)) main_win_control = BufferControl( buffer=self.input_buffer, lexer=PygmentsLexer(SqlLexer), search_buffer_control=self.search_field.control, include_default_input_processors=False, input_processors=[AppendAutoSuggestion()], preview_search=True) self.main_win = Window( main_win_control, height=( lambda: (None if get_app().is_done else (Dimension(min=self.my_app.min_num_menu_lines) if not self.my_app.show_preview else Dimension( min=self.my_app.min_num_menu_lines, preferred=180)))), get_line_prefix=partial(sql_line_prefix, my_app=self.my_app), scroll_offsets=ScrollOffsets(bottom=1, left=4, right=4)) self.lprompt = login_prompt(self.my_app) self.preview = preview_element(self.my_app) self.disconnect_dialog = disconnect_dialog(self.my_app) container = HSplit([ VSplit([ FloatContainer( content=HSplit([ self.main_win, self.search_field, ]), floats=[ Float( bottom=1, left=1, right=0, content=sql_sidebar_help(self.my_app), ), Float(content=self.lprompt), Float(content=self.preview, ), Float(content=self.disconnect_dialog, ), Float(left=2, bottom=1, content=exit_confirmation(self.my_app)), Float(xcursor=True, ycursor=True, transparent=True, content=CompletionsMenu(scroll_offset=1, max_height=16, extra_filter=has_focus( self.input_buffer))) ]), ConditionalContainer( content=sql_sidebar(self.my_app), filter=ShowSidebar(self.my_app) & ~is_done, ) ]), VSplit([ status_bar(self.my_app), show_sidebar_button_info(self.my_app) ]) ]) def accept(buff): app = get_app() app.exit(result=["non-preview", buff.text]) app.pre_run_callables.append(buff.reset) return True self.input_buffer.accept_handler = accept self.layout = Layout(container, focused_element=self.main_win)
def sql_sidebar(my_app: "sqlApp") -> Window: """ Create the `Layout` for the sidebar with the configurable objects. """ @if_mousedown def expand_item(obj: "myDBObject") -> None: obj.expand() def tokenize_obj(obj: "myDBObject") -> StyleAndTextTuples: " Recursively build the token list " tokens: StyleAndTextTuples = [] selected = obj is my_app.selected_object expanded = obj.children is not None connected = obj.otype == "Connection" and obj.conn.connected() active = my_app.active_conn is not None and my_app.active_conn is obj.conn and obj.level == 0 act = ",active" if active else "" sel = ",selected" if selected else "" if len(obj.name) > 24 - 2 * obj.level: name_trim = obj.name[:24 - 2 * obj.level - 3] + "..." else: name_trim = ("%-" + str(24 - 2 * obj.level) + "s") % obj.name tokens.append( ("class:sidebar.label" + sel + act, " >" if connected else " ")) tokens.append( ("class:sidebar.label" + sel, " " * 2 * obj.level, expand_item)) tokens.append( ("class:sidebar.label" + sel + act, name_trim, expand_item)) tokens.append(("class:sidebar.status" + sel + act, " ", expand_item)) tokens.append(("class:sidebar.status" + sel + act, "%+12s" % obj.otype, expand_item)) if selected: tokens.append(("[SetCursorPosition]", "")) if expanded: tokens.append(("class:sidebar.status" + sel + act, "\/")) else: tokens.append(("class:sidebar.status" + sel + act, " <" if selected else " ")) # Expand past the edge of the visible buffer to get an even panel tokens.append(("class:sidebar.status" + sel + act, " " * 10)) return tokens def _buffer_pos_changed(buff): """ When the cursor changes in the sidebar buffer, make sure the appropriate database object is market as selected """ # Only when this buffer has the focus. try: line_no = buff.document.cursor_position_row if line_no < 0: # When the cursor is above the inserted region. raise IndexError idx = 0 obj = my_app.obj_list[0] while idx < line_no: if not obj.next_object: raise IndexError idx += 1 obj = obj.next_object my_app.selected_object = obj except IndexError: pass search_buffer = Buffer(name="sidebarsearchbuffer") search_field = SearchToolbar(search_buffer=search_buffer, ignore_case=True) sidebar_buffer = Buffer(name="sidebarbuffer", read_only=True, on_cursor_position_changed=_buffer_pos_changed) class myLexer(Lexer): def __init__(self, token_list=None, *args, **kwargs): super().__init__(*args, **kwargs) self.token_list = token_list def lex_document( self, document: Document) -> Callable[[int], StyleAndTextTuples]: def get_line(lineno: int) -> StyleAndTextTuples: # TODO: raise out-of-range exception return self.token_list[lineno] return get_line def reset_tokens(self, tokens: [StyleAndTextTuples]): self.token_list = tokens sidebar_lexer = myLexer() class myControl(BufferControl): def move_cursor_down(self): my_app.select_next() # Need to figure out what do do here # AFAICT thse are only called for the mouse handler # when events are otherwise not handled def move_cursor_up(self): my_app.select_previous() def mouse_handler(self, mouse_event: MouseEvent) -> "NotImplementedOrNone": """ There is an intricate relationship between the cursor position in the sidebar document and which object is market as 'selected' in the linked list. Let's not muck that up by allowing the user to change the cursor position in the sidebar document with the mouse. """ return NotImplemented def create_content(self, width: int, height: Optional[int]) -> UIContent: res = [] res_tokens = [] count = 0 obj = my_app.obj_list[0] res.append(obj.name) res_tokens.append(tokenize_obj(obj)) found_selected = obj is my_app.selected_object idx = 0 while obj.next_object is not my_app.obj_list[0]: res.append(obj.next_object.name) res_tokens.append(tokenize_obj(obj.next_object)) if obj is not my_app.selected_object and not found_selected: count += 1 idx += len(obj.name) + 1 # Newline character else: found_selected = True obj = obj.next_object self.buffer.set_document( Document(text="\n".join(res), cursor_position=idx), True) self.lexer.reset_tokens(res_tokens) return super().create_content(width, height) sidebar_control = myControl( buffer=sidebar_buffer, lexer=sidebar_lexer, search_buffer_control=search_field.control, focusable=True, ) return HSplit([ search_field, Window(sidebar_control, right_margins=[ScrollbarMargin(display_arrows=True)], style="class:sidebar", width=Dimension.exact(45), height=Dimension(min=7, preferred=33), scroll_offsets=ScrollOffsets(top=1, bottom=1)), Window( height=Dimension.exact(1), char="\u2500", style="class:sidebar,separator", ), expanding_object_notification(my_app), sql_sidebar_navigation() ])
def __init__(self): pdb.Pdb.__init__(self) # Cache for the grammar. self._grammar_cache = None # (current_pdb_commands, grammar) tuple. self.completer = None self.validator = None self.lexer = None self._source_code_window = Window(BufferControl( buffer_name='source_code', lexer=PygmentsLexer(PythonLexer), input_processors=[ HighlightSearchProcessor(preview_search=True), HighlightSelectionProcessor(), ], ), left_margins=[ SourceCodeMargin(self), NumberredMargin(), ], right_margins=[ScrollbarMargin()], scroll_offsets=ScrollOffsets( top=2, bottom=2), height=LayoutDimension(preferred=10)) # Callstack window. callstack = CallStack(weakref.ref(self)) self.callstack_focussed = False # When True, show cursor there, and allow navigation through it. self.callstack_selected_frame = 0 # Top frame. show_pdb_content_filter = ~IsDone() & Condition( lambda cli: not self.python_input.show_exit_confirmation) self.python_input = PythonInput( get_locals=lambda: self.curframe.f_locals, get_globals=lambda: self.curframe.f_globals, _completer=DynamicCompleter(lambda: self.completer), _validator=DynamicValidator(lambda: self.validator), _accept_action=self._create_accept_action(), _extra_buffers={'source_code': Buffer(read_only=True)}, _input_buffer_height=LayoutDimension(min=2, max=4), _lexer=PdbLexer(), _extra_buffer_processors=[ ConditionalProcessor(processor=CompletionHint(), filter=~IsDone()) ], _extra_layout_body=ConditionalContainer( HSplit([ VSplit([ HSplit([ SourceTitlebar(weakref.ref(self)), FloatContainer( content=self._source_code_window, floats=[ Float(right=0, bottom=0, content=BreakPointInfoToolbar( weakref.ref(self))) ]), ]), HSplit([ Window(width=LayoutDimension.exact(1), height=LayoutDimension.exact(1), content=FillControl( '\u252c', token=Token.Toolbar.Title)), Window(width=LayoutDimension.exact(1), content=FillControl('\u2502', token=Token.Separator)), ]), HSplit([ StackTitlebar(weakref.ref(self)), Window(callstack, scroll_offsets=ScrollOffsets(top=2, bottom=2), right_margins=[ScrollbarMargin()], height=LayoutDimension(preferred=10)), ]), ]), ]), filter=show_pdb_content_filter), _extra_toolbars=[ ConditionalContainer(PdbShortcutsToolbar(weakref.ref(self)), show_pdb_content_filter) ], history_filename=os.path.expanduser('~/.ptpdb_history'), ) # Override prompt style. self.python_input.all_prompt_styles['pdb'] = PdbPromptStyle( self._get_current_pdb_commands()) self.python_input.prompt_style = 'pdb' # Override exit message. self.python_input.exit_message = 'Do you want to quit BDB? This raises BdbQuit.' # Set UI styles. self.python_input.ui_styles = { 'ptpdb': get_ui_style(), } self.python_input.use_ui_colorscheme('ptpdb') # Set autocompletion style. (Multi-column works nicer.) self.python_input.completion_visualisation = CompletionVisualisation.MULTI_COLUMN # Load additional key bindings. load_custom_pdb_key_bindings(self, self.python_input.key_bindings_registry) self.cli = CommandLineInterface( eventloop=create_eventloop(), application=self.python_input.create_application())
def __init__(self, editor): def highlight_location(location, search_string, default_token): """ Return a tokenlist with the `search_string` highlighted. """ result = [(default_token, c) for c in location] # Replace token of matching positions. for m in re.finditer(re.escape(search_string), location): for i in range(m.start(), m.end()): result[i] = ('class:searchmatch', result[i][1]) if location == search_string: result[0] = (result[0][0] + ' [SetCursorPosition]', result[0][1]) return result def get_tokens(): wa = editor.window_arrangement buffer_infos = wa.list_open_buffers() # Filter infos according to typed text. input_params = editor.command_buffer.text.lstrip().split(None, 1) search_string = input_params[1] if len(input_params) > 1 else '' if search_string: def matches(info): """ True when we should show this entry. """ # When the input appears in the location. if input_params[1] in (info.editor_buffer.location or ''): return True # When the input matches this buffer his index number. if input_params[1] in str(info.index): return True # When this entry is part of the current completions list. b = editor.command_buffer if b.complete_state and any( info.editor_buffer.location in c.display for c in b.complete_state.completions if info.editor_buffer.location is not None): return True return False buffer_infos = [info for info in buffer_infos if matches(info)] # Render output. if len(buffer_infos) == 0: return [('', ' No match found. ')] else: result = [] # Create title. result.append(('', ' ')) result.append(('class:title', 'Open buffers\n')) # Get length of longest location max_location_len = max( len(info.editor_buffer.get_display_name()) for info in buffer_infos) # Show info for each buffer. for info in buffer_infos: eb = info.editor_buffer char = '%' if info.is_active else ' ' char2 = 'a' if info.is_visible else ' ' char3 = ' + ' if info.editor_buffer.has_unsaved_changes else ' ' t = 'class:active' if info.is_active else '' result.extend([ ('', ' '), (t, '%3i ' % info.index), (t, '%s' % char), (t, '%s ' % char2), (t, '%s ' % char3), ]) result.extend( highlight_location(eb.get_display_name(), search_string, t)) result.extend([ (t, ' ' * (max_location_len - len(eb.get_display_name()))), (t + ' class:lineno', ' line %i' % (eb.buffer.document.cursor_position_row + 1)), (t, ' \n') ]) return result super(BufferListOverlay, self).__init__(Window(FormattedTextControl(get_tokens), style='class:bufferlist', scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=_bufferlist_overlay_visible(editor))
def get_app(choices): class InquirerControl(TokenListControl): selected_option_index = 0 answered = False choices = [] def __init__(self, choices, **kwargs): self.choices = choices super(InquirerControl, self).__init__(self._get_choice_tokens, **kwargs) @property def choice_count(self): return len(self.choices) def _get_choice_tokens(self, cli): tokens = [] T = Token def append(index, label): selected = (index == self.selected_option_index) tokens.append((T.Selected if selected else T, '> ' if selected else ' ')) if selected: tokens.append((Token.SetCursorPosition, '')) tokens.append((T.Selected if selected else T, '%-24s' % label)) tokens.append((T, '\n')) for i, choice in enumerate(self.choices): append(i, choice) tokens.pop() # Remove last newline. return tokens def get_selection(self): return self.choices[self.selected_option_index] ic = InquirerControl(choices) def get_prompt_tokens(cli): tokens = [] if ic.answered: cli.return_value = lambda: ic.get_selection() return tokens layout = HSplit([ Window(height=D.exact(0), content=TokenListControl(get_prompt_tokens, align_center=False)), ConditionalContainer(Window(ic, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=~IsDone()) ]) manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): event.cli.set_return_value(None) @manager.registry.add_binding(Keys.Down, eager=True) @manager.registry.add_binding(Keys.ControlN, eager=True) def move_cursor_down(event): ic.selected_option_index = ((ic.selected_option_index + 1) % ic.choice_count) @manager.registry.add_binding(Keys.Up, eager=True) @manager.registry.add_binding(Keys.ControlP, eager=True) def move_cursor_up(event): ic.selected_option_index = ((ic.selected_option_index - 1) % ic.choice_count) @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(None) inquirer_style = style_from_dict({ Token.QuestionMark: '#5F819D', Token.Selected: '#FF9D00', Token.Instruction: '', Token.Answer: '#FF9D00 bold', Token.Question: 'bold', }) app = Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=inquirer_style) return app
tokens.append((Token.Question, string_query)) if ic.answered: tokens.append((Token.Answer, ' ' + ic.get_selection())) selected_item(ic.get_selection()) else: tokens.append((Token.Instruction, inst)) return tokens layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens, align_center=False)), ConditionalContainer(Window(ic, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=~IsDone()) ]) manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): event.cli.set_return_value(None) @manager.registry.add_binding(Keys.Down, eager=True) def move_cursor_down(event): ic.selected_option_index = ((ic.selected_option_index + 1) %
def execute_code(self, frame): code = frame.code parsed_code = parse_code(frame) while True: inst = Inst(code[frame.ip]) operand_stack_layout = [] i = 0 for v in frame.stack[::-1]: operand_stack_layout += [Label(f'TOS: {v}' if i == 0 else f' {v}')] i += 1 if isinstance(v, (np.longlong, np.double)): operand_stack_layout += [Label('')] i += 1 code_layout = [] focused_element = None for ip, insn in parsed_code.items(): if ip==frame.ip: focused_element = Label(insn, style='bold fg:red') code_layout += [focused_element] else: code_layout += [Label(insn)] container = HSplit([ VSplit([ HSplit([ PTFrame( HSplit([ TextArea(f'NUMSTEPS'), Label(f'Class: {frame.current_class.name()}'), Label(f'Method: {frame.current_class.name()}.{frame.current_method.name}:{frame.current_method.desc}'), ], height=3), title='Context', ), PTFrame( ScrollablePane(HSplit(code_layout, height=len(parsed_code) or 1), scroll_offsets=ScrollOffsets(top=5, bottom=5), show_scrollbar=False), title='ByteCode', ), ]), HSplit([ PTFrame( HSplit([Label(f'{i}: {v}') for i, v in enumerate(frame.locals) ], height=len(frame.locals) or 1), title='Local Variables Stack', ), PTFrame( HSplit(operand_stack_layout, height=len(operand_stack_layout) or 1), title='Operands Stack', ) ]) ]), Window(), Label('UP/DOWN: step backward/forward. gg/GG: jump to the start/end. v: toggle view. q: quit.') ]) global LAYOUT_STACK layout = Layout(container=container, focused_element=focused_element) LAYOUT_STACK += [layout] #print(frame.ip, inst.name) if len(frame.stack) > frame.max_stack + 1: print("MAX STACK") break if inst in OPCODES: OPCODES[inst](frame) elif inst == Inst.IASTORE or inst == Inst.AASTORE: val = frame.stack.pop() index = frame.stack.pop() array = frame.stack.pop() array[index] = val elif inst == Inst.IREM: v2 = frame.stack.pop() v1 = frame.stack.pop() frame.stack.append(v1 % v2) elif inst == Inst.IINC: index = read_byte(frame) const = read_signed_byte(frame) frame.set_local(index, frame.get_local(index) + const) elif inst == Inst.IFNE: v1 = frame.stack.pop() branch = read_signed_short(frame) if v1 != 0: frame.ip -= 3 frame.ip += branch elif inst == Inst.IFLT: v1 = frame.stack.pop() branch = read_signed_short(frame) if v1 < 0: frame.ip -= 3 frame.ip += branch elif inst == Inst.IFGE: v1 = frame.stack.pop() branch = read_signed_short(frame) if v1 >= 0: frame.ip -= 3 frame.ip += branch elif inst == Inst.IFLE: v1 = frame.stack.pop() branch = read_signed_short(frame) if v1 <= 0: frame.ip -= 3 frame.ip += branch elif inst == Inst.IF_ICMPLT: v2 = frame.stack.pop() v1 = frame.stack.pop() branch = read_signed_short(frame) if type(v1) is str and len(v1) == 1: v1 = ord(v1) if type(v2) is str and len(v2) == 1: v2 = ord(v2) if v1 < v2: frame.ip -= 3 frame.ip += branch elif inst == Inst.IF_ICMPGE: v2 = frame.stack.pop() v1 = frame.stack.pop() branch = read_signed_short(frame) if type(v1) is str and len(v1) == 1: v1 = ord(v1) if type(v2) is str and len(v2) == 1: v2 = ord(v2) if v1 >= v2: frame.ip -= 3 frame.ip += branch elif inst == Inst.IF_ICMPGT: v2 = frame.stack.pop() v1 = frame.stack.pop() branch = read_signed_short(frame) if type(v1) is str and len(v1) == 1: v1 = ord(v1) if type(v2) is str and len(v2) == 1: v2 = ord(v2) if v1 > v2: frame.ip -= 3 frame.ip += branch elif inst == Inst.IF_ICMPLE: v2 = frame.stack.pop() v1 = frame.stack.pop() branch = read_signed_short(frame) if v1 <= v2: frame.ip -= 3 frame.ip += branch elif inst == Inst.GOTO: branch = read_signed_short(frame) frame.ip -= 3 frame.ip += branch elif inst == Inst.IRET or inst == Inst.LRET or inst == Inst.ARETURN or inst == Inst.DRETURN: return frame.stack.pop() elif inst == Inst.RETURN: return elif inst == Inst.GETSTATIC: index = read_unsigned_short(frame) methodRef = frame.current_class.const_pool[index - 1] name = frame.current_class.const_pool[methodRef.class_index - 1].name natIndex = methodRef.name_and_type_index nat = frame.current_class.const_pool[natIndex - 1] if name in self.class_files: cl = self.class_files[name] if not cl.static_initialized: cl.static_initialized = True # first parse and initialize all existing static fields if isinstance(cl, ClassFile): for c in cl.const_pool: if c.tag and c.tag.name == 'FIELDREF': name = cl.const_pool[c.name_and_type_index-1].name desc = cl.const_pool[c.name_and_type_index-1].desc cl.set_field(name, DEFAULTS.get(desc, None)) # then run the initializers cl.handleStatic('<clinit>', '()V', frame) frame.stack.append(cl.get_field(nat.name)) #print(name) #print(vars(nat)) #frame.stack.append(PrintStream()) elif inst == Inst.PUTSTATIC: index = read_unsigned_short(frame) methodRef = frame.current_class.const_pool[index - 1] name = frame.current_class.const_pool[methodRef.class_index - 1].name natIndex = methodRef.name_and_type_index nat = frame.current_class.const_pool[natIndex - 1] if name in self.class_files: cl = self.class_files[name] if not cl.static_initialized: cl.static_initialized = True # run the initializers cl.handleStatic('<clinit>', '()V', frame) cl.set_field(nat.name, frame.stack.pop()) elif inst == Inst.GETFIELD: index = read_unsigned_short(frame) ref = frame.current_class.const_pool[index - 1] name = frame.current_class.const_pool[ref.class_index - 1].name natIndex = ref.name_and_type_index nat = frame.current_class.const_pool[natIndex - 1] #print(vars(nat)) obj = frame.stack.pop() #print(obj) frame.stack.append(obj.get_field(nat.name)) elif inst == Inst.PUTFIELD: index = read_unsigned_short(frame) ref = frame.current_class.const_pool[index - 1] name = frame.current_class.const_pool[ref.class_index - 1].name natIndex = ref.name_and_type_index nat = frame.current_class.const_pool[natIndex - 1] #print(vars(nat)) value = frame.stack.pop() obj = frame.stack.pop() obj.set_field(nat.name, value) elif inst == Inst.INVOKEVIRTUAL: index = read_unsigned_short(frame) methodRef = frame.current_class.const_pool[index - 1] name = frame.current_class.const_pool[methodRef.class_index - 1].name natIndex = methodRef.name_and_type_index nat = frame.current_class.const_pool[natIndex - 1] #print(name) #print(vars(nat)) if name in self.class_files: cl = self.class_files[name] if cl.canHandleMethod(nat.name, nat.desc): ret = cl.handleMethod(nat.name, nat.desc, frame) if not nat.desc.endswith('V'): frame.push(ret) else: for i in range(argumentCount(nat.desc)): frame.stack.pop() frame.stack.pop() elif inst == Inst.INVOKESPECIAL: index = read_unsigned_short(frame) methodRef = frame.current_class.const_pool[index - 1] name = frame.current_class.const_pool[methodRef.class_index - 1].name natIndex = methodRef.name_and_type_index nat = frame.current_class.const_pool[natIndex - 1] #print(vars(methodRef)) #print(vars(nat)) #print(name) if name in self.class_files: cl = self.class_files[name] if cl.canHandleMethod(nat.name, nat.desc): ret = cl.handleMethod(nat.name, nat.desc, frame) else: frame.stack.pop() elif inst == Inst.INVOKESTATIC: index = read_unsigned_short(frame) methodRef = frame.current_class.const_pool[index - 1] cname = frame.current_class.const_pool[methodRef.class_index - 1].name natIndex = methodRef.name_and_type_index nat = frame.current_class.const_pool[natIndex - 1] #print(vars(methodRef)) #print(vars(nat)) #print(cname) if cname in self.class_files: cl = self.class_files[cname] if cl.canHandleMethod(nat.name, nat.desc): ret = cl.handleStatic(nat.name, nat.desc, frame) if not nat.desc.endswith('V'): frame.push(ret) elif inst == Inst.NEW: index = read_unsigned_short(frame) methodRef = frame.current_class.const_pool[index - 1] if methodRef.name in self.class_files: obj = self.class_files[methodRef.name].__class__() if self.class_files[methodRef.name].file_path: obj.from_file(self.class_files[methodRef.name].file_path) obj.python_initialize() frame.stack.append(obj) else: frame.stack.append(None) #print(frame.stack, frame.locals) frame.ip += 1
def python_sidebar(python_input): """ Create the `Layout` for the sidebar with the configurable options. """ def get_text_fragments(): tokens = [] def append_category(category): tokens.extend([ ('class:sidebar', ' '), ('class:sidebar.title', ' %-36s' % category.title), ('class:sidebar', '\n'), ]) def append(index, label, status): selected = index == python_input.selected_option_index @if_mousedown def select_item(mouse_event): python_input.selected_option_index = index @if_mousedown def goto_next(mouse_event): " Select item and go to next value. " python_input.selected_option_index = index option = python_input.selected_option option.activate_next() sel = ',selected' if selected else '' tokens.append(('class:sidebar' + sel, ' >' if selected else ' ')) tokens.append( ('class:sidebar.label' + sel, '%-24s' % label, select_item)) tokens.append(('class:sidebar.status' + sel, ' ', select_item)) tokens.append( ('class:sidebar.status' + sel, '%s' % status, goto_next)) if selected: tokens.append(('[SetCursorPosition]', '')) tokens.append(('class:sidebar.status' + sel, ' ' * (13 - len(status)), goto_next)) tokens.append(('class:sidebar', '<' if selected else '')) tokens.append(('class:sidebar', '\n')) i = 0 for category in python_input.options: append_category(category) for option in category.options: append(i, option.title, '%s' % option.get_current_value()) i += 1 tokens.pop() # Remove last newline. return tokens class Control(FormattedTextControl): def move_cursor_down(self): python_input.selected_option_index += 1 def move_cursor_up(self): python_input.selected_option_index -= 1 return Window(Control(get_text_fragments), style='class:sidebar', width=Dimension.exact(43), height=Dimension(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1))
def question(message, **kwargs): # TODO add bottom-bar (Move up and down to reveal more choices) # TODO extract common parts for list, checkbox, rawlist, expand # TODO disabled # TODO validate if not 'choices' in kwargs: raise PromptParameterException('choices') # this does not implement default, use checked... if 'default' in kwargs: raise ValueError('Checkbox does not implement \'default\' ' 'use \'checked\':True\' in choice!') choices = kwargs.pop('choices', None) validator = setup_simple_validator(kwargs) # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices) def get_prompt_tokens(cli): tokens = [] T = Token tokens.append((Token.QuestionMark, '?')) tokens.append((Token.Question, ' %s ' % message)) if ic.answered: nbr_selected = len(ic.selected_options) if nbr_selected == 0: tokens.append((Token.Answer, ' done')) elif nbr_selected == 1: tokens.append((Token.Answer, ' [%s]' % ic.selected_options[0])) else: tokens.append( (Token.Answer, ' done (%d selections)' % nbr_selected)) else: tokens.append((Token.Instruction, ' (<up>, <down> to move, <space> to select, <a> ' 'to toggle, <i> to invert)')) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens, align_center=False)), ConditionalContainer(Window(ic, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=~IsDone()) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() # event.cli.set_return_value(None) @manager.registry.add_binding(' ', eager=True) def toggle(event): pointed_choice = ic.choices[ic.pointer_index][0] # name if pointed_choice in ic.selected_options: ic.selected_options.remove(pointed_choice) else: ic.selected_options.append(pointed_choice) @manager.registry.add_binding('i', eager=True) def invert(event): inverted_selection = [ c[0] for c in ic.choices if not isinstance(c, Separator) and c[0] not in ic.selected_options ] ic.selected_options = inverted_selection @manager.registry.add_binding('a', eager=True) def all(event): all_selected = True # all choices have been selected for c in ic.choices: if not isinstance(c, Separator) and c[0] not in ic.selected_options: # add missing ones ic.selected_options.append(c[0]) all_selected = False if all_selected: ic.selected_options = [] @manager.registry.add_binding(Keys.Down, eager=True) def move_cursor_down(event): def _next(): ic.pointer_index = ((ic.pointer_index + 1) % ic.line_count) _next() while isinstance(ic.choices[ic.pointer_index], Separator): _next() @manager.registry.add_binding(Keys.Up, eager=True) def move_cursor_up(event): def _prev(): ic.pointer_index = ((ic.pointer_index - 1) % ic.line_count) _prev() while isinstance(ic.choices[ic.pointer_index], Separator): _prev() @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True # TODO use validator event.cli.set_return_value(ic.get_selected_values()) return Application(layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style)
def question(message, **kwargs): # TODO disabled, dict choices if not 'choices' in kwargs: raise PromptParameterException('choices') choices = kwargs.pop('choices', None) default = kwargs.pop('default', 0) # TODO # TODO style defaults on detail level style = kwargs.pop('style', default_style) ic = InquirerControl(choices) def get_prompt_tokens(cli): tokens = [] T = Token tokens.append((Token.QuestionMark, '?')) tokens.append((Token.Question, ' %s ' % message)) if ic.answered: tokens.append((Token.Answer, ' ' + ic.get_selection())) else: tokens.append((Token.Instruction, ' (Use arrow keys)')) return tokens # assemble layout layout = HSplit([ Window(height=D.exact(1), content=TokenListControl(get_prompt_tokens, align_center=False)), ConditionalContainer( Window( ic, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1) ), filter=~IsDone() ) ]) # key bindings manager = KeyBindingManager.for_prompt() @manager.registry.add_binding(Keys.ControlQ, eager=True) @manager.registry.add_binding(Keys.ControlC, eager=True) def _(event): raise KeyboardInterrupt() # event.cli.set_return_value(None) @manager.registry.add_binding(Keys.Down, eager=True) def move_cursor_down(event): def _next(): ic.selected_option_index = ( (ic.selected_option_index + 1) % ic.choice_count) _next() while isinstance(ic.choices[ic.selected_option_index][0], Separator) or\ ic.choices[ic.selected_option_index][1]: _next() @manager.registry.add_binding(Keys.Up, eager=True) def move_cursor_up(event): def _prev(): ic.selected_option_index = ( (ic.selected_option_index - 1) % ic.choice_count) _prev() while isinstance(ic.choices[ic.selected_option_index][0], Separator) or \ ic.choices[ic.selected_option_index][1]: _prev() @manager.registry.add_binding(Keys.Enter, eager=True) def set_answer(event): ic.answered = True event.cli.set_return_value(ic.get_selection()) return Application( layout=layout, key_bindings_registry=manager.registry, mouse_support=True, style=style )
def __init__(self, options: Sequence[Option], default_index: int = 0, header_filter: Callable[[Option], str] = str, match_filter: Callable[[Option], str] = str, custom_filter: Optional[Callable[[str], bool]] = None, search_buffer: Buffer = Buffer(multiline=False), cpu_count: int = os.cpu_count()): self.search_buffer = search_buffer self.last_query_text = '' # type: str self.search_buffer.on_text_changed += self.update self.header_filter = header_filter self.match_filter = match_filter self.current_index = default_index # type: Optional[int] self.entries_left_offset = 0 self.cpu_count = cpu_count self.options_headers_linecount = [] # type: List[int] self._indices_to_lines = [] # type: List[int] self.options_headers = [] # type: FormattedText self.options_matchers = [] # type: List[str] self.indices = [] # type: List[int] self._options = [] # type: Sequence[Option] self.marks = [] # type: List[int] self.max_entry_height = 1 # type: int # options are processed here also through the setter # ################################################## self.set_options(options) self.cursor = Point(0, 0) # type: Point # ################################################## self.content = FormattedTextControl( text=self.get_tokens, focusable=False, key_bindings=None, get_cursor_position=lambda: self.cursor, ) self.content_window = Window( content=self.content, wrap_lines=False, allow_scroll_beyond_bottom=True, scroll_offsets=ScrollOffsets(bottom=self.max_entry_height), cursorline=False, cursorcolumn=False, # right_margins=[NumberedMargin()], # left_margins=[NumberedMargin()], align=WindowAlign.LEFT, height=None, get_line_prefix=self.get_line_prefix # get_line_prefix=lambda line, b: [('bg:red', ' ')] ) self.update() super(OptionsList, self).__init__(content=self.content_window, filter=(custom_filter if custom_filter is not None else has_focus(self.search_buffer)))
def sidebar(name, kvdict): # shamelessly stolen and adapted from ptpython/layout.py _MAX_KEY_WIDTH = 8 _VAL_WIDTH = 14 # sufficient to print "0x" + 12hex chars for a 48bit memory address _CTR_WIDTH = _MAX_KEY_WIDTH + _VAL_WIDTH def center_str(s, w): l = len(s) e = w - l t = '' i = 0 while i < e / 2: t += ' ' i += 1 t += s i = len(t) while i < w: t += ' ' i += 1 return t def pad_or_cut(s, w): if len(s) > w: s = s[:w] while len(s) < w: s += ' ' return s def get_text_fragments(): tokens = [] def append_title(title): @if_mousedown def focus_from_title(mouse_event): get_app().my.set_focus(name) foc = ',focused' if get_app().my.focused_control == name else '' tokens.extend([ ('class:sidebar', ' ', focus_from_title), ('class:sidebar.title' + foc, center_str(title, _CTR_WIDTH), focus_from_title), ('class:sidebar', '\n'), ]) def append(index, label, status, max_key_len): key_len = min(_MAX_KEY_WIDTH, max_key_len) val_len = _CTR_WIDTH - key_len selected = get_app( ).my.controls[name].selected_option_index == index @if_mousedown def select_item(mouse_event): get_app().my.set_focus(name) get_app().my.controls[name].selected_option_index = index @if_mousedown def trigger_vardetail(mouse_event): get_app().my.set_focus(name) get_app().my.controls[name].selected_option_index = index vardetails_toggle_on_off() odd = 'odd' if index % 2 != 0 else '' sel = ',selected' if selected else '' chg = ',changed' if kvdict().was_changed(label) else '' tokens.append(('class:sidebar' + sel, '>' if selected else ' ')) tokens.append(('class:sidebar.label' + odd + sel, pad_or_cut(label, key_len), select_item)) tokens.append(('class:sidebar.status' + odd + sel + chg, pad_or_cut(status, val_len), trigger_vardetail)) if selected: tokens.append(('[SetCursorPosition]', '')) tokens.append(('class:sidebar', '<' if selected else ' ')) tokens.append(('class:sidebar', '\n')) i = 0 append_title(name) mydict = kvdict() if callable(kvdict) else kvdict max_key_len = 0 for key in mydict: max_key_len = max(max_key_len, len(key)) for key in mydict: values = mydict[key] append(i, key, '%s' % values[0], max_key_len + 1) i += 1 tokens.pop() # Remove last newline. i += 1 # title get_app().my.controls[name].height = Dimension(min=2, max=i + 1 if i > 1 else 2) return tokens ctrl = Window(SidebarControl(get_text_fragments), style='class:sidebar', width=Dimension.exact(_CTR_WIDTH + 2), height=Dimension(min=2), scroll_offsets=ScrollOffsets(top=1, bottom=1)) ctrl.selected_option_index = 0 return ctrl
def python_sidebar(python_input: "PythonInput") -> Window: """ Create the `Layout` for the sidebar with the configurable options. """ def get_text_fragments() -> StyleAndTextTuples: tokens: StyleAndTextTuples = [] def append_category(category: "OptionCategory") -> None: tokens.extend([ ("class:sidebar", " "), ("class:sidebar.title", " %-36s" % category.title), ("class:sidebar", "\n"), ]) def append(index: int, label: str, status: str) -> None: selected = index == python_input.selected_option_index @if_mousedown def select_item(mouse_event: MouseEvent) -> None: python_input.selected_option_index = index @if_mousedown def goto_next(mouse_event: MouseEvent) -> None: " Select item and go to next value. " python_input.selected_option_index = index option = python_input.selected_option option.activate_next() sel = ",selected" if selected else "" tokens.append(("class:sidebar" + sel, " >" if selected else " ")) tokens.append( ("class:sidebar.label" + sel, "%-24s" % label, select_item)) tokens.append(("class:sidebar.status" + sel, " ", select_item)) tokens.append( ("class:sidebar.status" + sel, "%s" % status, goto_next)) if selected: tokens.append(("[SetCursorPosition]", "")) tokens.append(("class:sidebar.status" + sel, " " * (13 - len(status)), goto_next)) tokens.append(("class:sidebar", "<" if selected else "")) tokens.append(("class:sidebar", "\n")) i = 0 for category in python_input.options: append_category(category) for option in category.options: append(i, option.title, "%s" % option.get_current_value()) i += 1 tokens.pop() # Remove last newline. return tokens class Control(FormattedTextControl): def move_cursor_down(self): python_input.selected_option_index += 1 def move_cursor_up(self): python_input.selected_option_index -= 1 return Window( Control(get_text_fragments), style="class:sidebar", width=Dimension.exact(43), height=Dimension(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1), )
def __init__(self, history): search_toolbar = SearchToolbar() self.help_buffer_control = BufferControl(buffer=history.help_buffer, lexer=PygmentsLexer(RstLexer)) help_window = _create_popup_window( title="History Help", body=Window( content=self.help_buffer_control, right_margins=[ScrollbarMargin(display_arrows=True)], scroll_offsets=ScrollOffsets(top=2, bottom=2), ), ) self.default_buffer_control = BufferControl( buffer=history.default_buffer, input_processors=[GrayExistingText(history.history_mapping)], lexer=PygmentsLexer(PythonLexer), ) self.history_buffer_control = BufferControl( buffer=history.history_buffer, lexer=PygmentsLexer(PythonLexer), search_buffer_control=search_toolbar.control, preview_search=True, ) history_window = Window( content=self.history_buffer_control, wrap_lines=False, left_margins=[HistoryMargin(history)], scroll_offsets=ScrollOffsets(top=2, bottom=2), ) self.root_container = HSplit([ # Top title bar. Window( content=FormattedTextControl(_get_top_toolbar_fragments), align=WindowAlign.CENTER, style="class:status-toolbar", ), FloatContainer( content=VSplit([ # Left side: history. history_window, # Separator. Window( width=D.exact(1), char=BORDER.LIGHT_VERTICAL, style="class:separator", ), # Right side: result. Window( content=self.default_buffer_control, wrap_lines=False, left_margins=[ResultMargin(history)], scroll_offsets=ScrollOffsets(top=2, bottom=2), ), ]), floats=[ # Help text as a float. Float( width=60, top=3, bottom=2, content=ConditionalContainer( content=help_window, filter=has_focus(history.help_buffer), ), ) ], ), # Bottom toolbars. ArgToolbar(), search_toolbar, Window( content=FormattedTextControl( partial(_get_bottom_toolbar_fragments, history=history)), style="class:status-toolbar", ), ]) self.layout = Layout(self.root_container, history_window)
def question(message, **kwargs): # TODO add bottom-bar (Move up and down to reveal more choices) # TODO extract common parts for list, checkbox, rawlist, expand # TODO validate if not 'choices' in kwargs: raise PromptParameterException('choices') # this does not implement default, use checked... if 'default' in kwargs: raise ValueError('Checkbox does not implement \'default\' ' 'use \'checked\':True\' in choice!') choices = kwargs.pop('choices', None) validator = setup_simple_validator(kwargs) # TODO style defaults on detail level style = kwargs.pop('style', default_style) pointer_index = kwargs.pop('pointer_index', 0) additional_parameters = dict() additional_parameters.update( {"pointer_sign": kwargs.pop('pointer_sign', '\u276f')}) additional_parameters.update( {"selected_sign": kwargs.pop('selected_sign', '\u25cf')}) additional_parameters.update( {"unselected_sign": kwargs.pop('unselected_sign', '\u25cb')}) ic = InquirerControl(choices, pointer_index, **additional_parameters) qmark = kwargs.pop('qmark', '?') def get_prompt_tokens(): tokens = [] tokens.append(('class:questionmark', qmark)) tokens.append(('class:question', ' %s ' % message)) if ic.answered: nbr_selected = len(ic.selected_options) if nbr_selected == 0: tokens.append(('class:answer', ' done')) elif nbr_selected == 1: tokens.append( ('class:Answer', ' [%s]' % ic.selected_options[0])) else: tokens.append( ('class:answer', ' done (%d selections)' % nbr_selected)) else: tokens.append(('class:instruction', ' (<up>, <down> to move, <space> to select, <a> ' 'to toggle, <i> to invert)')) if not ic.answered_correctly: tokens.append((Token.Error, ' Error: %s' % ic.error_message)) return tokens # assemble layout layout = HSplit([ Window( height=D.exact(1), content=FormattedTextControl(get_prompt_tokens), align=WindowAlign.CENTER, ), ConditionalContainer(Window(ic, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets(top=1, bottom=1)), filter=~IsDone()) ]) # key bindings kb = KeyBindings() @kb.add('c-q', eager=True) @kb.add('c-c', eager=True) def _(event): raise KeyboardInterrupt() # event.app.exit(result=None) @kb.add(' ', eager=True) def toggle(event): pointed_choice = ic.choices[ic.pointer_index][1] # value if pointed_choice in ic.selected_options: ic.selected_options.remove(pointed_choice) else: ic.selected_options.append(pointed_choice) @kb.add('i', eager=True) def invert(event): inverted_selection = [ c[1] for c in ic.choices if not isinstance(c, Separator) and c[1] not in ic.selected_options and not c[2] ] ic.selected_options = inverted_selection @kb.add('a', eager=True) def all(event): all_selected = True # all choices have been selected for c in ic.choices: if not isinstance(c, Separator) and c[ 1] not in ic.selected_options and not c[2]: # add missing ones ic.selected_options.append(c[1]) all_selected = False if all_selected: ic.selected_options = [] @kb.add('down', eager=True) def move_cursor_down(event): def _next(): ic.pointer_index = ((ic.pointer_index + 1) % ic.line_count) _next() while isinstance(ic.choices[ic.pointer_index], Separator) or \ ic.choices[ic.pointer_index][2]: _next() @kb.add('up', eager=True) def move_cursor_up(event): def _prev(): ic.pointer_index = ((ic.pointer_index - 1) % ic.line_count) _prev() while isinstance(ic.choices[ic.pointer_index], Separator) or \ ic.choices[ic.pointer_index][2]: _prev() @kb.add('enter', eager=True) def set_answer(event): ic.answered = True # TODO use validator event.app.exit(result=ic.get_selected_values()) return Application(layout=Layout(layout), key_bindings=kb, mouse_support=True, style=style)
def select_issue(choices, pointer_index): controller = IssuesController(message='choose issues', choices=choices, pointer_index=pointer_index) def get_prompt(): prompt = [] prompt.append(('class:qmark', '?')) prompt.append(('class:question', ' %s ' % 'Choose issues:')) return prompt layout = Layout( HSplit([ Window(height=D.exact(1), content=FormattedTextControl(get_prompt(), show_cursor=False)), ConditionalContainer(Window(content=controller, width=D.exact(43), height=D(min=3), scroll_offsets=ScrollOffsets( top=1, bottom=1)), filter=~IsDone()) ])) bindings = KeyBindings() @bindings.add(Keys.ControlQ, eager=True) @bindings.add(Keys.ControlC, eager=True) def exit(event): event.app.exit(result=[]) @bindings.add(' ', eager=True) def toggle(event): controller.toggle(controller.pointer_index) event.app.invalidate() @bindings.add('j', eager=True) @bindings.add(Keys.Down, eager=True) def move_cursor_down(event): def _next(): controller.pointer_index = ((controller.pointer_index + 1) % controller.line_count) event.app.invalidate() _next() while controller.choices[controller.pointer_index][2]: _next() @bindings.add(Keys.Up, eager=True) @bindings.add('k', eager=True) def move_cursor_up(event): def _prev(): controller.pointer_index = ((controller.pointer_index - 1) % controller.line_count) event.app.invalidate() _prev() while controller.choices[controller.pointer_index][2]: _prev() @bindings.add(Keys.Enter, eager=True) def set_answer(event): controller.answered = True event.app.exit(result=controller.selected) style = Style.from_dict({ 'separator': '#6C6C6C', 'qmark': '#FF9D00 bold', 'sel_issue': 'fg:#5Fff9D bg: bold', 'pointer': '#FF9D00 bold', 'answer': '#5F819D bold', 'default': '', }) app = Application( layout=layout, key_bindings=bindings, mouse_support=True, style=style, ) if controller.has_active_choices(): result = app.run() return result else: print_formatted_text(FormattedText(controller.get_formatted_choices()), style=style) return []