class TextEditor(WidgetWrap): """Editor for creating arbitrary text.""" __metaclass__ = signals.MetaSignals signals = ['done'] def __init__(self, prompt, content, done_signal_handler): if content: content += ' ' self.editor = Edit(u'%s (twice enter key to validate or esc) \n>> ' % prompt, content) widgets = [self.editor] w = AttrMap(Columns(widgets), 'editor') connect_signal(self, 'done', done_signal_handler) self.__super.__init__(w) def keypress(self, size, key): if key == 'enter' and self.last_key == 'enter': self.emit_done_signal(self.editor.get_edit_text()) return elif key == 'esc': self.emit_done_signal() return self.last_key = key size = size, self.editor.keypress(size, key) def emit_done_signal(self, content=None): emit_signal(self, 'done', content)
class TextEditor(WidgetWrap): """Editor for creating arbitrary text.""" __metaclass__ = signals.MetaSignals signals = ['done'] def __init__(self, prompt, content, done_signal_handler): if content: content += ' ' self.editor = Edit( u'%s (twice enter key to validate or esc) \n>> ' % prompt, content) widgets = [self.editor] w = AttrMap(Columns(widgets), 'editor') connect_signal(self, 'done', done_signal_handler) self.__super.__init__(w) def keypress(self, size, key): if key == 'enter' and self.last_key == 'enter': self.emit_done_signal(self.editor.get_edit_text()) return elif key == 'esc': self.emit_done_signal() return self.last_key = key size = size, self.editor.keypress(size, key) def emit_done_signal(self, content=None): emit_signal(self, 'done', content)
class NoteEditor(WidgetWrap): __metaclass__ = signals.MetaSignals signals = ['done'] def __init__(self, done_handler, note=None): self.modes = ['title', 'tags', 'text'] self.mode = self.modes[0] self.note = note if note is None: self.title = '' self.tags = '' self.text = '' else: self.title = note.title self.tags = note.formatted_tags() self.text = note.text self.editor = Edit(u'title :: ', self.title) connect_signal(self, 'done', done_handler) WidgetWrap.__init__(self, self.editor) def keypress(self, size, key): if key == 'enter': if self.mode == 'title': self.title = self.editor.get_edit_text() self.init_tags_mode() elif self.mode == 'tags': # Enforce lower case tags for consistency self.tags = self.editor.get_edit_text().lower() self.init_text_mode() elif key == 'esc': self.emit_done() return size = size, self.editor.keypress(size, key) def init_tags_mode(self): self.mode = self.modes[1] self.editor.set_caption('tags :: ') self.editor.set_edit_text(self.tags) def init_text_mode(self): self.mode = self.modes[2] editor = os.environ.get('EDITOR', 'vim') with tempfile.NamedTemporaryFile(prefix="aerende_tmp", suffix=".tmp") as temp: temp.write(self.text.encode('utf-8')) temp.flush() call([editor, temp.name]) temp.seek(0) self.text = temp.read().decode('utf-8').strip() os.system('clear') self.emit_done((self.title, self.tags, self.text)) def emit_done(self, note=None): emit_signal(self, 'done', note, self.note)
class BaseEditor(WidgetWrap): """Base class for editors.""" __metaclass__ = signals.MetaSignals signals = ["done"] def __init__(self, prompt, content, done_signal_handler, cursor_position=None): """ Initializes editor, connects 'done' signal. When pressing 'enter' twice the `submit` method is called, which by default calls `emit_done_signal` with the text that has been introduced. When pressing 'esc' the `cancel` method is called, which by default calls `emit_done_signal` with no arguments. The subclasses must call the `_wrap` method with the editor widgets and `BaseEditor` will wrap it in a `urwid.Colums` widget, calling to `urwid.WidgetWrap.__init__` with the wrapped widget. """ caption = _(u"%s (twice enter key to validate or esc) \n>> ") % prompt if content: content += " " self.content = content self.editor = Edit(caption=caption, edit_text=content, edit_pos=cursor_position) self.last_key = None connect_signal(self, "done", done_signal_handler) def _wrap(self, widgets): widgets = widgets if isinstance(widgets, list) else [widgets] composed_widget = Columns(widgets) widget = AttrMap(LineBox(composed_widget), "editor") WidgetWrap.__init__(self, widget) def keypress(self, size, key): if key == "enter" and self.last_key == "enter": self.submit() return elif key == "esc": self.cancel() return self.last_key = key size = (size,) self.editor.keypress(size, key) def submit(self): self.emit_done_signal(self.editor.get_edit_text()) def cancel(self): self.emit_done_signal() def emit_done_signal(self, content=None): emit_signal(self, "done", content)
def keypress(self, size, key): """ Handle editing keystrokes. Remove leading zeros. >>> e, size = NumEdit("0123456789", u"", "5002"), (10,) >>> e.keypress(size, 'home') >>> e.keypress(size, 'delete') >>> assert e.edit_text == "002" >>> e.keypress(size, 'end') >>> assert e.edit_text == "2" >>> # binary only >>> e, size = NumEdit("01", u"", ""), (10,) >>> assert e.edit_text == "" >>> e.keypress(size, '1') >>> e.keypress(size, '0') >>> e.keypress(size, '1') >>> assert e.edit_text == "101" """ (maxcol, ) = size unhandled = Edit.keypress(self, (maxcol, ), key) if not unhandled: if self.trimLeadingZeros: # trim leading zeros while self.edit_pos > 0 and self.edit_text[:1] == "0": self.set_edit_pos(self.edit_pos - 1) self.set_edit_text(self.edit_text[1:]) return unhandled
class TweetEditor(WidgetWrap): """Editor for creating tweets.""" __metaclass__ = signals.MetaSignals signals = ['done'] def __init__(self, prompt, content, done_signal_handler): if content: content += ' ' self.editor = Edit(u'%s (twice enter key to validate or esc) \n>> ' % prompt, content) self.counter = len(content) self.counter_widget = Text(str(self.counter)) widgets = [('fixed', 4, self.counter_widget), self.editor] w = AttrMap(Columns(widgets), 'editor') connect_signal(self, 'done', done_signal_handler) connect_signal(self.editor, 'change', self.update_counter) self.__super.__init__(w) def update_counter(self, edit, new_edit_text): self.counter = len(new_edit_text) self.counter_widget.set_text(str(self.counter)) def keypress(self, size, key): if key == 'enter' and self.last_key == 'enter': if self.counter > TWEET_MAX_CHARS: return else: self.emit_done_signal(self.editor.get_edit_text()) elif key == 'esc': self.emit_done_signal() return self.last_key = key size = size, self.editor.keypress(size, key) def emit_done_signal(self, content=None): emit_signal(self, 'done', content)
class TweetEditor(WidgetWrap): """Editor for creating tweets.""" __metaclass__ = signals.MetaSignals signals = ['done'] def __init__(self, prompt, content, done_signal_handler): if content: content += ' ' self.editor = Edit( u'%s (twice enter key to validate or esc) \n>> ' % prompt, content) self.counter = len(content) self.counter_widget = Text(str(self.counter)) widgets = [('fixed', 4, self.counter_widget), self.editor] w = AttrMap(Columns(widgets), 'editor') connect_signal(self, 'done', done_signal_handler) connect_signal(self.editor, 'change', self.update_counter) self.__super.__init__(w) def update_counter(self, edit, new_edit_text): self.counter = len(new_edit_text) self.counter_widget.set_text(str(self.counter)) def keypress(self, size, key): if key == 'enter' and self.last_key == 'enter': if self.counter > TWEET_MAX_CHARS: return else: self.emit_done_signal(self.editor.get_edit_text()) elif key == 'esc': self.emit_done_signal() return self.last_key = key size = size, self.editor.keypress(size, key) def emit_done_signal(self, content=None): emit_signal(self, 'done', content)
def keypress(self, size, key): if key == 'enter': self._top[1]() self._done(self.get_edit_text()) elif key == 'esc': self._top[1]() elif key == 'tab' and self._tab: text = self.get_edit_text()[:self.edit_pos] text_len = len(text) match = None for entry in self._tab(text): if entry.startswith(text): entry = entry[text_len:] if match is None: match = entry else: while not entry.startswith(match): match = match[:-1] if match: self.insert_text(match) else: return Edit.keypress(self, size, key)
class BaseEditor(with_metaclass(signals.MetaSignals, WidgetWrap)): """Base class for editors.""" signals = ['done'] def __init__(self, prompt, content, done_signal_handler, cursor_position=None): """ Initializes editor, connects 'done' signal. When pressing 'enter' twice the `submit` method is called, which by default calls `emit_done_signal` with the text that has been introduced. When pressing 'esc' the `cancel` method is called, which by default calls `emit_done_signal` with no arguments. The subclasses must call the `_wrap` method with the editor widgets and `BaseEditor` will wrap it in a `urwid.Colums` widget, calling to `urwid.WidgetWrap.__init__` with the wrapped widget. """ caption = _(u'{0} (Enter key twice to validate, ' u'Esc or Ctrl-C to cancel) \n>> ').format(prompt) if content: content += ' ' self.content = content self.editor = Edit(caption=caption, edit_text=content, edit_pos=cursor_position) self.last_key = None connect_signal(self, 'done', done_signal_handler) def _wrap(self, widgets): widgets = widgets if isinstance(widgets, list) else [widgets] composed_widget = Columns(widgets) widget = AttrMap(LineBox(composed_widget), 'editor') super(BaseEditor, self).__init__(widget) def keypress(self, size, key): if key == 'enter' and self.last_key == 'enter': self.submit() return elif key == 'esc': self.cancel() return self.last_key = key size = size, self.editor.keypress(size, key) def submit(self): self.emit_done_signal(self.editor.get_edit_text()) def cancel(self): self.emit_done_signal() def emit_done_signal(self, content=None): emit_signal(self, 'done', content)
class BaseEditor(WidgetWrap, metaclass=signals.MetaSignals): """Base class for editors.""" signals = ['done'] def __init__(self, prompt, content, done_signal_handler, cursor_position=None): """ Initializes editor, connects 'done' signal. When pressing 'enter' twice the `submit` method is called, which by default calls `emit_done_signal` with the text that has been introduced. When pressing 'esc' the `cancel` method is called, which by default calls `emit_done_signal` with no arguments. The subclasses must call the `_wrap` method with the editor widgets and `BaseEditor` will wrap it in a `urwid.Colums` widget, calling to `urwid.WidgetWrap.__init__` with the wrapped widget. """ caption = _(u'{0} (Enter key twice to validate, ' u'Esc or Ctrl-C to cancel) \n>> ').format(prompt) if content: content += ' ' self.content = content self.editor = Edit(caption=caption, edit_text=content, edit_pos=cursor_position) self.last_key = None connect_signal(self, 'done', done_signal_handler) def _wrap(self, widgets): widgets = widgets if isinstance(widgets, list) else [widgets] composed_widget = Columns(widgets) widget = AttrMap(LineBox(composed_widget), 'editor') super(BaseEditor, self).__init__(widget) def keypress(self, size, key): if key == 'enter' and self.last_key == 'enter': self.submit() return elif key == 'esc': self.cancel() return self.last_key = key size = size, self.editor.keypress(size, key) def submit(self): self.emit_done_signal(self.editor.get_edit_text()) def cancel(self): self.emit_done_signal() def emit_done_signal(self, content=None): emit_signal(self, 'done', content)