#!/usr/bin/python import os import sys import subprocess import termios import tty import readline import math readline.parse_and_bind('tab: complete') readline.parse_and_bind('set editing-mode vi') MENUFILE='.foldermenu' def termsize(): rows, columns = os.popen('stty size', 'r').read().split() return (int(rows),int(columns)) class bc: MAG = '\033[95m' BLU = '\033[94m' GRE = '\033[92m' YEL = '\033[93m' RED = '\033[91m' CYA = '\033[96m' WHI = '\033[1m' END = '\033[0m' CLR = '\033[2J' def disable(self): self.MAG = '' self.BLU = '' self.GRE = '' self.YEL = '' self.RED = '' self.END = '' self.CLR = '' self.CYA = '' self.WHI = '' def pos(self,y,x): return "\033["+str(y)+";"+str(x)+"H" class getch: def __init__(self): import sys, tty, termios def get(self): 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 def read_menu(): ''' Read menu file ''' entries=[] if os.path.exists(MENUFILE): f=file(MENUFILE,'r') for row in f: if row.strip()=='': continue if row[0]=='#': continue row=row.strip().split(':',1) if len(row)==1: row=[row[0], row[0]] else: row=[row[0].strip()+' ('+row[1]+')', row[1]] entries.append(row) return entries def read_folder(): ''' Read folder contents, return executable files and dirs ''' dirs=[] dirs.append(['..','..']) executables=[] for f in os.listdir('.'): if os.path.isfile(f): if os.access(f,os.X_OK): executables.append([f,f]) if os.path.isdir(f) and f[0]!='.': dirs.append([f,f]) dirs.sort(key=lambda x: x[0]) executables.sort(key=lambda x: x[0]) return (executables,dirs) def print_help(): if not os.path.exists(MENUFILE): print('Consider having a '+MENUFILE+' file containing shell commands / line.') print('Command may be of format "My Description: my_command" or simply "my_command -switch"') def ichr(i): ''' convert integer to 1-9, a-z, A-Z, omitting x ''' if i < 10: return str(i) i=i + 87 if i>119: i=i+1 if i>122: i=i-122+64 return chr(i) def drawmenu(entries,dir_mode,args=""): maxrows,maxcolumns = termsize() maxrows-=5 maxcolumns-=10 twocol=False co=bc() if dir_mode: helptext=".:execs" else: helptext='-:args ('+co.END+args+co.YEL+') .:folders' print(co.END+co.CLR+co.pos(1,3)+co.YEL+'FolderMenu x:exit '+helptext+co.END) if len(entries)>10: twocol=True maxrows=int(math.ceil(min(maxrows/2.0, len(entries)/2.0))) maxcolumns=int(math.ceil(maxcolumns/2.0)) r=1 for e in range(len(entries)): if r>maxrows: break printline=entries[e][1] if len(printline)>maxcolumns: printline=printline[:maxcolumns]+"..." print(co.WHI+entries[e][0]+co.END+' '+entries[e][3]+printline+co.END) r=1+r if twocol: r=1 for e in range(e,len(entries)): if r>maxrows: break printline=entries[e][1] if len(printline)>maxcolumns: printline=printline[:maxcolumns]+"..." print(co.pos(r+1,maxcolumns)+'| '+co.WHI+entries[e][0]+co.END+' '+entries[e][3]+printline+co.END) r=1+r print(co.pos(maxrows+2,0)) def append_index(entries,offset=0,color=None,t='menu'): e=1+offset for el in range(len(entries)): entries[el]=[ichr(e), entries[el][0], entries[el][1], color,t] e=e+1 return entries def launch(key,entries,args=""): ''' launch the given program ''' bg=False idx=[i for i in range(len(entries)) if entries[i][0]==key][0] command_str=entries[idx][2] if command_str[-1]=='&': command_str=command_str[:-1] bg=True if len(args)>0: command_str=command_str+" "+args if entries[idx][4]=='exec': command_str='./'+command_str if entries[idx][4]=='dir': os.chdir(command_str) return try: print('#$ '+command_str) if bg: subprocess.Popen(command_str, stderr=subprocess.PIPE, shell=True) else: subprocess.call(command_str, stderr=subprocess.STDOUT, shell=True) except: print('Unable to run: "'+command_str+'"') print('Press any key...') ch=getch() inkey=ord(ch.get()) def initialize(): entries=read_menu() entries=append_index(entries, color=bc.CYA,t='menu') [execs,dirs]=read_folder() execs=append_index(execs, offset=len(entries), color=bc.GRE,t='exec') entries.extend(execs) dirs=append_index(dirs,color=bc.BLU+bc.WHI,t='dir') return (entries,dirs) def main(): [entries,dirs]=initialize() show_entries=entries dir_mode=False ch=getch() args="" drawmenu(show_entries,dir_mode,args) while True: inkey=ord(ch.get()) #print('-'+str((inkey))+'-') if inkey in [120,27,3,24,4]: print_help() print('Exited in: '+os.getcwd()) sys.exit(0) if inkey==45: # - readline.set_startup_hook(lambda: readline.insert_text(args)) args=raw_input('args: ') readline.set_startup_hook(None) if inkey==46: # . dir_mode = not dir_mode if chr(inkey) in [x[0] for x in show_entries]: launch(chr(inkey),show_entries,args) [entries,dirs]=initialize() if dir_mode: show_entries=dirs else: show_entries=entries drawmenu(show_entries,dir_mode,args) main()