Skip to content

Instantly share code, notes, and snippets.

@secemp9
Last active July 2, 2021 09:49
Show Gist options
  • Save secemp9/ffa7e8eb7704dadc690e7732ec05505e to your computer and use it in GitHub Desktop.
Save secemp9/ffa7e8eb7704dadc690e7732ec05505e to your computer and use it in GitHub Desktop.
Text editor used as Text viewer (Prototype 0)
import sys
import curses
import io
import locale
import os
import binascii
class Editor:
def __init__(self, win, file_name):
self.win = win
self.file_name = file_name
self.cur_x, self.cur_y = 0, 0 # cursor position
self.win_x, self.win_y = 0, 0 # window top left position
self.bar_msg = f'{self.cur_x}, {self.cur_y}'
self.read_file()
self.screen = curses.initscr()
def guess_encoding(self, file_name):
csv_file = file_name
with io.open(csv_file, "rb") as f:
self.data = f.read(5)
if self.data.startswith(b"\xEF\xBB\xBF"): # UTF-8 with a "BOM"
return "utf-8-sig"
elif self.data.startswith(b"\xFF\xFE") or self.data.startswith(b"\xFE\xFF"):
return "utf-16"
else: # in Windows, guessing utf-8 doesn't work, so we have to try
try:
with io.open(csv_file, encoding="utf-8") as f:
self.preview = f.read(222222)
return "utf-8"
except:
return locale.getdefaultlocale()[1]
def read_file(self):
with open(self.file_name, 'rb') as f:
f.seek(-1, os.SEEK_END)
self.last_char = f.read(1)
if bytes.hex(self.last_char) == '0a':
with open(self.file_name, 'a+', encoding=self.guess_encoding(self.file_name)) as f:
f.seek(0)
self.buff = f.readlines()
if not self.buff:
self.buff.append('\n')
else:
self.chunk_size = 1024
with open(self.file_name, 'rb') as f:
while True:
self.data = f.read(self.chunk_size)
if not self.data:
break
self.buff = binascii.hexlify(self.data)
self.buff = self.buff.decode('ascii')
def draw(self):
def show_bar():
msg = self.bar_msg[:self.win_w-1]
self.win.addstr(self.win_h - 1, 0, msg)
def show_text():
for i in range(self.win_x, min(len(self.buff), self.win_x + self.win_h - 1)):
line = self.buff[i]
line = line[self.win_y : self.win_y + self.win_w]
self.win.addstr(line if line else '\n')
def update_cursor_position():
self.win.move(self.cur_x - self.win_x, self.cur_y - self.win_y)
def update_window_position():
self.win_h, self.win_w = self.win.getmaxyx() # window height, width
if self.cur_x < self.win_x:
self.win_x = self.cur_x
if self.cur_y < self.win_y:
self.win_y = self.cur_y
if self.cur_x > self.win_x + self.win_h - 2:
self.win_x = self.cur_x - self.win_h + 2
if self.cur_y > self.win_x + self.win_w- 2:
self.win_y = self.cur_y - self.win_w + 2
self.win.erase()
update_window_position()
show_text()
show_bar()
update_cursor_position()
def read_key(self):
def move_up():
self.cur_x = max(self.cur_x - 1, 0)
self.cur_y = min(self.cur_y, len(self.buff[self.cur_x]) - 1)
def move_down():
self.cur_x = min(self.cur_x + 1, len(self.buff) - 1)
self.cur_y = min(self.cur_y, len(self.buff[self.cur_x]) - 1)
def move_left():
self.cur_y = max(self.cur_y - 1, 0)
def move_right():
self.cur_y = min(self.cur_y + 1, len(self.buff[self.cur_x]) - 1)
key = self.win.getch()
if key == curses.KEY_UP:
move_up()
elif key == curses.KEY_DOWN:
move_down()
elif key == curses.KEY_LEFT:
move_left()
elif key == curses.KEY_RIGHT:
move_right()
elif key == ord('q'):
raise SystemExit
def run(self):
self.draw()
while True:
self.bar_msg = f'{self.cur_x}, {self.cur_y}'
self.read_key()
self.draw()
def main(win):
editor = Editor(win, sys.argv[1])
editor.run()
curses.wrapper(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment