diff options
author | 2020-08-03 14:33:06 +0000 | |
---|---|---|
committer | 2020-08-03 14:33:06 +0000 | |
commit | 061da546b983eb767bad15e67af1174fb0bcf31c (patch) | |
tree | 83c78b820819d70aa40c36d90447978b300078c5 /gnu/llvm/lldb/utils/lui/cui.py | |
parent | Import LLVM 10.0.0 release including clang, lld and lldb. (diff) | |
download | wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.tar.xz wireguard-openbsd-061da546b983eb767bad15e67af1174fb0bcf31c.zip |
Import LLVM 10.0.0 release including clang, lld and lldb.
ok hackroom
tested by plenty
Diffstat (limited to 'gnu/llvm/lldb/utils/lui/cui.py')
-rwxr-xr-x | gnu/llvm/lldb/utils/lui/cui.py | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/gnu/llvm/lldb/utils/lui/cui.py b/gnu/llvm/lldb/utils/lui/cui.py new file mode 100755 index 00000000000..fffb812fbb9 --- /dev/null +++ b/gnu/llvm/lldb/utils/lui/cui.py @@ -0,0 +1,338 @@ +##===-- cui.py -----------------------------------------------*- Python -*-===## +## +# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +# See https://llvm.org/LICENSE.txt for license information. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +## +##===----------------------------------------------------------------------===## + +import curses +import curses.ascii +import threading + + +class CursesWin(object): + + def __init__(self, x, y, w, h): + self.win = curses.newwin(h, w, y, x) + self.focus = False + + def setFocus(self, focus): + self.focus = focus + + def getFocus(self): + return self.focus + + def canFocus(self): + return True + + def handleEvent(self, event): + return + + def draw(self): + return + + +class TextWin(CursesWin): + + def __init__(self, x, y, w): + super(TextWin, self).__init__(x, y, w, 1) + self.win.bkgd(curses.color_pair(1)) + self.text = '' + self.reverse = False + + def canFocus(self): + return False + + def draw(self): + w = self.win.getmaxyx()[1] + text = self.text + if len(text) > w: + #trunc_length = len(text) - w + text = text[-w + 1:] + if self.reverse: + self.win.addstr(0, 0, text, curses.A_REVERSE) + else: + self.win.addstr(0, 0, text) + self.win.noutrefresh() + + def setReverse(self, reverse): + self.reverse = reverse + + def setText(self, text): + self.text = text + + +class TitledWin(CursesWin): + + def __init__(self, x, y, w, h, title): + super(TitledWin, self).__init__(x, y + 1, w, h - 1) + self.title = title + self.title_win = TextWin(x, y, w) + self.title_win.setText(title) + self.draw() + + def setTitle(self, title): + self.title_win.setText(title) + + def draw(self): + self.title_win.setReverse(self.getFocus()) + self.title_win.draw() + self.win.noutrefresh() + + +class ListWin(CursesWin): + + def __init__(self, x, y, w, h): + super(ListWin, self).__init__(x, y, w, h) + self.items = [] + self.selected = 0 + self.first_drawn = 0 + self.win.leaveok(True) + + def draw(self): + if len(self.items) == 0: + self.win.erase() + return + + h, w = self.win.getmaxyx() + + allLines = [] + firstSelected = -1 + lastSelected = -1 + for i, item in enumerate(self.items): + lines = self.items[i].split('\n') + lines = lines if lines[len(lines) - 1] != '' else lines[:-1] + if len(lines) == 0: + lines = [''] + + if i == self.getSelected(): + firstSelected = len(allLines) + allLines.extend(lines) + if i == self.selected: + lastSelected = len(allLines) - 1 + + if firstSelected < self.first_drawn: + self.first_drawn = firstSelected + elif lastSelected >= self.first_drawn + h: + self.first_drawn = lastSelected - h + 1 + + self.win.erase() + + begin = self.first_drawn + end = begin + h + + y = 0 + for i, line in list(enumerate(allLines))[begin:end]: + attr = curses.A_NORMAL + if i >= firstSelected and i <= lastSelected: + attr = curses.A_REVERSE + line = '{0:{width}}'.format(line, width=w - 1) + + # Ignore the error we get from drawing over the bottom-right char. + try: + self.win.addstr(y, 0, line[:w], attr) + except curses.error: + pass + y += 1 + self.win.noutrefresh() + + def getSelected(self): + if self.items: + return self.selected + return -1 + + def setSelected(self, selected): + self.selected = selected + if self.selected < 0: + self.selected = 0 + elif self.selected >= len(self.items): + self.selected = len(self.items) - 1 + + def handleEvent(self, event): + if isinstance(event, int): + if len(self.items) > 0: + if event == curses.KEY_UP: + self.setSelected(self.selected - 1) + if event == curses.KEY_DOWN: + self.setSelected(self.selected + 1) + if event == curses.ascii.NL: + self.handleSelect(self.selected) + + def addItem(self, item): + self.items.append(item) + + def clearItems(self): + self.items = [] + + def handleSelect(self, index): + return + + +class InputHandler(threading.Thread): + + def __init__(self, screen, queue): + super(InputHandler, self).__init__() + self.screen = screen + self.queue = queue + + def run(self): + while True: + c = self.screen.getch() + self.queue.put(c) + + +class CursesUI(object): + """ Responsible for updating the console UI with curses. """ + + def __init__(self, screen, event_queue): + self.screen = screen + self.event_queue = event_queue + + curses.start_color() + curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE) + curses.init_pair(2, curses.COLOR_YELLOW, curses.COLOR_BLACK) + curses.init_pair(3, curses.COLOR_RED, curses.COLOR_BLACK) + self.screen.bkgd(curses.color_pair(1)) + self.screen.clear() + + self.input_handler = InputHandler(self.screen, self.event_queue) + self.input_handler.daemon = True + + self.focus = 0 + + self.screen.refresh() + + def focusNext(self): + self.wins[self.focus].setFocus(False) + old = self.focus + while True: + self.focus += 1 + if self.focus >= len(self.wins): + self.focus = 0 + if self.wins[self.focus].canFocus(): + break + self.wins[self.focus].setFocus(True) + + def handleEvent(self, event): + if isinstance(event, int): + if event == curses.KEY_F3: + self.focusNext() + + def eventLoop(self): + + self.input_handler.start() + self.wins[self.focus].setFocus(True) + + while True: + self.screen.noutrefresh() + + for i, win in enumerate(self.wins): + if i != self.focus: + win.draw() + # Draw the focused window last so that the cursor shows up. + if self.wins: + self.wins[self.focus].draw() + curses.doupdate() # redraw the physical screen + + event = self.event_queue.get() + + for win in self.wins: + if isinstance(event, int): + if win.getFocus() or not win.canFocus(): + win.handleEvent(event) + else: + win.handleEvent(event) + self.handleEvent(event) + + +class CursesEditLine(object): + """ Embed an 'editline'-compatible prompt inside a CursesWin. """ + + def __init__(self, win, history, enterCallback, tabCompleteCallback): + self.win = win + self.history = history + self.enterCallback = enterCallback + self.tabCompleteCallback = tabCompleteCallback + + self.prompt = '' + self.content = '' + self.index = 0 + self.startx = -1 + self.starty = -1 + + def draw(self, prompt=None): + if not prompt: + prompt = self.prompt + (h, w) = self.win.getmaxyx() + if (len(prompt) + len(self.content)) / w + self.starty >= h - 1: + self.win.scroll(1) + self.starty -= 1 + if self.starty < 0: + raise RuntimeError('Input too long; aborting') + (y, x) = (self.starty, self.startx) + + self.win.move(y, x) + self.win.clrtobot() + self.win.addstr(y, x, prompt) + remain = self.content + self.win.addstr(remain[:w - len(prompt)]) + remain = remain[w - len(prompt):] + while remain != '': + y += 1 + self.win.addstr(y, 0, remain[:w]) + remain = remain[w:] + + length = self.index + len(prompt) + self.win.move(self.starty + length / w, length % w) + + def showPrompt(self, y, x, prompt=None): + self.content = '' + self.index = 0 + self.startx = x + self.starty = y + self.draw(prompt) + + def handleEvent(self, event): + if not isinstance(event, int): + return # not handled + key = event + + if self.startx == -1: + raise RuntimeError('Trying to handle input without prompt') + + if key == curses.ascii.NL: + self.enterCallback(self.content) + elif key == curses.ascii.TAB: + self.tabCompleteCallback(self.content) + elif curses.ascii.isprint(key): + self.content = self.content[:self.index] + \ + chr(key) + self.content[self.index:] + self.index += 1 + elif key == curses.KEY_BACKSPACE or key == curses.ascii.BS: + if self.index > 0: + self.index -= 1 + self.content = self.content[ + :self.index] + self.content[self.index + 1:] + elif key == curses.KEY_DC or key == curses.ascii.DEL or key == curses.ascii.EOT: + self.content = self.content[ + :self.index] + self.content[self.index + 1:] + elif key == curses.ascii.VT: # CTRL-K + self.content = self.content[:self.index] + elif key == curses.KEY_LEFT or key == curses.ascii.STX: # left or CTRL-B + if self.index > 0: + self.index -= 1 + elif key == curses.KEY_RIGHT or key == curses.ascii.ACK: # right or CTRL-F + if self.index < len(self.content): + self.index += 1 + elif key == curses.ascii.SOH: # CTRL-A + self.index = 0 + elif key == curses.ascii.ENQ: # CTRL-E + self.index = len(self.content) + elif key == curses.KEY_UP or key == curses.ascii.DLE: # up or CTRL-P + self.content = self.history.previous(self.content) + self.index = len(self.content) + elif key == curses.KEY_DOWN or key == curses.ascii.SO: # down or CTRL-N + self.content = self.history.next() + self.index = len(self.content) + self.draw() |