Initial commit
This commit is contained in:
54
src/editorUI.py
Normal file
54
src/editorUI.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import urwid
|
||||||
|
from lineWalker import LineWalker
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
class EditorUI(object):
|
||||||
|
|
||||||
|
def __init__(self, filename):
|
||||||
|
|
||||||
|
assert open(filename, "a")
|
||||||
|
|
||||||
|
self.filename = filename
|
||||||
|
|
||||||
|
self.footer = urwid.AttrWrap(urwid.Text("<Alt + s> Save as | <Alt + q> Close"), "standard")
|
||||||
|
|
||||||
|
self.walker = LineWalker(filename)
|
||||||
|
self.content = urwid.ListBox(self.walker)
|
||||||
|
|
||||||
|
self.central_frame = urwid.Frame(self.content)
|
||||||
|
self.central_frame.set_footer(self.footer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main(self):
|
||||||
|
self.palette = [("standard", "light blue", "black"),
|
||||||
|
("warning", "yellow", "black")]
|
||||||
|
self.loop = urwid.MainLoop(self.central_frame, self.palette, unhandled_input = self.keypress_handler)
|
||||||
|
self.loop.run()
|
||||||
|
|
||||||
|
def keypress_handler(self, key):
|
||||||
|
|
||||||
|
if key == "meta q":
|
||||||
|
raise urwid.ExitMainLoop()
|
||||||
|
|
||||||
|
elif key == "meta s":
|
||||||
|
self.save(self.filename)
|
||||||
|
|
||||||
|
|
||||||
|
def save(self, save_filename):
|
||||||
|
walker = self.walker
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
while walker.file is not None:
|
||||||
|
lines.append(walker.read_next_line())
|
||||||
|
|
||||||
|
file_handle = open(save_filename, "w")
|
||||||
|
|
||||||
|
|
||||||
|
prefix = ""
|
||||||
|
for line in lines:
|
||||||
|
file_handle.write(line)
|
||||||
|
prefix = "\n"
|
||||||
101
src/lineWalker.py
Normal file
101
src/lineWalker.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
import urwid
|
||||||
|
|
||||||
|
class LineWalker:
|
||||||
|
"""ListWalker-compatible class for lazily reading file contents."""
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.file = open(name)
|
||||||
|
self.lines = []
|
||||||
|
self.focus = 0
|
||||||
|
|
||||||
|
def get_focus(self):
|
||||||
|
return self._get_at_pos( self.focus )
|
||||||
|
|
||||||
|
def set_focus(self, focus):
|
||||||
|
self.focus = focus
|
||||||
|
|
||||||
|
def get_next(self, start_from):
|
||||||
|
return self._get_at_pos( start_from + 1 )
|
||||||
|
|
||||||
|
def get_prev(self, start_from):
|
||||||
|
return self._get_at_pos( start_from - 1 )
|
||||||
|
|
||||||
|
def read_next_line(self):
|
||||||
|
"""Read another line from the file."""
|
||||||
|
|
||||||
|
next_line = self.file.readline()
|
||||||
|
|
||||||
|
if not next_line or next_line[-1:] != '\n':
|
||||||
|
# no newline on last line of file
|
||||||
|
self.file = None
|
||||||
|
else:
|
||||||
|
# trim newline characters
|
||||||
|
next_line = next_line[:-1]
|
||||||
|
|
||||||
|
expanded = next_line.expandtabs()
|
||||||
|
|
||||||
|
edit = urwid.Edit( "", expanded, allow_tab=True )
|
||||||
|
edit.set_edit_pos(0)
|
||||||
|
edit.original_text = next_line
|
||||||
|
self.lines.append( edit )
|
||||||
|
|
||||||
|
return next_line
|
||||||
|
|
||||||
|
|
||||||
|
def _get_at_pos(self, pos):
|
||||||
|
"""Return a widget for the line number passed."""
|
||||||
|
|
||||||
|
if pos < 0:
|
||||||
|
# line 0 is the start of the file, no more above
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
if len(self.lines) > pos:
|
||||||
|
# we have that line so return it
|
||||||
|
return self.lines[pos], pos
|
||||||
|
|
||||||
|
if self.file is None:
|
||||||
|
# file is closed, so there are no more lines
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
assert pos == len(self.lines), "out of order request?"
|
||||||
|
|
||||||
|
self.read_next_line()
|
||||||
|
|
||||||
|
return self.lines[-1], pos
|
||||||
|
|
||||||
|
def split_focus(self):
|
||||||
|
"""Divide the focus edit widget at the cursor location."""
|
||||||
|
|
||||||
|
focus = self.lines[self.focus]
|
||||||
|
pos = focus.edit_pos
|
||||||
|
edit = urwid.Edit("",focus.edit_text[pos:], allow_tab=True )
|
||||||
|
edit.original_text = ""
|
||||||
|
focus.set_edit_text( focus.edit_text[:pos] )
|
||||||
|
edit.set_edit_pos(0)
|
||||||
|
self.lines.insert( self.focus+1, edit )
|
||||||
|
|
||||||
|
def combine_focus_with_prev(self):
|
||||||
|
"""Combine the focus edit widget with the one above."""
|
||||||
|
|
||||||
|
above, ignore = self.get_prev(self.focus)
|
||||||
|
if above is None:
|
||||||
|
# already at the top
|
||||||
|
return
|
||||||
|
|
||||||
|
focus = self.lines[self.focus]
|
||||||
|
above.set_edit_pos(len(above.edit_text))
|
||||||
|
above.set_edit_text( above.edit_text + focus.edit_text )
|
||||||
|
del self.lines[self.focus]
|
||||||
|
self.focus -= 1
|
||||||
|
|
||||||
|
def combine_focus_with_next(self):
|
||||||
|
"""Combine the focus edit widget with the one below."""
|
||||||
|
|
||||||
|
below, ignore = self.get_next(self.focus)
|
||||||
|
if below is None:
|
||||||
|
# already at bottom
|
||||||
|
return
|
||||||
|
|
||||||
|
focus = self.lines[self.focus]
|
||||||
|
focus.set_edit_text( focus.edit_text + below.edit_text )
|
||||||
|
del self.lines[self.focus+1]
|
||||||
7
src/main.py
Executable file
7
src/main.py
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import editorUI
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
ui=editorUI.EditorUI(str(uuid4()) + ".txt")
|
||||||
|
ui.main()
|
||||||
Reference in New Issue
Block a user