just formatted code better..

This commit is contained in:
q
2019-01-03 21:22:14 +02:00
parent a98f3e875d
commit 17603445ca

View File

@@ -44,27 +44,28 @@ def setup_options():
parser.add_argument("--version",action='version', version=VERSION) parser.add_argument("--version",action='version', version=VERSION)
parser.add_argument("args",type=str,action="store",default="",nargs="?", parser.add_argument("args",type=str,action="store",default="",nargs="?",
help="Arguments for the command, if -c used. The string will be re-parsed with shutils. Use '--' to skip local parsing.") help="Arguments for the command, if -c used. The string will be re-parsed with shutils. Use '--' to skip local parsing.")
options=parser.parse_args()
options = parser.parse_args()
if not os.path.exists(DEFAULTFILE): if not os.path.exists(DEFAULTFILE):
options.defaults=False options.defaults = False
return options return options
def termsize(): def termsize():
rows, columns = os.popen('stty size', 'r').read().split() rows, columns = os.popen('stty size', 'r').read().split()
return (int(rows),int(columns)) return (int(rows), int(columns))
def ichr(i): def ichr(i):
''' convert integer to 1-9, a-z, A-Z, omitting q,x ''' ''' convert integer to 1-9, a-z, A-Z, omitting q,x '''
if i < 10: if i < 10:
return str(i) return str(i)
i=i + 87 i += 87
if i>112: if i > 112:
i=i+1 i += 1
if i>119: if i > 119:
i=i+1 i += 1
if i>122: if i > 122:
i=i-122+64 i += 64 - 122
return chr(i) return chr(i)
class bc: class bc:
@@ -89,10 +90,11 @@ class bc:
self.END = '' self.END = ''
def pos(self,y,x): def pos(self,y,x):
return "\033["+str(y)+";"+str(x)+"H" return "\033[%s;%sH"%( y, x )
def posprint(self, y, x, s):
sys.stdout.write( self.pos(y, x) + str(s) )
def posprint(self, y,x,s):
sys.stdout.write( self.pos(y,x) + str(s) )
class getch: class getch:
def __init__(self): def __init__(self):
@@ -109,210 +111,272 @@ class getch:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch return ch
class launch_item: class launch_item:
''' Class for launchable items ''' ''' Class for launchable items '''
description='' def __init__(self, command, description, launcher):
command='' self.command = command
launcher='' self.description = description
def __init__(self,command,description,launcher): self.launcher = launcher
self.command=command
self.description=description
self.launcher=launcher
class entry_collection: class entry_collection:
''' Object containing the list items, and the printing methods ''' ''' Object containing the list items, and the printing methods '''
options=[]
entries=[]
dirs=[]
banner=[]
menu_keys=[ichr(i+1) for i in range(60)]
args=''
dir_mode=False
co=bc()
max_length=0
def __init__(self, options): def __init__(self, options):
self.options=options self.options = options
self.menu_keys=[ichr(i+1) for i in range(60)]
self.args = ''
self.co = bc()
self.dir_mode = False
self.max_length = 0
self.initialize() self.initialize()
if not self.options.colors: if not self.options.colors:
self.co.disable() self.co.disable()
def initialize(self): def initialize(self):
self.entries=[] self.entries = []
self.dirs=[] self.dirs = []
self.banner=[] self.banner = []
if self.options.defaults: if self.options.defaults:
self.read_menu(DEFAULTFILE) self.read_menu(DEFAULTFILE)
self.read_menu() self.read_menu()
self.read_folder() self.read_folder()
self.entries=self.entries[0:60] self.entries = self.entries[0:60]
self.dirs=self.dirs[0:60] self.dirs = self.dirs[0:60]
if len(self.entries)>0: if len(self.entries) > 0:
self.max_length=max([len(e.description) for e in self.entries])+1 self.max_length = max([len(e.description) for e in self.entries]) + 1
def set_args(self,args): def set_args(self, args):
self.args=args; self.args = args
def read_menu(self,menu_file=MENUFILE): def read_menu(self, menu_file = MENUFILE):
''' Read the menu file ''' ''' Read the menu file '''
if os.path.exists(menu_file): if os.path.exists(menu_file):
f=file(menu_file,'r') with open(menu_file, 'rt') as f:
for row in f: for row in f:
if row.strip()=='': if row.strip() == '':
continue continue
if row[0:2]=='##': if row[0:2] == '##':
self.banner.append(row[2:].replace("\n","").replace("\r","")) self.banner.append(
continue row[2:].replace("\n","").replace("\r","")
if row[0]=='#': )
continue continue
row=row.strip().split(':',1) if row[0] == '#':
if len(row)==1: continue
row=["$"+row[0].strip(), row[0]] row = row.strip().split(':',1)
else: if len(row) == 1:
row=[row[0].strip(),row[1]] row = [ "$" + row[0].strip(), row[0] ]
self.entries.append(launch_item(command=row[1], else:
description=row[0], row = [ row[0].strip(), row[1] ]
launcher="menu")) self.entries.append(
launch_item(
command = row[1],
description = row[0],
launcher = "menu"
)
)
def read_folder(self): def read_folder(self):
''' Read folder contents, return executable files and dirs ''' ''' Read folder contents, return executable files and dirs '''
self.dirs.append(launch_item(command='..', self.dirs.append(
description='..', launch_item(
launcher="dir")) command = '..',
dirs=[] description = '..',
executables=[] launcher = "dir"
)
)
dirs = []
executables = []
for f in os.listdir('.'): for f in os.listdir('.'):
if os.path.isfile(f): if os.path.isfile(f):
if os.access(f,os.X_OK): if os.access(f, os.X_OK):
executables.append(f) executables.append(f)
if os.path.isdir(f) and f[0]!='.': if os.path.isdir(f) and f[0] != '.':
dirs.append(f) dirs.append(f)
dirs.sort() dirs.sort()
for d in dirs: for d in dirs:
self.dirs.append(launch_item( self.dirs.append(
command=d, launch_item(
description=d, command = d,
launcher="dir")) description = d,
launcher = "dir"
)
)
if self.options.executables: if self.options.executables:
executables.sort() executables.sort()
for e in executables: for e in executables:
self.entries.append(launch_item( self.entries.append(
command=e, launch_item(
description=e, command = e,
launcher="exec")) description = e,
launcher = "exec"
)
)
def entry_color(self,launcher): def entry_color(self, launcher):
if launcher=="dir": if launcher == "dir":
return self.co.WHI return self.co.WHI
if launcher=="exec": if launcher == "exec":
return self.co.GRE return self.co.GRE
if launcher=="menu": if launcher == "menu":
return self.co.CYA return self.co.CYA
def menu(self): def menu(self):
""" draws the menu at the top of the screen """ """ draws the menu at the top of the screen """
if self.dir_mode: if self.dir_mode:
helptext=".:executables" helptext = "[.]executables"
my_entries=self.dirs my_entries = self.dirs
else: else:
helptext='-:args ('+self.co.END+self.args+self.co.YEL+') .:folders' helptext = '[.]folders [-]args (%s%s%s)'%(
my_entries=self.entries self.co.END,
self.args,
self.co.YEL
)
my_entries = self.entries
maxrows,maxcolumns = termsize() maxrows, maxcolumns = termsize()
rows=maxrows - 5 rows = maxrows - 5
maxcolumns-=10 maxcolumns -= 10
if self.options.columns==0: if self.options.columns == 0:
pars=1 pars = 1
if len(my_entries)>9: if len(my_entries) > 9:
pars=2 pars = 2
if len(my_entries)>30: if len(my_entries) > 30:
pars=3 pars = 3
pars=float(pars) pars = float(pars)
else: else:
pars=float(self.options.columns) pars = float(self.options.columns)
if self.options.banner: if self.options.banner:
b=self.banner banner = self.banner
else: else:
b=[] banner = []
blen=len(b) blen = len(banner)
cwd=os.path.basename(os.getcwd())[0:15] cwd = os.path.basename( os.getcwd() )[0:15]
self.co.posprint(1,3,self.co.END+self.co.CLR+self.co.WHI+cwd+self.co.YEL+' Menu q/x:exit '+helptext+self.co.END)
for i,e in enumerate(b): self.co.posprint(
self.co.posprint(i+2,0,e) 1,
rows=int(math.ceil(len(my_entries)/pars)) 1,
self.co.END + self.co.CLR
)
self.co.posprint(
1,
3,
"%s%s%s [q/x]exit %s%s"%(
self.co.WHI,
cwd,
self.co.YEL,
helptext,
self.co.END
)
)
for i, e in enumerate(banner):
self.co.posprint(
i+2,
0,
e
)
rows = int( math.ceil( len(my_entries) / pars ) )
while rows > maxrows: while rows > maxrows:
pars+=1 pars += 1
rows=int(math.ceil(len(my_entries)/pars)) rows = int( math.ceil( len(my_entries) / pars ) )
maxcolumns=int(math.ceil(maxcolumns/pars)) maxcolumns = int(math.ceil(maxcolumns / pars))
r=1+blen r = 1 + blen
par=1 par = 1
for e,i in zip(my_entries,self.menu_keys): for entry, key in zip(my_entries, self.menu_keys):
if r-blen>rows: if r - blen > rows:
par+=1 par += 1
r=1+blen r = 1 + blen
printline=e.description printline = entry.description
if len(printline)>maxcolumns: if len(printline) > maxcolumns:
printline=printline[:maxcolumns]+"..." printline = printline[:maxcolumns] + "..."
if par==1: if par == 1:
self.co.posprint(r+1,2,self.co.WHI+i+self.co.END+' '+self.entry_color(e.launcher)+printline+self.co.END) column = 2
border = ""
else: else:
self.co.posprint(r+1,maxcolumns*(par-1),'| '+self.co.WHI+i+self.co.END+' '+self.entry_color(e.launcher)+printline+self.co.END) column = maxcolumns * ( par - 1 )
r+=1 border = '| '
self.co.posprint(rows+2+blen,0,"") self.co.posprint(
r+1,
column,
"%s%s%s%s %s%s%s"%(
border,
self.co.WHI,
key,
self.co.END,
self.entry_color(entry.launcher),
printline,
self.co.END
)
)
r += 1
self.co.posprint(
rows + 2 + blen,
0,
"#"
)
def list(self): def list(self):
""" draws the list at cursor """ """ draws the list at cursor """
maxrows,maxcolumns = termsize() maxrows, maxcolumns = termsize()
rows=maxrows-5 rows = maxrows - 5
maxcolumns-=10 maxcolumns -= 10
# heuristics for guessing column count # heuristics for guessing column count
if self.options.columns==0: if self.options.columns == 0:
pars=float(1) pars = 1.0
if len(self.entries)>9: if len(self.entries) > 9:
pars=math.floor(maxcolumns/float(self.max_length)) pars = max(
pars=max(1,pars) 1.0,
if len(self.entries)/pars < pars: math.floor(
while len(self.entries)/pars < pars: maxcolumns / float(self.max_length)
pars-=1 )
)
while len(self.entries) / pars < pars:
pars -= 1
else: else:
pars=float(self.options.columns) pars = float(self.options.columns)
rows=int(math.ceil(len(self.entries)/float(pars)))
maxcolumns=int(math.floor(maxcolumns/pars))-2
# If names won't fit the columns, make sure at least 3 characters are visible
if maxcolumns<6:
origmaxrows,origmaxcolumns = termsize()
origmaxrows-=5
origmaxcolumns-=10
while maxcolumns<6:
pars=pars-1
rows=int(math.ceil(len(self.entries)/float(pars)))
maxcolumns=int(math.floor(origmaxcolumns/pars))-2
self.max_length=min(maxcolumns,self.max_length) rows = int(math.ceil( len(self.entries) / float(pars) ))
maxcolumns = int(math.floor(maxcolumns / pars)) - 2
# If names won't fit the columns, make sure at least 3 characters are visible
if maxcolumns < 6:
origmaxrows, origmaxcolumns = termsize()
origmaxrows -= 5
origmaxcolumns -= 10
while maxcolumns < 6:
pars -= 1
rows = int(math.ceil( len(self.entries) / float(pars) ))
maxcolumns = int(math.floor( origmaxcolumns / pars )) - 2
self.max_length = min(maxcolumns, self.max_length)
if self.options.horizontal: if self.options.horizontal:
foo=pars pars, rows = rows, pars
pars=rows formatted = []
rows=foo
formatted=[]
for r in range(int(rows)): for r in range(int(rows)):
formatted.append([]) formatted.append([])
for p in range(int(pars)): for p in range(int(pars)):
formatted[r].append(' '*(self.max_length)) formatted[r].append(' '*(self.max_length))
if self.options.horizontal: if self.options.horizontal:
formatted[r][p]+=' ' formatted[r][p] += ' '
r=0 r = 0
par=0 par = 0
for e,i in zip(self.entries,self.menu_keys): for entry,key in zip(self.entries, self.menu_keys):
if r>=rows: if r >= rows:
par=1+par par += 1
r=0 r = 0
printline=e.description[:(maxcolumns-3)] printline = entry.description[:(maxcolumns-3)]
printline=printline+' '*(self.max_length-len(printline)-1) printline += ' '*(self.max_length-len(printline)-1)
formatted[r][par]=self.co.WHI+i+self.co.END+' '+self.entry_color(e.launcher)+printline+self.co.END formatted[r][par]="%s%s%s %s%s%s"%(
r=1+r self.co.WHI,
key,
self.co.END,
self.entry_color(entry.launcher),
printline,
self.co.END
)
r += 1
if self.options.horizontal: if self.options.horizontal:
# let's shuffle the deck, and print values in horizontal order: # let's shuffle the deck, and print values in horizontal order:
formatted=zip(*formatted) formatted = zip(*formatted)
if self.options.banner: if self.options.banner:
if self.banner: if self.banner:
print("\n".join(self.banner)) print("\n".join(self.banner))
@@ -322,70 +386,76 @@ class entry_collection:
def launch(self,key): def launch(self,key):
''' launch the given entry ''' ''' launch the given entry '''
bg=False bg = False
wait=True idx = self.menu_keys.index(key)
#Run the program in background
idx=self.menu_keys.index(key)
# note, no error checking here # note, no error checking here
if self.dir_mode: if self.dir_mode:
command_str=self.dirs[idx].command command_str = self.dirs[idx].command
os.chdir(command_str) os.chdir(command_str)
return return
# continue here if not changing folders # continue here if not changing folders
command_str=self.entries[idx].command command_str = self.entries[idx].command
if command_str[-1]=='&': if command_str[-1] == '&':
command_str=command_str[:-1] #Run the program in background
bg=True command_str = command_str[:-1]
if len(self.args)>0: bg = True
command_str=command_str+" "+self.args if len(self.args) > 0:
if self.entries[idx].launcher=='exec': command_str += ' ' + self.args
command_str='./'+command_str if self.entries[idx].launcher == 'exec':
command_str = './' + command_str
if not self.options.command: if not self.options.command:
print('#$ '+command_str) print(command_str)
try: try:
if bg: if bg:
subprocess.Popen(command_str, stderr=subprocess.PIPE, shell=True,executable="/bin/bash") subprocess.Popen(
command_str,
stderr = subprocess.PIPE,
shell=True,
executable="/bin/bash"
)
else: else:
subprocess.call(command_str, stderr=subprocess.STDOUT, shell=True,executable="/bin/bash") subprocess.call(
command_str,
stderr = subprocess.STDOUT,
shell = True,
executable = "/bin/bash"
)
except: except:
print('Non-zero exit code: "'+command_str+'"') print('Non-zero exit code: "' + command_str + '"')
if (self.options.command or self.options.once or bg): if not (self.options.command or self.options.once or bg):
wait=False
if wait:
print('Press any key...') print('Press any key...')
ch=getch() ch=getch()
inkey=ord(ch.get()) inkey=ord(ch.get())
def flip_mode(self): def flip_mode(self):
self.dir_mode=not self.dir_mode self.dir_mode = not self.dir_mode
def is_key(self,key): def is_key(self, key):
if self.dir_mode: if self.dir_mode:
my_len=len(self.dirs) my_len = len(self.dirs)
else: else:
my_len=len(self.entries) my_len = len(self.entries)
try: try:
idx=self.menu_keys.index(key) idx = self.menu_keys.index(key)
except ValueError: except ValueError:
return (False,'Not a possible key') return (False, 'Not a possible key')
if idx+1>my_len: if idx + 1 > my_len:
return (False,'No such entry') return (False, 'No such entry')
return (True,'') return (True, '')
def start_engines(): def start_engines():
options=setup_options() options = setup_options()
entries=entry_collection(options) entries = entry_collection(options)
if options.list: if options.list:
entries.list() entries.list()
if not options.command: if not options.command:
sys.exit(0) sys.exit(0)
if options.command: if options.command:
found,message=entries.is_key(options.command) found, message = entries.is_key(options.command)
if not found: if not found:
print(message) print(message)
sys.exit(1) sys.exit(1)
@@ -393,28 +463,30 @@ def start_engines():
entries.launch(options.command) entries.launch(options.command)
sys.exit(0) sys.exit(0)
ch=getch() ch = getch()
while True: while True:
entries.menu() entries.menu()
inkey=ord(ch.get()) inkey = ord(ch.get())
#print('-'+str((inkey))+'-') #print('-'+str((inkey))+'-')
if inkey in [113,120,27,3,24,4]: if inkey in (113, 120, 27, 3, 24, 4): # esc, q, x
print('Exited in: '+os.getcwd()) print('Exited in: ' + os.getcwd())
sys.exit(0) sys.exit(0)
if inkey==45: # - if inkey == 45: # -
print('')
readline.set_startup_hook(lambda: readline.insert_text(entries.args)) readline.set_startup_hook(lambda: readline.insert_text(entries.args))
args=raw_input('args: ') args = raw_input('args: ')
entries.set_args(args) entries.set_args(args)
readline.set_startup_hook(None) readline.set_startup_hook(None)
if inkey==46: # . if inkey == 46: # .
entries.flip_mode() entries.flip_mode()
found,message=entries.is_key(chr(inkey)) found, message = entries.is_key(chr(inkey))
if found: if found:
entries.launch(chr(inkey)) entries.launch(chr(inkey))
if options.once and not entries.dir_mode: if options.once and not entries.dir_mode:
sys.exit(0) sys.exit(0)
entries.initialize() entries.initialize()
start_engines() if __name__ == "__main__":
start_engines()