Skip to content

Commit

Permalink
Merge pull request #4 from mohitk0208/explorer
Browse files Browse the repository at this point in the history
Explorer: add file mode explorer mode for better user experience
  • Loading branch information
divyanshu-in authored Aug 28, 2020
2 parents 24058a1 + 80d8612 commit ecf3e2f
Show file tree
Hide file tree
Showing 2 changed files with 352 additions and 1 deletion.
42 changes: 42 additions & 0 deletions getch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import os
class _Getch:
"""Gets a single character from standard input. Does not echo to the
screen."""

def __init__(self):
try:
self.impl = _GetchWindows()
except ImportError:
self.impl = _GetchUnix()

def __call__(self): return self.impl()


class _GetchUnix:
def __init__(self):
import tty
import sys

def __call__(self):
import sys
import tty
import termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch


class _GetchWindows:
def __init__(self):
import msvcrt

def __call__(self):
import msvcrt
return msvcrt.getch()

getch = _Getch()
311 changes: 310 additions & 1 deletion script.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
import shutil
import sys

from getch import getch

color = {
"red": "\033[31m", # for errors
Expand All @@ -13,6 +13,312 @@
"cyan": "\033[36m",
"reset": "\033[0m",
}
def rich_text(style=0,text_color=37,background=40):
st = "\033[{style};{text_color};{background}m".format(style=style,text_color=text_color,background=background)
return st



class Interactive_operations:
def __init__(self,files):
self.files = files

def move(self):
if not self.files:
print(color["red"] + "ERROR No file selected")
return None
tomove = self.files
for i in tomove:
path = input("where to move (path/same) >> ")
shutil.move(i, path)

def rename(self):
while True:
if not self.files:
print(color["red"] + "ERROR No file selected" + color["reset"])
return None
print(color["yellow"])
dont_over = (
input("Overwrite prexisting files [y]/n?").strip().lower()
== "n"
)
torename = self.files
for _file in torename:
newname = str(input("Rename '" + _file + "' as>> "))
if dont_over:
if os.path.exists(newname):
if (
input(_file + " already exists overwrite y/[n]?")
.strip()
.lower()
== "y"
):
try:
os.rename(_file, newname)
except IsADirectoryError as e:
print(color["red"] + e + color["yellow"])
except NotADirectoryError as e:
print(color["red"] + e + color["yellow"])

else:
continue
else:
try:
os.rename(_file, newname)
except IsADirectoryError as e:
print(color["red"] + e + color["yellow"])
except NotADirectoryError as e:
print(color["red"] + e + color["yellow"])
break

def delete(self):
while True:
if not self.files:
print(color["red"] + "ERROR No file selected" + color["reset"])
return None

todelete = self.files
print(color["yellow"])
del_confirm = (
input("Ask confirmaton to delete y/[n]?").strip().lower() == "y"
)
deleted = []
for i in todelete:
if os.path.isdir(i):
if del_confirm:
if (
input("Delete directory " + i + " [y]/n?")
.strip()
.lower()
== "n"
):
continue
shutil.rmtree(i, ignore_errors=True)
deleted.append(i)
else:
if del_confirm:
if (
input("Delete file " + i + " [y]/n?")
.strip()
.lower()
== "n"
):
continue
os.remove(i)
deleted.append(i)
break

return deleted

def copy(self):
if not self.files:
print(color["red"] + "ERROR No file selected")
return None
tocopy = self.files
for i in tocopy:
path = str(input("where to copy (path/same) >> "))
shutil.copy(i, path)

@staticmethod
def create():
print(
color["yellow"]
+ "Select 1. to create Directories\n"
+ " 2. to create files\n"
)
ask = int(input(">> "))
index = int(input("How many folders to create>> "))
for i in range(index):
if ask == 1:
os.mkdir(input("Enter name of folder [{}]>> ".format(i + 1)))
elif ask == 2:
fname = input("Enter name of file along with extension>> ")
if not os.path.exists(fname):
with open(fname, "w+"):
pass
else:
print(color["red"] + "ERROR File already exists")




def selection_pointer(isSelected):
temp = rich_text()+"["+(rich_text(1,32,42) if isSelected else rich_text(0,37,40))+"{0}"+rich_text()+"]"
return temp.format("*" if isSelected else " ")



def interactive_show_dirs(path=os.getcwd()):
"""
opens a terminal to use all operations in an interactive way.
Parameters:
path (str): Path of the directory (default = os.getcwd())
"""

filelist = os.listdir(path)
filelist.sort(key=lambda x: x.lower())

scr_width = int(os.get_terminal_size()[0])
try:
mlen = (
max(
len(word) + 1 if os.path.isdir(word) else len(word)
for word in filelist
)
+ 1
)
except ValueError:
mlen = 1
cols = scr_width // mlen

if scr_width < mlen:
mlen = scr_width

selected__files = []
currentIndex = 0

while True:
os.system('cls' if os.name == 'nt' else 'clear')

####################### DISPLAYING FILES ######################
line = ""
lst = []
for _file in filelist:
last = True # last line

# directories(cyan)
if os.path.isdir(path + os.sep + _file):
_fileM = _file + os.sep
st = selection_pointer(_file in selected__files)+ (rich_text(1,35,47) if filelist[currentIndex] == _file else rich_text(0,36,40)) +"{0:<{mlen}}".format(_fileM,mlen=mlen)+rich_text()

if scr_width - (abs(len(line) - cols * 5) % scr_width) > len(st):
line = line + st
else:
lst.append(line)
line = st
last = False

# executeable files(yellow)
elif os.access(path + os.sep + _file, os.X_OK):

st = selection_pointer(_file in selected__files)+(rich_text(1,35,47) if filelist[currentIndex] == _file else rich_text(0,33,40)) + "{0:<{mlen}}".format(_file, mlen=mlen)+rich_text()

if scr_width - (abs(len(line) - cols * 5) % scr_width) > len(st):
line = line+ st
else:
lst.append(line)
line = st
last = False

# other files(green)
else:
st = selection_pointer(_file in selected__files)+(rich_text(1,35,47) if filelist[currentIndex] == _file else rich_text(0,32,40)) + "{0:<{mlen}}".format(_file, mlen=mlen)+rich_text()

if scr_width - (abs(len(line) - cols * 5) % scr_width) > len(st):
line = line+ st
else:
lst.append(line)
line = st
last = False
# append the last line to the list

if last:
lst.append(line)

print("\n".join(lst))
###############################################################

print(color["magenta"],"\nPATH->",color["blue"],path,color["reset"])

if os.name == 'nt':
k = getch().decode('UTF-8').lower()
else:
k = getch().lower()

if k == 'a':
if not currentIndex <= -1:
currentIndex -= 1
else:
currentIndex = len(filelist) -1
if k == 's':
if not currentIndex >= len(filelist)-1:
currentIndex += 1
else:
currentIndex = 0
if k == ' ':
if filelist[currentIndex] in selected__files:
selected__files.remove(filelist[currentIndex])
else:
selected__files.append(filelist[currentIndex])
if k == 'd':
return 'delete',selected__files,path
if k == 'c':
return 'copy',selected__files,path
if k == 'r':
return 'rename',selected__files,path
if k == 'e':
return 'change',filelist[currentIndex],path
if k == 'b':
return 'back',[],path
if k == 'm':
return 'move',selected__files,path
if k == 'w':
return 'make',[],path
if k == 'q':
return 'quit',[],path



def file_explorer():
print(color['magenta'],'welcome to file explorer mode')
print(
"[a] Move backwards",
"[s] Move forwards",
"[ ] 'SPACE' to select or unselect"
"[d] Delete selected files or folders",
"[c] To copy files or folders",
"[m] To move files or folders",
"[r] Rename files or folders",
"[e] Enter a directory",
"[b] Navigate to previous directory",
"[w] Make files/ folders",
"[q] To quit File Explorer mode",
sep="\n"
)
print("Press ANY key to continue...")
getch()
path = os.getcwd()
while True:
o,files,path = interactive_show_dirs(path)
if o == 'delete':
oper_files = Interactive_operations(files)
oper_files.delete()
if o == 'copy':
oper_files = Interactive_operations(files)
oper_files.copy()
if o == 'rename':
oper_files = Interactive_operations(files)
oper_files.rename()
if o == 'change':
path = str(path) + os.sep + files
os.chdir(path)
if o == 'back':
i = str(path).rfind(os.sep)
path = path[0:i]
os.chdir(path)
if o == 'move':
oper_files = Interactive_operations(files)
oper_files.move()
if o == 'make':
oper_files = Interactive_operations.create()
if o == 'quit':
break

print('Have a good day!!')




# TODO: catch permission errors
# TODO: add usage of a global variable to hold the path
Expand Down Expand Up @@ -208,6 +514,7 @@ def select_op():
" 5. Create new folder/s, file/s",
" 6. Enter a directory",
" 7. Enter navigation mode",
" 8. Enter File Explorer Mode",
" 9. Change directory",
"99. EXIT",
sep="\n",
Expand Down Expand Up @@ -434,6 +741,8 @@ def main(path=os.getcwd()):
filelist = os.listdir(path)
filelist.sort(key=lambda x: x.lower())
oper_files = Operations(filelist)
elif oprselection == 8:
file_explorer()
elif oprselection == 9:
directory_ask(True)
show_dirs(os.getcwd())
Expand Down

0 comments on commit ecf3e2f

Please sign in to comment.