#! /Library/Frameworks/Python.framework/Versions/2.6/bin/python
import curses
import sys
import os
import time
from curses import panel
from curses.wrapper import wrapper
class Container:
pass
def drawbottom(mainwind, width, height, status):
mainwind.move(height-2, 1)
mainwind.clrtoeol()
mainwind.addch(height-2, width-1, curses.ACS_VLINE)
mainwind.move(height-2, 1)
mainwind.addstr(status)
mainwind.refresh()
def setupdir(mainwind, infowind, width, height, currdir):
global d
mainwind.move(1, 1)
mainwind.clrtoeol()
mainwind.addch(1, width-1, curses.ACS_VLINE)
mainwind.move(1, 1)
mainwind.addstr("Path: " + currdir)
mainwind.touchwin()
mainwind.noutrefresh()
d.l = os.listdir(currdir) #list of the current dir
if len(d.l) == 0:
d.l.append("<EMPTY>")
d.i = {} #file info
d.p = curses.newpad(len(d.l), width-3)
d.selected = 0
d.oldselected = 0
d.scroll = 0
d.bar = 0
#d.oldbar = 0
idx = 0
for x in d.l[:]:
if x[0] == "." and d.invisible:
d.l.remove(x)
continue
d.p.move(idx, 0)
if os.path.isdir(x):
d.i[x] = 1
d.p.addstr(x, curses.color_pair(1))
else:
d.i[x] = 0
d.p.addstr(x)
idx = idx + 1
length = len(d.l)
if length == 0:
d.l.append("<EMPTY>")
d.i["<EMPTY>"] = 0
if d.l[0] == "<EMPTY>" and len(d.l) == 1:
length = 0
s = str(length) + " file"
if length != 1:
s = s + "s"
mainwind.addstr(1, width-2-len(s), s)
mainwind.addch(3, width-2, curses.ACS_UARROW)
mainwind.addch(height-4, width-2, curses.ACS_DARROW)
for x in range(4, height-4):
mainwind.addch(x, width-2, curses.ACS_VLINE)
drawdir(mainwind, infowind, width, height)
def drawdir(mainwind, infowind, width, height):
global d
d.p.move(d.oldselected, 0)
if d.i[d.l[d.oldselected]] == 1:
d.p.addstr(d.l[d.oldselected], curses.color_pair(1))
else:
d.p.addstr(d.l[d.oldselected])
d.p.move(d.selected, 0)
d.p.addstr(d.l[d.selected], curses.A_REVERSE)
d.p.noutrefresh(d.scroll, 0, 3, 1, height-4, width-2)
mainwind.addch(d.bar+4, width-2, curses.ACS_VLINE)
try:
d.bar = int((d.selected*1.0/(len(d.l)-1))*(height-9))
except:
d.bar = 0
#raise Exception(d.bar, d.selected, height-8, len(d.l)-1, (d.selected*1.0/(len(d.l)-1)))
mainwind.addch(d.bar+4, width-2, " ", curses.A_REVERSE)
mainwind.noutrefresh()
if d.info:
infowind.erase()
infowind.box()
infowind.hline(2, 0, curses.ACS_HLINE, 50)
infowind.addch(2, 0, curses.ACS_LTEE)
infowind.addch(2, 49, curses.ACS_RTEE)
fname = d.l[d.selected]
if len(fname) > 42:
fname = fname[:-(len(fname)-42+3)] + "..."
infowind.addstr(1, 1, "File: " + fname)
statcall = os.stat(d.l[d.selected])
size = statcall.st_size
suffixes = ["B", "KB", "MB", "GB", "TB"]
for suffix in suffixes:
if size > 1024:
size /= 1024
else:
break
infowind.addstr(3, 1, "File size: " + str(size) + suffix + " (" + str(statcall.st_size) + " bytes)")
permslist = ["x", "w", "r"]
tlist = range(9)
tlist.reverse()
if os.path.isdir(d.l[d.selected]):
permstr = "d"
else:
permstr = "-"
for num in tlist:
if statcall.st_mode & (1 << num) > 0:
permstr = permstr + permslist[num%3]
else:
permstr = permstr + "-"
infowind.addstr(4, 1, "Permissions: " + permstr)
infowind.addstr(5, 1, time.strftime("Last modification: %c", time.localtime(statcall.st_mtime)))
infowind.noutrefresh()
curses.doupdate()
def main(mw):
global d
mainwind = mw
mainwind.addstr("Initializing...")
mainwind.refresh()
curses.init_pair(1, curses.COLOR_RED, curses.COLOR_BLACK)
mainwind.erase()
height, width = mainwind.getmaxyx()
if height < 24 or width < 110:
return 1
currdir = os.getcwd()
#set up pretty view
mainwind.box()
mainwind.hline(2, 0, curses.ACS_HLINE, width)
mainwind.addch(2, 0, curses.ACS_LTEE)
mainwind.addch(2, width-1, curses.ACS_RTEE)
mainwind.hline(height-3, 0, curses.ACS_HLINE, width)
mainwind.addch(height-3, 0, curses.ACS_LTEE)
mainwind.addch(height-3, width-1, curses.ACS_RTEE)
mainwind.move(height-2, 1)
mainwind.addstr("Commands: q: quit, c: chdir, u: up, s: show/hide info window, i: show/hide invisible files, d: delete file")
infowind = curses.newwin(10, 50, 5, width-54)
d.info = False
d.invisible = True
setupdir(mainwind, infowind, width, height, currdir)
dirty = False
while True:
mainwind.move(0, 0)
c = mainwind.getch()
if dirty == True:
drawbottom(mainwind, width, height, "Commands: q: quit, c: chdir, u: up, s: show/hide info window, i: show/hide invisible files, d: delete file")
dirty = False
if c >= 0 and c < 256:
c = chr(c)
if c == "q":
return
elif c == curses.KEY_UP:
if d.selected > 0:
d.oldselected = d.selected
d.selected = d.selected - 1
if d.selected < d.scroll:
d.scroll -= (height-6)/2
drawdir(mainwind, infowind, width, height)
elif c == curses.KEY_DOWN:
if d.selected < len(d.l)-1:
d.oldselected = d.selected
d.selected = d.selected + 1
if d.selected > d.scroll + height - 6:
d.scroll += (height-6)/2
if d.scroll > len(d.l)-height+6:
d.scroll = len(d.l)-height+6
drawdir(mainwind, infowind, width, height)
elif c == "u":
try:
os.chdir("..")
except OSError as e:
drawbottom(mainwind, width, height, "CHDir error: " + e[1] + " (" + str(e[0]) + ")")
dirty = True
continue
currdir = os.getcwd()
setupdir(mainwind, infowind, width, height, currdir)
elif c == "c":
if d.i[d.l[d.selected]] != 1:
drawbottom(mainwind, width, height, "Error: Not a directory!")
dirty = True
else:
try:
os.chdir(d.l[d.selected])
except OSError as e:
drawbottom(mainwind, width, height, "CHDir error: " + e[1] + " (" + str(e[0]) + ")")
dirty = True
continue
currdir = os.getcwd()
setupdir(mainwind, infowind, width, height, currdir)
elif c == "s":
if d.info == True:
d.info = False
mainwind.touchwin()
mainwind.refresh()
drawdir(mainwind, infowind, width, height)
else:
d.info = True
drawdir(mainwind, infowind, width, height)
elif c == "i":
d.invisible = not d.invisible
setupdir(mainwind, infowind, width, height, currdir)
elif c == "d":
dirty = True
if d.i[d.l[d.selected]] != 0:
drawbottom(mainwind, width, height, "Error: Not a file!")
continue
drawbottom(mainwind, width, height, "Are you sure? ")
yn = mainwind.getch()
if yn != ord("y"):
drawbottom(mainwind, width, height, "File deletion aborted!")
continue
try:
os.unlink(d.l[d.selected])
setupdir(mainwind, infowind, width, height, currdir)
drawbottom(mainwind, width, height, "File deleted successfully!")
except OSError as e:
drawbottom(mainwind, width, height, "Deletion error: " + e[1] + " (" + str(e[0]) + ")")
d = Container()
r = wrapper(main)
if r == 1:
print "Your terminal isn't big enough! It needs to be at least 110x24."