diff --git a/hgext3rd/interactiveui.py b/hgext3rd/interactiveui.py new file mode 100644 --- /dev/null +++ b/hgext3rd/interactiveui.py @@ -0,0 +1,82 @@ +# interactiveui.py: display information and allow for left/right control +# +# Copyright 2017 Facebook, Inc. +# +# This software may be used and distributed according to the terms of the +# GNU General Public License version 2 or any later version. + +import os +import sys +import termios +import tty + +def clearline(): + w = sys.stdout + # ANSI + # ESC[#A : up # lines + # ESC[K : clear to end of line + w.write('\033[1A\033[K') + w.flush() + +def getchar(fd): + # from: + # https://github.com/pallets/click/blob/master/click/_termui_impl.py#L534 + if not os.isatty(fd): + # TODO: figure out tests + return None + try: + attr = termios.tcgetattr(fd) + try: + tty.setraw(fd) + ch = os.read(fd, 32) + finally: + termios.tcsetattr(fd, termios.TCSADRAIN, attr) + except termios.error: + pass + if ch == '\x03': + raise KeyboardInterrupt() + if ch == '\x04': + raise EOFError() + return ch + +class viewframe(object): + # framework for view + def __init__(self, ui, repo, index): + self.ui = ui + self.repo = repo + self.index = index + def render(): + # returns string to print + pass + def enter(): + # handle user keypress return + pass + def leftarrow(): + # handle user keypress left arrow + pass + def rightarrow(): + # handle user keypress right arrow + pass + +def view(viewobj): + done = False + s = viewobj.render() + print(s) + while not done: + output = getchar(sys.stdin.fileno()) + if str(repr(output)) == '\'q\'': + done = True + break + if str(repr(output)) == '\'\\r\'': + # \r = return + viewobj.enter() + done = True + break + if str(repr(output)) == '\'\\x1b[C\'': + viewobj.rightarrow() + if str(repr(output)) == '\'\\x1b[D\'': + viewobj.leftarrow() + for i in range(len(s.split("\n"))): + clearline() + s = viewobj.render() + print(s) diff --git a/hgext3rd/undo.py b/hgext3rd/undo.py --- a/hgext3rd/undo.py +++ b/hgext3rd/undo.py @@ -572,7 +572,34 @@ branch = branch) if preview: - _preview(ui, repo, reverseindex) + try: + interactiveui = extensions.find('interactiveui') + except KeyError: + _preview(ui, repo, reverseindex) + return + + class undopreview(interactiveui.viewframe): + def init(self, repo, ui, index): + self.repo = repo + self.ui = ui + self.index = index + def render(self): + ui = self.ui + ui.pushbuffer() + _preview(ui, self.repo, self.index) + return ui.popbuffer() + def rightarrow(self): + self.index += 1 + def leftarrow(self): + self.index -= 1 + def enter(self): + del opts["preview"] + opts["absolute"] = "absolute" + opts["index"] = self.index + undo(ui, repo, *args, **opts) + return + viewobj = undopreview(ui, repo, reverseindex) + interactiveui.view(viewobj) return with repo.wlock(), repo.lock(), repo.transaction("undo"):