diff options
Diffstat (limited to 'lldb/utils/lui/cui.py')
-rwxr-xr-x | lldb/utils/lui/cui.py | 589 |
1 files changed, 304 insertions, 285 deletions
diff --git a/lldb/utils/lui/cui.py b/lldb/utils/lui/cui.py index e82f0ab..963606a 100755 --- a/lldb/utils/lui/cui.py +++ b/lldb/utils/lui/cui.py @@ -1,9 +1,9 @@ ##===-- cui.py -----------------------------------------------*- Python -*-===## ## -## The LLVM Compiler Infrastructure +# The LLVM Compiler Infrastructure ## -## This file is distributed under the University of Illinois Open Source -## License. See LICENSE.TXT for details. +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. ## ##===----------------------------------------------------------------------===## @@ -11,310 +11,329 @@ 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 + + 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 + + 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 __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() - 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 + + 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) + 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) + """ Responsible for updating the console UI with curses. """ - def handleEvent(self, event): - if isinstance(event, int): - if event == curses.KEY_F3: - self.focusNext() + def __init__(self, screen, event_queue): + self.screen = screen + self.event_queue = event_queue - def eventLoop(self): + 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.start() - self.wins[self.focus].setFocus(True) + self.input_handler = InputHandler(self.screen, self.event_queue) + self.input_handler.daemon = True - while True: - self.screen.noutrefresh() + self.focus = 0 - 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 + self.screen.refresh() - event = self.event_queue.get() + 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) - for win in self.wins: + def handleEvent(self, event): if isinstance(event, int): - if win.getFocus() or not win.canFocus(): - win.handleEvent(event) - else: - win.handleEvent(event) - self.handleEvent(event) + 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() + """ 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() |